aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2009-08-15 12:53:46 -0400
committerIngo Molnar <mingo@elte.hu>2009-08-15 13:02:07 -0400
commit27569620c748ec13f801b4683b448a2ac2adaae4 (patch)
treed5fd5dd1b9d352ca0ef2cf224f7141338d3413f3
parentfa08661af834875c9bd6f7f0b1b9388dc72a6585 (diff)
rcu: Split hierarchical RCU initialization into boot-time and CPU-online pieces
This patch divides the rcutree initialization into boot-time and hotplug-time components, so that the tree data structures are guaranteed to be fully linked at boot time regardless of what might happen in CPU hotplug operations. This makes RCU more resilient against CPU hotplug misbehavior (and vice versa), but more importantly, does a better job of compartmentalizing the code. Reported-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: laijs@cn.fujitsu.com Cc: dipankar@in.ibm.com Cc: josht@linux.vnet.ibm.com Cc: akpm@linux-foundation.org Cc: mathieu.desnoyers@polymtl.ca Cc: dvhltc@us.ibm.com Cc: niv@us.ibm.com Cc: peterz@infradead.org Cc: rostedt@goodmis.org Cc: hugh.dickins@tiscali.co.uk Cc: benh@kernel.crashing.org LKML-Reference: <1250355231152-git-send-email-> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--kernel/rcutree.c53
1 files changed, 33 insertions, 20 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 7717b95c2027..f3e43274ed53 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -1325,22 +1325,40 @@ int rcu_needs_cpu(int cpu)
1325} 1325}
1326 1326
1327/* 1327/*
1328 * Initialize a CPU's per-CPU RCU data. We take this "scorched earth" 1328 * Do boot-time initialization of a CPU's per-CPU RCU data.
1329 * approach so that we don't have to worry about how long the CPU has 1329 */
1330 * been gone, or whether it ever was online previously. We do trust the 1330static void __init
1331 * ->mynode field, as it is constant for a given struct rcu_data and 1331rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
1332 * initialized during early boot. 1332{
1333 * 1333 unsigned long flags;
1334 * Note that only one online or offline event can be happening at a given 1334 int i;
1335 * time. Note also that we can accept some slop in the rsp->completed 1335 struct rcu_data *rdp = rsp->rda[cpu];
1336 * access due to the fact that this CPU cannot possibly have any RCU 1336 struct rcu_node *rnp = rcu_get_root(rsp);
1337 * callbacks in flight yet. 1337
1338 /* Set up local state, ensuring consistent view of global state. */
1339 spin_lock_irqsave(&rnp->lock, flags);
1340 rdp->grpmask = 1UL << (cpu - rdp->mynode->grplo);
1341 rdp->nxtlist = NULL;
1342 for (i = 0; i < RCU_NEXT_SIZE; i++)
1343 rdp->nxttail[i] = &rdp->nxtlist;
1344 rdp->qlen = 0;
1345#ifdef CONFIG_NO_HZ
1346 rdp->dynticks = &per_cpu(rcu_dynticks, cpu);
1347#endif /* #ifdef CONFIG_NO_HZ */
1348 rdp->cpu = cpu;
1349 spin_unlock_irqrestore(&rnp->lock, flags);
1350}
1351
1352/*
1353 * Initialize a CPU's per-CPU RCU data. Note that only one online or
1354 * offline event can be happening at a given time. Note also that we
1355 * can accept some slop in the rsp->completed access due to the fact
1356 * that this CPU cannot possibly have any RCU callbacks in flight yet.
1338 */ 1357 */
1339static void __cpuinit 1358static void __cpuinit
1340rcu_init_percpu_data(int cpu, struct rcu_state *rsp) 1359rcu_init_percpu_data(int cpu, struct rcu_state *rsp)
1341{ 1360{
1342 unsigned long flags; 1361 unsigned long flags;
1343 int i;
1344 long lastcomp; 1362 long lastcomp;
1345 unsigned long mask; 1363 unsigned long mask;
1346 struct rcu_data *rdp = rsp->rda[cpu]; 1364 struct rcu_data *rdp = rsp->rda[cpu];
@@ -1355,16 +1373,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp)
1355 rdp->qs_pending = 1; /* so set up to respond to current GP. */ 1373 rdp->qs_pending = 1; /* so set up to respond to current GP. */
1356 rdp->beenonline = 1; /* We have now been online. */ 1374 rdp->beenonline = 1; /* We have now been online. */
1357 rdp->passed_quiesc_completed = lastcomp - 1; 1375 rdp->passed_quiesc_completed = lastcomp - 1;
1358 rdp->grpmask = 1UL << (cpu - rdp->mynode->grplo);
1359 rdp->nxtlist = NULL;
1360 for (i = 0; i < RCU_NEXT_SIZE; i++)
1361 rdp->nxttail[i] = &rdp->nxtlist;
1362 rdp->qlen = 0;
1363 rdp->blimit = blimit; 1376 rdp->blimit = blimit;
1364#ifdef CONFIG_NO_HZ
1365 rdp->dynticks = &per_cpu(rcu_dynticks, cpu);
1366#endif /* #ifdef CONFIG_NO_HZ */
1367 rdp->cpu = cpu;
1368 spin_unlock(&rnp->lock); /* irqs remain disabled. */ 1377 spin_unlock(&rnp->lock); /* irqs remain disabled. */
1369 1378
1370 /* 1379 /*
@@ -1539,8 +1548,12 @@ void __init __rcu_init(void)
1539#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ 1548#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
1540 rcu_init_one(&rcu_state); 1549 rcu_init_one(&rcu_state);
1541 RCU_DATA_PTR_INIT(&rcu_state, rcu_data); 1550 RCU_DATA_PTR_INIT(&rcu_state, rcu_data);
1551 for_each_possible_cpu(i)
1552 rcu_boot_init_percpu_data(i, &rcu_state);
1542 rcu_init_one(&rcu_bh_state); 1553 rcu_init_one(&rcu_bh_state);
1543 RCU_DATA_PTR_INIT(&rcu_bh_state, rcu_bh_data); 1554 RCU_DATA_PTR_INIT(&rcu_bh_state, rcu_bh_data);
1555 for_each_possible_cpu(i)
1556 rcu_boot_init_percpu_data(i, &rcu_bh_state);
1544 1557
1545 for_each_online_cpu(i) 1558 for_each_online_cpu(i)
1546 rcu_cpu_notify(&rcu_nb, CPU_UP_PREPARE, (void *)(long)i); 1559 rcu_cpu_notify(&rcu_nb, CPU_UP_PREPARE, (void *)(long)i);