Commit 62ab7072476ae1600e877cc62b43758e485f4f1e

Authored by Paul E. McKenney
Committed by Thomas Gleixner
1 parent bcd951cf10

rcu: Use smp_hotplug_thread facility for RCUs per-CPU kthread

Bring RCU into the new-age CPU-hotplug fold by modifying RCU's per-CPU
kthread code to use the new smp_hotplug_thread facility.

[ tglx: Adapted it to use callbacks and to the simplified rcu yield ]

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/r/20120716103948.673354828@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Showing 4 changed files with 41 additions and 177 deletions Side-by-side Diff

... ... @@ -133,7 +133,6 @@
133 133 */
134 134 static DEFINE_PER_CPU(struct task_struct *, rcu_cpu_kthread_task);
135 135 DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_status);
136   -DEFINE_PER_CPU(int, rcu_cpu_kthread_cpu);
137 136 DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_loops);
138 137 DEFINE_PER_CPU(char, rcu_cpu_has_work);
139 138  
... ... @@ -1468,7 +1467,6 @@
1468 1467 struct rcu_node *rnp = rdp->mynode; /* Outgoing CPU's rdp & rnp. */
1469 1468  
1470 1469 /* Adjust any no-longer-needed kthreads. */
1471   - rcu_stop_cpu_kthread(cpu);
1472 1470 rcu_boost_kthread_setaffinity(rnp, -1);
1473 1471  
1474 1472 /* Remove the dead CPU from the bitmasks in the rcu_node hierarchy. */
1475 1473  
... ... @@ -2595,11 +2593,9 @@
2595 2593 case CPU_ONLINE:
2596 2594 case CPU_DOWN_FAILED:
2597 2595 rcu_boost_kthread_setaffinity(rnp, -1);
2598   - rcu_cpu_kthread_setrt(cpu, 1);
2599 2596 break;
2600 2597 case CPU_DOWN_PREPARE:
2601 2598 rcu_boost_kthread_setaffinity(rnp, cpu);
2602   - rcu_cpu_kthread_setrt(cpu, 0);
2603 2599 break;
2604 2600 case CPU_DYING:
2605 2601 case CPU_DYING_FROZEN:
... ... @@ -196,12 +196,6 @@
196 196 /* Refused to boost: not sure why, though. */
197 197 /* This can happen due to race conditions. */
198 198 #endif /* #ifdef CONFIG_RCU_BOOST */
199   - struct task_struct *node_kthread_task;
200   - /* kthread that takes care of this rcu_node */
201   - /* structure, for example, awakening the */
202   - /* per-CPU kthreads as needed. */
203   - unsigned int node_kthread_status;
204   - /* State of node_kthread_task for tracing. */
205 199 } ____cacheline_internodealigned_in_smp;
206 200  
207 201 /*
... ... @@ -468,7 +462,6 @@
468 462 #ifdef CONFIG_HOTPLUG_CPU
469 463 static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp,
470 464 unsigned long flags);
471   -static void rcu_stop_cpu_kthread(int cpu);
472 465 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
473 466 static void rcu_print_detail_task_stall(struct rcu_state *rsp);
474 467 static int rcu_print_task_stall(struct rcu_node *rnp);
... ... @@ -494,7 +487,6 @@
494 487 static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
495 488 struct rcu_node *rnp);
496 489 #endif /* #ifdef CONFIG_RCU_BOOST */
497   -static void rcu_cpu_kthread_setrt(int cpu, int to_rt);
498 490 static void __cpuinit rcu_prepare_kthreads(int cpu);
499 491 static void rcu_prepare_for_idle_init(int cpu);
500 492 static void rcu_cleanup_after_idle(int cpu);
kernel/rcutree_plugin.h
... ... @@ -25,6 +25,7 @@
25 25 */
26 26  
27 27 #include <linux/delay.h>
  28 +#include <linux/smpboot.h>
28 29  
29 30 #define RCU_KTHREAD_PRIO 1
30 31  
... ... @@ -1292,25 +1293,6 @@
1292 1293 return 0;
1293 1294 }
1294 1295  
1295   -#ifdef CONFIG_HOTPLUG_CPU
1296   -
1297   -/*
1298   - * Stop the RCU's per-CPU kthread when its CPU goes offline,.
1299   - */
1300   -static void rcu_stop_cpu_kthread(int cpu)
1301   -{
1302   - struct task_struct *t;
1303   -
1304   - /* Stop the CPU's kthread. */
1305   - t = per_cpu(rcu_cpu_kthread_task, cpu);
1306   - if (t != NULL) {
1307   - per_cpu(rcu_cpu_kthread_task, cpu) = NULL;
1308   - kthread_stop(t);
1309   - }
1310   -}
1311   -
1312   -#endif /* #ifdef CONFIG_HOTPLUG_CPU */
1313   -
1314 1296 static void rcu_kthread_do_work(void)
1315 1297 {
1316 1298 rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data));
1317 1299  
1318 1300  
1319 1301  
1320 1302  
1321 1303  
1322 1304  
1323 1305  
1324 1306  
1325 1307  
1326 1308  
1327 1309  
1328 1310  
1329 1311  
1330 1312  
1331 1313  
... ... @@ -1318,159 +1300,61 @@
1318 1300 rcu_preempt_do_callbacks();
1319 1301 }
1320 1302  
1321   -/*
1322   - * Set the specified CPU's kthread to run RT or not, as specified by
1323   - * the to_rt argument. The CPU-hotplug locks are held, so the task
1324   - * is not going away.
1325   - */
1326   -static void rcu_cpu_kthread_setrt(int cpu, int to_rt)
  1303 +static void rcu_cpu_kthread_setup(unsigned int cpu)
1327 1304 {
1328   - int policy;
1329 1305 struct sched_param sp;
1330   - struct task_struct *t;
1331 1306  
1332   - t = per_cpu(rcu_cpu_kthread_task, cpu);
1333   - if (t == NULL)
1334   - return;
1335   - if (to_rt) {
1336   - policy = SCHED_FIFO;
1337   - sp.sched_priority = RCU_KTHREAD_PRIO;
1338   - } else {
1339   - policy = SCHED_NORMAL;
1340   - sp.sched_priority = 0;
1341   - }
1342   - sched_setscheduler_nocheck(t, policy, &sp);
  1307 + sp.sched_priority = RCU_KTHREAD_PRIO;
  1308 + sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
1343 1309 }
1344 1310  
1345   -/*
1346   - * Handle cases where the rcu_cpu_kthread() ends up on the wrong CPU.
1347   - * This can happen while the corresponding CPU is either coming online
1348   - * or going offline. We cannot wait until the CPU is fully online
1349   - * before starting the kthread, because the various notifier functions
1350   - * can wait for RCU grace periods. So we park rcu_cpu_kthread() until
1351   - * the corresponding CPU is online.
1352   - *
1353   - * Return 1 if the kthread needs to stop, 0 otherwise.
1354   - *
1355   - * Caller must disable bh. This function can momentarily enable it.
1356   - */
1357   -static int rcu_cpu_kthread_should_stop(int cpu)
  1311 +static void rcu_cpu_kthread_park(unsigned int cpu)
1358 1312 {
1359   - while (cpu_is_offline(cpu) ||
1360   - !cpumask_equal(&current->cpus_allowed, cpumask_of(cpu)) ||
1361   - smp_processor_id() != cpu) {
1362   - if (kthread_should_stop())
1363   - return 1;
1364   - per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU;
1365   - per_cpu(rcu_cpu_kthread_cpu, cpu) = raw_smp_processor_id();
1366   - local_bh_enable();
1367   - schedule_timeout_uninterruptible(1);
1368   - if (!cpumask_equal(&current->cpus_allowed, cpumask_of(cpu)))
1369   - set_cpus_allowed_ptr(current, cpumask_of(cpu));
1370   - local_bh_disable();
1371   - }
1372   - per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu;
1373   - return 0;
  1313 + per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU;
1374 1314 }
1375 1315  
  1316 +static int rcu_cpu_kthread_should_run(unsigned int cpu)
  1317 +{
  1318 + return __get_cpu_var(rcu_cpu_has_work);
  1319 +}
  1320 +
1376 1321 /*
1377 1322 * Per-CPU kernel thread that invokes RCU callbacks. This replaces the
1378 1323 * RCU softirq used in flavors and configurations of RCU that do not
1379 1324 * support RCU priority boosting.
1380 1325 */
1381   -static int rcu_cpu_kthread(void *arg)
  1326 +static void rcu_cpu_kthread(unsigned int cpu)
1382 1327 {
1383   - int cpu = (int)(long)arg;
1384   - unsigned long flags;
1385   - int spincnt = 0;
1386   - unsigned int *statusp = &per_cpu(rcu_cpu_kthread_status, cpu);
1387   - char work;
1388   - char *workp = &per_cpu(rcu_cpu_has_work, cpu);
  1328 + unsigned int *statusp = &__get_cpu_var(rcu_cpu_kthread_status);
  1329 + char work, *workp = &__get_cpu_var(rcu_cpu_has_work);
  1330 + int spincnt;
1389 1331  
1390   - trace_rcu_utilization("Start CPU kthread@init");
1391   - for (;;) {
1392   - *statusp = RCU_KTHREAD_WAITING;
1393   - trace_rcu_utilization("End CPU kthread@rcu_wait");
1394   - rcu_wait(*workp != 0 || kthread_should_stop());
  1332 + for (spincnt = 0; spincnt < 10; spincnt++) {
1395 1333 trace_rcu_utilization("Start CPU kthread@rcu_wait");
1396 1334 local_bh_disable();
1397   - if (rcu_cpu_kthread_should_stop(cpu)) {
1398   - local_bh_enable();
1399   - break;
1400   - }
1401 1335 *statusp = RCU_KTHREAD_RUNNING;
1402   - per_cpu(rcu_cpu_kthread_loops, cpu)++;
1403   - local_irq_save(flags);
  1336 + this_cpu_inc(rcu_cpu_kthread_loops);
  1337 + local_irq_disable();
1404 1338 work = *workp;
1405 1339 *workp = 0;
1406   - local_irq_restore(flags);
  1340 + local_irq_enable();
1407 1341 if (work)
1408 1342 rcu_kthread_do_work();
1409 1343 local_bh_enable();
1410   - if (*workp != 0)
1411   - spincnt++;
1412   - else
1413   - spincnt = 0;
1414   - if (spincnt > 10) {
1415   - *statusp = RCU_KTHREAD_YIELDING;
1416   - trace_rcu_utilization("End CPU kthread@rcu_yield");
1417   - schedule_timeout_interruptible(2);
1418   - trace_rcu_utilization("Start CPU kthread@rcu_yield");
1419   - spincnt = 0;
  1344 + if (*workp == 0) {
  1345 + trace_rcu_utilization("End CPU kthread@rcu_wait");
  1346 + *statusp = RCU_KTHREAD_WAITING;
  1347 + return;
1420 1348 }
1421 1349 }
1422   - *statusp = RCU_KTHREAD_STOPPED;
1423   - trace_rcu_utilization("End CPU kthread@term");
1424   - return 0;
  1350 + *statusp = RCU_KTHREAD_YIELDING;
  1351 + trace_rcu_utilization("Start CPU kthread@rcu_yield");
  1352 + schedule_timeout_interruptible(2);
  1353 + trace_rcu_utilization("End CPU kthread@rcu_yield");
  1354 + *statusp = RCU_KTHREAD_WAITING;
1425 1355 }
1426 1356  
1427 1357 /*
1428   - * Spawn a per-CPU kthread, setting up affinity and priority.
1429   - * Because the CPU hotplug lock is held, no other CPU will be attempting
1430   - * to manipulate rcu_cpu_kthread_task. There might be another CPU
1431   - * attempting to access it during boot, but the locking in kthread_bind()
1432   - * will enforce sufficient ordering.
1433   - *
1434   - * Please note that we cannot simply refuse to wake up the per-CPU
1435   - * kthread because kthreads are created in TASK_UNINTERRUPTIBLE state,
1436   - * which can result in softlockup complaints if the task ends up being
1437   - * idle for more than a couple of minutes.
1438   - *
1439   - * However, please note also that we cannot bind the per-CPU kthread to its
1440   - * CPU until that CPU is fully online. We also cannot wait until the
1441   - * CPU is fully online before we create its per-CPU kthread, as this would
1442   - * deadlock the system when CPU notifiers tried waiting for grace
1443   - * periods. So we bind the per-CPU kthread to its CPU only if the CPU
1444   - * is online. If its CPU is not yet fully online, then the code in
1445   - * rcu_cpu_kthread() will wait until it is fully online, and then do
1446   - * the binding.
1447   - */
1448   -static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu)
1449   -{
1450   - struct sched_param sp;
1451   - struct task_struct *t;
1452   -
1453   - if (!rcu_scheduler_fully_active ||
1454   - per_cpu(rcu_cpu_kthread_task, cpu) != NULL)
1455   - return 0;
1456   - t = kthread_create_on_node(rcu_cpu_kthread,
1457   - (void *)(long)cpu,
1458   - cpu_to_node(cpu),
1459   - "rcuc/%d", cpu);
1460   - if (IS_ERR(t))
1461   - return PTR_ERR(t);
1462   - if (cpu_online(cpu))
1463   - kthread_bind(t, cpu);
1464   - per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu;
1465   - WARN_ON_ONCE(per_cpu(rcu_cpu_kthread_task, cpu) != NULL);
1466   - sp.sched_priority = RCU_KTHREAD_PRIO;
1467   - sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
1468   - per_cpu(rcu_cpu_kthread_task, cpu) = t;
1469   - wake_up_process(t); /* Get to TASK_INTERRUPTIBLE quickly. */
1470   - return 0;
1471   -}
1472   -
1473   -/*
1474 1358 * Set the per-rcu_node kthread's affinity to cover all CPUs that are
1475 1359 * served by the rcu_node in question. The CPU hotplug lock is still
1476 1360 * held, so the value of rnp->qsmaskinit will be stable.
... ... @@ -1503,6 +1387,15 @@
1503 1387 free_cpumask_var(cm);
1504 1388 }
1505 1389  
  1390 +static struct smp_hotplug_thread rcu_cpu_thread_spec = {
  1391 + .store = &rcu_cpu_kthread_task,
  1392 + .thread_should_run = rcu_cpu_kthread_should_run,
  1393 + .thread_fn = rcu_cpu_kthread,
  1394 + .thread_comm = "rcuc/%u",
  1395 + .setup = rcu_cpu_kthread_setup,
  1396 + .park = rcu_cpu_kthread_park,
  1397 +};
  1398 +
1506 1399 /*
1507 1400 * Spawn all kthreads -- called as soon as the scheduler is running.
1508 1401 */
1509 1402  
... ... @@ -1512,11 +1405,9 @@
1512 1405 int cpu;
1513 1406  
1514 1407 rcu_scheduler_fully_active = 1;
1515   - for_each_possible_cpu(cpu) {
  1408 + for_each_possible_cpu(cpu)
1516 1409 per_cpu(rcu_cpu_has_work, cpu) = 0;
1517   - if (cpu_online(cpu))
1518   - (void)rcu_spawn_one_cpu_kthread(cpu);
1519   - }
  1410 + BUG_ON(smpboot_register_percpu_thread(&rcu_cpu_thread_spec));
1520 1411 rnp = rcu_get_root(rcu_state);
1521 1412 (void)rcu_spawn_one_boost_kthread(rcu_state, rnp);
1522 1413 if (NUM_RCU_NODES > 1) {
1523 1414  
... ... @@ -1533,10 +1424,8 @@
1533 1424 struct rcu_node *rnp = rdp->mynode;
1534 1425  
1535 1426 /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */
1536   - if (rcu_scheduler_fully_active) {
1537   - (void)rcu_spawn_one_cpu_kthread(cpu);
  1427 + if (rcu_scheduler_fully_active)
1538 1428 (void)rcu_spawn_one_boost_kthread(rcu_state, rnp);
1539   - }
1540 1429 }
1541 1430  
1542 1431 #else /* #ifdef CONFIG_RCU_BOOST */
1543 1432  
... ... @@ -1560,19 +1449,7 @@
1560 1449 {
1561 1450 }
1562 1451  
1563   -#ifdef CONFIG_HOTPLUG_CPU
1564   -
1565   -static void rcu_stop_cpu_kthread(int cpu)
1566   -{
1567   -}
1568   -
1569   -#endif /* #ifdef CONFIG_HOTPLUG_CPU */
1570   -
1571 1452 static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu)
1572   -{
1573   -}
1574   -
1575   -static void rcu_cpu_kthread_setrt(int cpu, int to_rt)
1576 1453 {
1577 1454 }
1578 1455  
kernel/rcutree_trace.c
... ... @@ -108,11 +108,10 @@
108 108 rdp->nxttail[RCU_WAIT_TAIL]],
109 109 ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]]);
110 110 #ifdef CONFIG_RCU_BOOST
111   - seq_printf(m, " kt=%d/%c/%d ktl=%x",
  111 + seq_printf(m, " kt=%d/%c ktl=%x",
112 112 per_cpu(rcu_cpu_has_work, rdp->cpu),
113 113 convert_kthread_status(per_cpu(rcu_cpu_kthread_status,
114 114 rdp->cpu)),
115   - per_cpu(rcu_cpu_kthread_cpu, rdp->cpu),
116 115 per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff);
117 116 #endif /* #ifdef CONFIG_RCU_BOOST */
118 117 seq_printf(m, " b=%ld", rdp->blimit);