Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 338810
b: refs/heads/master
c: b637a32
h: refs/heads/master
v: v3
  • Loading branch information
Paul E. McKenney authored and Paul E. McKenney committed Oct 23, 2012
1 parent 77a8303 commit 64cb781
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 46 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cda4dc813071e6cb04944c5a140610bd06acd295
refs/heads/master: b637a328bd4f43a0e146d1eef0142b650ba0d644
2 changes: 2 additions & 0 deletions trunk/include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ extern void update_cpu_load_nohz(void);

extern unsigned long get_parent_ip(unsigned long addr);

extern void dump_cpu_task(int cpu);

struct seq_file;
struct cfs_rq;
struct task_group;
Expand Down
34 changes: 0 additions & 34 deletions trunk/include/linux/srcu.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Copyright (C) IBM Corporation, 2006
* Copyright (C) Fujitsu, 2012
*
* Author: Paul McKenney <paulmck@us.ibm.com>
* Lai Jiangshan <laijs@cn.fujitsu.com>
*
* For detailed explanation of Read-Copy Update mechanism see -
* Documentation/RCU/ *.txt
Expand All @@ -42,8 +40,6 @@ struct rcu_batch {
struct rcu_head *head, **tail;
};

#define RCU_BATCH_INIT(name) { NULL, &(name.head) }

struct srcu_struct {
unsigned completed;
struct srcu_struct_array __percpu *per_cpu_ref;
Expand Down Expand Up @@ -74,42 +70,12 @@ int __init_srcu_struct(struct srcu_struct *sp, const char *name,
__init_srcu_struct((sp), #sp, &__srcu_key); \
})

#define __SRCU_DEP_MAP_INIT(srcu_name) .dep_map = { .name = #srcu_name },
#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */

int init_srcu_struct(struct srcu_struct *sp);

#define __SRCU_DEP_MAP_INIT(srcu_name)
#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */

void process_srcu(struct work_struct *work);

#define __SRCU_STRUCT_INIT(name) \
{ \
.completed = -300, \
.per_cpu_ref = &name##_srcu_array, \
.queue_lock = __SPIN_LOCK_UNLOCKED(name.queue_lock), \
.running = false, \
.batch_queue = RCU_BATCH_INIT(name.batch_queue), \
.batch_check0 = RCU_BATCH_INIT(name.batch_check0), \
.batch_check1 = RCU_BATCH_INIT(name.batch_check1), \
.batch_done = RCU_BATCH_INIT(name.batch_done), \
.work = __DELAYED_WORK_INITIALIZER(name.work, process_srcu, 0),\
__SRCU_DEP_MAP_INIT(name) \
}

/*
* define and init a srcu struct at build time.
* dont't call init_srcu_struct() nor cleanup_srcu_struct() on it.
*/
#define DEFINE_SRCU(name) \
static DEFINE_PER_CPU(struct srcu_struct_array, name##_srcu_array);\
struct srcu_struct name = __SRCU_STRUCT_INIT(name);

#define DEFINE_STATIC_SRCU(name) \
static DEFINE_PER_CPU(struct srcu_struct_array, name##_srcu_array);\
static struct srcu_struct name = __SRCU_STRUCT_INIT(name);

/**
* call_srcu() - Queue a callback for invocation after an SRCU grace period
* @sp: srcu_struct in queue the callback
Expand Down
41 changes: 35 additions & 6 deletions trunk/kernel/rcutorture.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ rcu_stutter_wait(char *title)

struct rcu_torture_ops {
void (*init)(void);
void (*cleanup)(void);
int (*readlock)(void);
void (*read_delay)(struct rcu_random_state *rrsp);
void (*readunlock)(int idx);
Expand Down Expand Up @@ -430,6 +431,7 @@ static void rcu_torture_deferred_free(struct rcu_torture *p)

static struct rcu_torture_ops rcu_ops = {
.init = NULL,
.cleanup = NULL,
.readlock = rcu_torture_read_lock,
.read_delay = rcu_read_delay,
.readunlock = rcu_torture_read_unlock,
Expand Down Expand Up @@ -473,6 +475,7 @@ static void rcu_sync_torture_init(void)

static struct rcu_torture_ops rcu_sync_ops = {
.init = rcu_sync_torture_init,
.cleanup = NULL,
.readlock = rcu_torture_read_lock,
.read_delay = rcu_read_delay,
.readunlock = rcu_torture_read_unlock,
Expand All @@ -490,6 +493,7 @@ static struct rcu_torture_ops rcu_sync_ops = {

static struct rcu_torture_ops rcu_expedited_ops = {
.init = rcu_sync_torture_init,
.cleanup = NULL,
.readlock = rcu_torture_read_lock,
.read_delay = rcu_read_delay, /* just reuse rcu's version. */
.readunlock = rcu_torture_read_unlock,
Expand Down Expand Up @@ -532,6 +536,7 @@ static void rcu_bh_torture_deferred_free(struct rcu_torture *p)

static struct rcu_torture_ops rcu_bh_ops = {
.init = NULL,
.cleanup = NULL,
.readlock = rcu_bh_torture_read_lock,
.read_delay = rcu_read_delay, /* just reuse rcu's version. */
.readunlock = rcu_bh_torture_read_unlock,
Expand All @@ -548,6 +553,7 @@ static struct rcu_torture_ops rcu_bh_ops = {

static struct rcu_torture_ops rcu_bh_sync_ops = {
.init = rcu_sync_torture_init,
.cleanup = NULL,
.readlock = rcu_bh_torture_read_lock,
.read_delay = rcu_read_delay, /* just reuse rcu's version. */
.readunlock = rcu_bh_torture_read_unlock,
Expand All @@ -564,6 +570,7 @@ static struct rcu_torture_ops rcu_bh_sync_ops = {

static struct rcu_torture_ops rcu_bh_expedited_ops = {
.init = rcu_sync_torture_init,
.cleanup = NULL,
.readlock = rcu_bh_torture_read_lock,
.read_delay = rcu_read_delay, /* just reuse rcu's version. */
.readunlock = rcu_bh_torture_read_unlock,
Expand All @@ -582,7 +589,19 @@ static struct rcu_torture_ops rcu_bh_expedited_ops = {
* Definitions for srcu torture testing.
*/

DEFINE_STATIC_SRCU(srcu_ctl);
static struct srcu_struct srcu_ctl;

static void srcu_torture_init(void)
{
init_srcu_struct(&srcu_ctl);
rcu_sync_torture_init();
}

static void srcu_torture_cleanup(void)
{
synchronize_srcu(&srcu_ctl);
cleanup_srcu_struct(&srcu_ctl);
}

static int srcu_torture_read_lock(void) __acquires(&srcu_ctl)
{
Expand Down Expand Up @@ -653,7 +672,8 @@ static int srcu_torture_stats(char *page)
}

static struct rcu_torture_ops srcu_ops = {
.init = rcu_sync_torture_init,
.init = srcu_torture_init,
.cleanup = srcu_torture_cleanup,
.readlock = srcu_torture_read_lock,
.read_delay = srcu_read_delay,
.readunlock = srcu_torture_read_unlock,
Expand All @@ -667,7 +687,8 @@ static struct rcu_torture_ops srcu_ops = {
};

static struct rcu_torture_ops srcu_sync_ops = {
.init = rcu_sync_torture_init,
.init = srcu_torture_init,
.cleanup = srcu_torture_cleanup,
.readlock = srcu_torture_read_lock,
.read_delay = srcu_read_delay,
.readunlock = srcu_torture_read_unlock,
Expand All @@ -691,7 +712,8 @@ static void srcu_torture_read_unlock_raw(int idx) __releases(&srcu_ctl)
}

static struct rcu_torture_ops srcu_raw_ops = {
.init = rcu_sync_torture_init,
.init = srcu_torture_init,
.cleanup = srcu_torture_cleanup,
.readlock = srcu_torture_read_lock_raw,
.read_delay = srcu_read_delay,
.readunlock = srcu_torture_read_unlock_raw,
Expand All @@ -705,7 +727,8 @@ static struct rcu_torture_ops srcu_raw_ops = {
};

static struct rcu_torture_ops srcu_raw_sync_ops = {
.init = rcu_sync_torture_init,
.init = srcu_torture_init,
.cleanup = srcu_torture_cleanup,
.readlock = srcu_torture_read_lock_raw,
.read_delay = srcu_read_delay,
.readunlock = srcu_torture_read_unlock_raw,
Expand All @@ -724,7 +747,8 @@ static void srcu_torture_synchronize_expedited(void)
}

static struct rcu_torture_ops srcu_expedited_ops = {
.init = rcu_sync_torture_init,
.init = srcu_torture_init,
.cleanup = srcu_torture_cleanup,
.readlock = srcu_torture_read_lock,
.read_delay = srcu_read_delay,
.readunlock = srcu_torture_read_unlock,
Expand Down Expand Up @@ -759,6 +783,7 @@ static void rcu_sched_torture_deferred_free(struct rcu_torture *p)

static struct rcu_torture_ops sched_ops = {
.init = rcu_sync_torture_init,
.cleanup = NULL,
.readlock = sched_torture_read_lock,
.read_delay = rcu_read_delay, /* just reuse rcu's version. */
.readunlock = sched_torture_read_unlock,
Expand All @@ -774,6 +799,7 @@ static struct rcu_torture_ops sched_ops = {

static struct rcu_torture_ops sched_sync_ops = {
.init = rcu_sync_torture_init,
.cleanup = NULL,
.readlock = sched_torture_read_lock,
.read_delay = rcu_read_delay, /* just reuse rcu's version. */
.readunlock = sched_torture_read_unlock,
Expand All @@ -788,6 +814,7 @@ static struct rcu_torture_ops sched_sync_ops = {

static struct rcu_torture_ops sched_expedited_ops = {
.init = rcu_sync_torture_init,
.cleanup = NULL,
.readlock = sched_torture_read_lock,
.read_delay = rcu_read_delay, /* just reuse rcu's version. */
.readunlock = sched_torture_read_unlock,
Expand Down Expand Up @@ -1909,6 +1936,8 @@ rcu_torture_cleanup(void)

rcu_torture_stats_print(); /* -After- the stats thread is stopped! */

if (cur_ops->cleanup)
cur_ops->cleanup();
if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
else if (n_online_successes != n_online_attempts ||
Expand Down
25 changes: 24 additions & 1 deletion trunk/kernel/rcutree.c
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,29 @@ static void record_gp_stall_check_time(struct rcu_state *rsp)
rsp->jiffies_stall = jiffies + jiffies_till_stall_check();
}

/*
* Dump stacks of all tasks running on stalled CPUs. This is a fallback
* for architectures that do not implement trigger_all_cpu_backtrace().
* The NMI-triggered stack traces are more accurate because they are
* printed by the target CPU.
*/
static void rcu_dump_cpu_stacks(struct rcu_state *rsp)
{
int cpu;
unsigned long flags;
struct rcu_node *rnp;

rcu_for_each_leaf_node(rsp, rnp) {
raw_spin_lock_irqsave(&rnp->lock, flags);
if (rnp->qsmask != 0) {
for (cpu = 0; cpu <= rnp->grphi - rnp->grplo; cpu++)
if (rnp->qsmask & (1UL << cpu))
dump_cpu_task(rnp->grplo + cpu);
}
raw_spin_unlock_irqrestore(&rnp->lock, flags);
}
}

static void print_other_cpu_stall(struct rcu_state *rsp)
{
int cpu;
Expand Down Expand Up @@ -929,7 +952,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
if (ndetected == 0)
printk(KERN_ERR "INFO: Stall ended before state dump start\n");
else if (!trigger_all_cpu_backtrace())
dump_stack();
rcu_dump_cpu_stacks(rsp);

/* Complain about tasks blocking the grace period. */

Expand Down
6 changes: 6 additions & 0 deletions trunk/kernel/sched/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -8076,3 +8076,9 @@ struct cgroup_subsys cpuacct_subsys = {
.base_cftypes = files,
};
#endif /* CONFIG_CGROUP_CPUACCT */

void dump_cpu_task(int cpu)
{
pr_info("Task dump for CPU %d:\n", cpu);
sched_show_task(cpu_curr(cpu));
}
8 changes: 4 additions & 4 deletions trunk/kernel/srcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Copyright (C) IBM Corporation, 2006
* Copyright (C) Fujitsu, 2012
*
* Author: Paul McKenney <paulmck@us.ibm.com>
* Lai Jiangshan <laijs@cn.fujitsu.com>
*
* For detailed explanation of Read-Copy Update mechanism see -
* Documentation/RCU/ *.txt
Expand Down Expand Up @@ -94,6 +92,9 @@ static inline void rcu_batch_move(struct rcu_batch *to, struct rcu_batch *from)
}
}

/* single-thread state-machine */
static void process_srcu(struct work_struct *work);

static int init_srcu_struct_fields(struct srcu_struct *sp)
{
sp->completed = 0;
Expand Down Expand Up @@ -636,7 +637,7 @@ static void srcu_reschedule(struct srcu_struct *sp)
/*
* This is the work-queue function that handles SRCU grace periods.
*/
void process_srcu(struct work_struct *work)
static void process_srcu(struct work_struct *work)
{
struct srcu_struct *sp;

Expand All @@ -647,4 +648,3 @@ void process_srcu(struct work_struct *work)
srcu_invoke_callbacks(sp);
srcu_reschedule(sp);
}
EXPORT_SYMBOL_GPL(process_srcu);

0 comments on commit 64cb781

Please sign in to comment.