aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-09-16 03:08:43 -0400
committerIngo Molnar <mingo@kernel.org>2016-09-16 03:08:43 -0400
commit2d8fbcd13ea1d0be3a7ea5f20c3a5b44b592e79c (patch)
tree5a88bad802e3c2e4f5d241b9596f9102db04f78e
parent024c7e3756d8a42fc41fe8a9488488b9b09d1dcc (diff)
parentd74b62bc3241af8ebf5141f5b12e89d9d7f341e1 (diff)
Merge branch 'for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu into core/rcu
Pull RCU changes from Paul E. McKenney: - Expedited grace-period changes, most notably avoiding having user threads drive expedited grace periods, using a workqueue instead. - Miscellaneous fixes, including a performance fix for lists that was sent with the lists modifications (second URL below). - CPU hotplug updates, most notably providing exact CPU-online tracking for RCU. This will in turn allow removal of the checks supporting RCU's prior heuristic that was based on the assumption that CPUs would take no longer than one jiffy to come online. - Torture-test updates. - Documentation updates. Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--Documentation/RCU/Design/Requirements/Requirements.html22
-rw-r--r--Documentation/RCU/torture.txt15
-rw-r--r--include/linux/list.h7
-rw-r--r--include/linux/rcupdate.h1
-rw-r--r--include/linux/torture.h2
-rw-r--r--kernel/cpu.c1
-rw-r--r--kernel/rcu/rcuperf.c7
-rw-r--r--kernel/rcu/rcutorture.c62
-rw-r--r--kernel/rcu/tree.c44
-rw-r--r--kernel/rcu/tree.h1
-rw-r--r--kernel/rcu/tree_exp.h124
-rw-r--r--kernel/rcu/tree_plugin.h1
-rw-r--r--kernel/rcu/tree_trace.c7
-rw-r--r--kernel/rcu/update.c3
-rw-r--r--kernel/sched/core.c7
-rw-r--r--kernel/torture.c27
16 files changed, 193 insertions, 138 deletions
diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html
index ece410f40436..a4d3838130e4 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.html
+++ b/Documentation/RCU/Design/Requirements/Requirements.html
@@ -2493,6 +2493,28 @@ or some future &ldquo;lazy&rdquo;
2493variant of <tt>call_rcu()</tt> that might one day be created for 2493variant of <tt>call_rcu()</tt> that might one day be created for
2494energy-efficiency purposes. 2494energy-efficiency purposes.
2495 2495
2496<p>
2497That said, there are limits.
2498RCU requires that the <tt>rcu_head</tt> structure be aligned to a
2499two-byte boundary, and passing a misaligned <tt>rcu_head</tt>
2500structure to one of the <tt>call_rcu()</tt> family of functions
2501will result in a splat.
2502It is therefore necessary to exercise caution when packing
2503structures containing fields of type <tt>rcu_head</tt>.
2504Why not a four-byte or even eight-byte alignment requirement?
2505Because the m68k architecture provides only two-byte alignment,
2506and thus acts as alignment's least common denominator.
2507
2508<p>
2509The reason for reserving the bottom bit of pointers to
2510<tt>rcu_head</tt> structures is to leave the door open to
2511&ldquo;lazy&rdquo; callbacks whose invocations can safely be deferred.
2512Deferring invocation could potentially have energy-efficiency
2513benefits, but only if the rate of non-lazy callbacks decreases
2514significantly for some important workload.
2515In the meantime, reserving the bottom bit keeps this option open
2516in case it one day becomes useful.
2517
2496<h3><a name="Performance, Scalability, Response Time, and Reliability"> 2518<h3><a name="Performance, Scalability, Response Time, and Reliability">
2497Performance, Scalability, Response Time, and Reliability</a></h3> 2519Performance, Scalability, Response Time, and Reliability</a></h3>
2498 2520
diff --git a/Documentation/RCU/torture.txt b/Documentation/RCU/torture.txt
index 118e7c176ce7..278f6a9383b6 100644
--- a/Documentation/RCU/torture.txt
+++ b/Documentation/RCU/torture.txt
@@ -10,21 +10,6 @@ status messages via printk(), which can be examined via the dmesg
10command (perhaps grepping for "torture"). The test is started 10command (perhaps grepping for "torture"). The test is started
11when the module is loaded, and stops when the module is unloaded. 11when the module is loaded, and stops when the module is unloaded.
12 12
13CONFIG_RCU_TORTURE_TEST_RUNNABLE
14
15It is also possible to specify CONFIG_RCU_TORTURE_TEST=y, which will
16result in the tests being loaded into the base kernel. In this case,
17the CONFIG_RCU_TORTURE_TEST_RUNNABLE config option is used to specify
18whether the RCU torture tests are to be started immediately during
19boot or whether the /proc/sys/kernel/rcutorture_runnable file is used
20to enable them. This /proc file can be used to repeatedly pause and
21restart the tests, regardless of the initial state specified by the
22CONFIG_RCU_TORTURE_TEST_RUNNABLE config option.
23
24You will normally -not- want to start the RCU torture tests during boot
25(and thus the default is CONFIG_RCU_TORTURE_TEST_RUNNABLE=n), but doing
26this can sometimes be useful in finding boot-time bugs.
27
28 13
29MODULE PARAMETERS 14MODULE PARAMETERS
30 15
diff --git a/include/linux/list.h b/include/linux/list.h
index 5183138aa932..5809e9a2de5b 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -381,8 +381,11 @@ static inline void list_splice_tail_init(struct list_head *list,
381 * 381 *
382 * Note that if the list is empty, it returns NULL. 382 * Note that if the list is empty, it returns NULL.
383 */ 383 */
384#define list_first_entry_or_null(ptr, type, member) \ 384#define list_first_entry_or_null(ptr, type, member) ({ \
385 (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL) 385 struct list_head *head__ = (ptr); \
386 struct list_head *pos__ = READ_ONCE(head__->next); \
387 pos__ != head__ ? list_entry(pos__, type, member) : NULL; \
388})
386 389
387/** 390/**
388 * list_next_entry - get the next element in list 391 * list_next_entry - get the next element in list
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 1aa62e1a761b..321f9ed552a9 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -334,6 +334,7 @@ void rcu_sched_qs(void);
334void rcu_bh_qs(void); 334void rcu_bh_qs(void);
335void rcu_check_callbacks(int user); 335void rcu_check_callbacks(int user);
336void rcu_report_dead(unsigned int cpu); 336void rcu_report_dead(unsigned int cpu);
337void rcu_cpu_starting(unsigned int cpu);
337 338
338#ifndef CONFIG_TINY_RCU 339#ifndef CONFIG_TINY_RCU
339void rcu_end_inkernel_boot(void); 340void rcu_end_inkernel_boot(void);
diff --git a/include/linux/torture.h b/include/linux/torture.h
index 6685a73736a2..a45702eb3e7b 100644
--- a/include/linux/torture.h
+++ b/include/linux/torture.h
@@ -43,7 +43,7 @@
43 43
44#define TORTURE_FLAG "-torture:" 44#define TORTURE_FLAG "-torture:"
45#define TOROUT_STRING(s) \ 45#define TOROUT_STRING(s) \
46 pr_alert("%s" TORTURE_FLAG s "\n", torture_type) 46 pr_alert("%s" TORTURE_FLAG " %s\n", torture_type, s)
47#define VERBOSE_TOROUT_STRING(s) \ 47#define VERBOSE_TOROUT_STRING(s) \
48 do { if (verbose) pr_alert("%s" TORTURE_FLAG " %s\n", torture_type, s); } while (0) 48 do { if (verbose) pr_alert("%s" TORTURE_FLAG " %s\n", torture_type, s); } while (0)
49#define VERBOSE_TOROUT_ERRSTRING(s) \ 49#define VERBOSE_TOROUT_ERRSTRING(s) \
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 341bf80f80bd..ff8bc3817dde 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -889,6 +889,7 @@ void notify_cpu_starting(unsigned int cpu)
889 struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu); 889 struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
890 enum cpuhp_state target = min((int)st->target, CPUHP_AP_ONLINE); 890 enum cpuhp_state target = min((int)st->target, CPUHP_AP_ONLINE);
891 891
892 rcu_cpu_starting(cpu); /* Enables RCU usage on this CPU. */
892 while (st->state < target) { 893 while (st->state < target) {
893 struct cpuhp_step *step; 894 struct cpuhp_step *step;
894 895
diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c
index d38ab08a3fe7..123ccbd22449 100644
--- a/kernel/rcu/rcuperf.c
+++ b/kernel/rcu/rcuperf.c
@@ -52,7 +52,7 @@ MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.vnet.ibm.com>");
52 52
53#define PERF_FLAG "-perf:" 53#define PERF_FLAG "-perf:"
54#define PERFOUT_STRING(s) \ 54#define PERFOUT_STRING(s) \
55 pr_alert("%s" PERF_FLAG s "\n", perf_type) 55 pr_alert("%s" PERF_FLAG " %s\n", perf_type, s)
56#define VERBOSE_PERFOUT_STRING(s) \ 56#define VERBOSE_PERFOUT_STRING(s) \
57 do { if (verbose) pr_alert("%s" PERF_FLAG " %s\n", perf_type, s); } while (0) 57 do { if (verbose) pr_alert("%s" PERF_FLAG " %s\n", perf_type, s); } while (0)
58#define VERBOSE_PERFOUT_ERRSTRING(s) \ 58#define VERBOSE_PERFOUT_ERRSTRING(s) \
@@ -400,9 +400,8 @@ rcu_perf_writer(void *arg)
400 sp.sched_priority = 0; 400 sp.sched_priority = 0;
401 sched_setscheduler_nocheck(current, 401 sched_setscheduler_nocheck(current,
402 SCHED_NORMAL, &sp); 402 SCHED_NORMAL, &sp);
403 pr_alert("%s" PERF_FLAG 403 pr_alert("%s%s rcu_perf_writer %ld has %d measurements\n",
404 "rcu_perf_writer %ld has %d measurements\n", 404 perf_type, PERF_FLAG, me, MIN_MEAS);
405 perf_type, me, MIN_MEAS);
406 if (atomic_inc_return(&n_rcu_perf_writer_finished) >= 405 if (atomic_inc_return(&n_rcu_perf_writer_finished) >=
407 nrealwriters) { 406 nrealwriters) {
408 schedule_timeout_interruptible(10); 407 schedule_timeout_interruptible(10);
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 971e2b138063..bf08fee53dc7 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -1238,6 +1238,7 @@ rcu_torture_stats_print(void)
1238 long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 }; 1238 long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
1239 long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 }; 1239 long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
1240 static unsigned long rtcv_snap = ULONG_MAX; 1240 static unsigned long rtcv_snap = ULONG_MAX;
1241 struct task_struct *wtp;
1241 1242
1242 for_each_possible_cpu(cpu) { 1243 for_each_possible_cpu(cpu) {
1243 for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { 1244 for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
@@ -1258,8 +1259,9 @@ rcu_torture_stats_print(void)
1258 atomic_read(&n_rcu_torture_alloc), 1259 atomic_read(&n_rcu_torture_alloc),
1259 atomic_read(&n_rcu_torture_alloc_fail), 1260 atomic_read(&n_rcu_torture_alloc_fail),
1260 atomic_read(&n_rcu_torture_free)); 1261 atomic_read(&n_rcu_torture_free));
1261 pr_cont("rtmbe: %d rtbke: %ld rtbre: %ld ", 1262 pr_cont("rtmbe: %d rtbe: %ld rtbke: %ld rtbre: %ld ",
1262 atomic_read(&n_rcu_torture_mberror), 1263 atomic_read(&n_rcu_torture_mberror),
1264 n_rcu_torture_barrier_error,
1263 n_rcu_torture_boost_ktrerror, 1265 n_rcu_torture_boost_ktrerror,
1264 n_rcu_torture_boost_rterror); 1266 n_rcu_torture_boost_rterror);
1265 pr_cont("rtbf: %ld rtb: %ld nt: %ld ", 1267 pr_cont("rtbf: %ld rtb: %ld nt: %ld ",
@@ -1312,10 +1314,12 @@ rcu_torture_stats_print(void)
1312 1314
1313 rcutorture_get_gp_data(cur_ops->ttype, 1315 rcutorture_get_gp_data(cur_ops->ttype,
1314 &flags, &gpnum, &completed); 1316 &flags, &gpnum, &completed);