diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-02-28 02:38:30 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-02-28 02:38:30 -0500 |
commit | 62c206bd514600d4d73751ade00dca8e488390a3 (patch) | |
tree | 78d0b44e4672dc7da1762d153b6dbc520eeddb04 /include | |
parent | d2a0476307e67a6e6a293563a4f4ad4ec79ac0e5 (diff) | |
parent | f5604f67fe8cbd6f2088b20b9463f721aa613d4b (diff) |
Merge branch 'rcu/next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu into core/rcu
Pull RCU updates from Paul E. McKenney:
* Update RCU documentation. These were posted to LKML at
https://lkml.org/lkml/2014/2/17/555.
* Miscellaneous fixes. These were posted to LKML at
https://lkml.org/lkml/2014/2/17/530. Note that two of these
are RCU changes to other maintainer's trees: add1f0995454
(fs) and 8857563b819b (notifer), both of which substitute
rcu_access_pointer() for rcu_dereference_raw().
* Real-time latency fixes. These were posted to LKML at
https://lkml.org/lkml/2014/2/17/544.
* Torture-test changes, including refactoring of rcutorture
and introduction of a vestigial locktorture. These were posted
to LKML at https://lkml.org/lkml/2014/2/17/599.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/rculist.h | 17 | ||||
-rw-r--r-- | include/linux/rcupdate.h | 94 | ||||
-rw-r--r-- | include/linux/rcutiny.h | 10 | ||||
-rw-r--r-- | include/linux/rcutree.h | 6 | ||||
-rw-r--r-- | include/linux/srcu.h | 4 | ||||
-rw-r--r-- | include/linux/torture.h | 100 |
6 files changed, 165 insertions, 66 deletions
diff --git a/include/linux/rculist.h b/include/linux/rculist.h index dbaf99084112..8183b46fbaa2 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h | |||
@@ -247,9 +247,10 @@ static inline void list_splice_init_rcu(struct list_head *list, | |||
247 | * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). | 247 | * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). |
248 | */ | 248 | */ |
249 | #define list_entry_rcu(ptr, type, member) \ | 249 | #define list_entry_rcu(ptr, type, member) \ |
250 | ({typeof (*ptr) __rcu *__ptr = (typeof (*ptr) __rcu __force *)ptr; \ | 250 | ({ \ |
251 | container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \ | 251 | typeof(*ptr) __rcu *__ptr = (typeof(*ptr) __rcu __force *)ptr; \ |
252 | }) | 252 | container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \ |
253 | }) | ||
253 | 254 | ||
254 | /** | 255 | /** |
255 | * Where are list_empty_rcu() and list_first_entry_rcu()? | 256 | * Where are list_empty_rcu() and list_first_entry_rcu()? |
@@ -285,11 +286,11 @@ static inline void list_splice_init_rcu(struct list_head *list, | |||
285 | * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). | 286 | * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). |
286 | */ | 287 | */ |
287 | #define list_first_or_null_rcu(ptr, type, member) \ | 288 | #define list_first_or_null_rcu(ptr, type, member) \ |
288 | ({struct list_head *__ptr = (ptr); \ | 289 | ({ \ |
289 | struct list_head *__next = ACCESS_ONCE(__ptr->next); \ | 290 | struct list_head *__ptr = (ptr); \ |
290 | likely(__ptr != __next) ? \ | 291 | struct list_head *__next = ACCESS_ONCE(__ptr->next); \ |
291 | list_entry_rcu(__next, type, member) : NULL; \ | 292 | likely(__ptr != __next) ? list_entry_rcu(__next, type, member) : NULL; \ |
292 | }) | 293 | }) |
293 | 294 | ||
294 | /** | 295 | /** |
295 | * list_for_each_entry_rcu - iterate over rcu list of given type | 296 | * list_for_each_entry_rcu - iterate over rcu list of given type |
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 72bf3a01a4ee..cda2583d67e9 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
@@ -12,8 +12,8 @@ | |||
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, you can access it online at |
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 16 | * http://www.gnu.org/licenses/gpl-2.0.html. |
17 | * | 17 | * |
18 | * Copyright IBM Corporation, 2001 | 18 | * Copyright IBM Corporation, 2001 |
19 | * | 19 | * |
@@ -44,7 +44,9 @@ | |||
44 | #include <linux/debugobjects.h> | 44 | #include <linux/debugobjects.h> |
45 | #include <linux/bug.h> | 45 | #include <linux/bug.h> |
46 | #include <linux/compiler.h> | 46 | #include <linux/compiler.h> |
47 | #include <asm/barrier.h> | ||
47 | 48 | ||
49 | extern int rcu_expedited; /* for sysctl */ | ||
48 | #ifdef CONFIG_RCU_TORTURE_TEST | 50 | #ifdef CONFIG_RCU_TORTURE_TEST |
49 | extern int rcutorture_runnable; /* for sysctl */ | 51 | extern int rcutorture_runnable; /* for sysctl */ |
50 | #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ | 52 | #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ |
@@ -479,11 +481,9 @@ static inline void rcu_preempt_sleep_check(void) | |||
479 | do { \ | 481 | do { \ |
480 | rcu_preempt_sleep_check(); \ | 482 | rcu_preempt_sleep_check(); \ |
481 | rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map), \ | 483 | rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map), \ |
482 | "Illegal context switch in RCU-bh" \ | 484 | "Illegal context switch in RCU-bh read-side critical section"); \ |
483 | " read-side critical section"); \ | ||
484 | rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map), \ | 485 | rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map), \ |
485 | "Illegal context switch in RCU-sched"\ | 486 | "Illegal context switch in RCU-sched read-side critical section"); \ |
486 | " read-side critical section"); \ | ||
487 | } while (0) | 487 | } while (0) |
488 | 488 | ||
489 | #else /* #ifdef CONFIG_PROVE_RCU */ | 489 | #else /* #ifdef CONFIG_PROVE_RCU */ |
@@ -510,43 +510,40 @@ static inline void rcu_preempt_sleep_check(void) | |||
510 | #endif /* #else #ifdef __CHECKER__ */ | 510 | #endif /* #else #ifdef __CHECKER__ */ |
511 | 511 | ||
512 | #define __rcu_access_pointer(p, space) \ | 512 | #define __rcu_access_pointer(p, space) \ |
513 | ({ \ | 513 | ({ \ |
514 | typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \ | 514 | typeof(*p) *_________p1 = (typeof(*p) *__force)ACCESS_ONCE(p); \ |
515 | rcu_dereference_sparse(p, space); \ | 515 | rcu_dereference_sparse(p, space); \ |
516 | ((typeof(*p) __force __kernel *)(_________p1)); \ | 516 | ((typeof(*p) __force __kernel *)(_________p1)); \ |
517 | }) | 517 | }) |
518 | #define __rcu_dereference_check(p, c, space) \ | 518 | #define __rcu_dereference_check(p, c, space) \ |
519 | ({ \ | 519 | ({ \ |
520 | typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \ | 520 | typeof(*p) *_________p1 = (typeof(*p) *__force)ACCESS_ONCE(p); \ |
521 | rcu_lockdep_assert(c, "suspicious rcu_dereference_check()" \ | 521 | rcu_lockdep_assert(c, "suspicious rcu_dereference_check() usage"); \ |
522 | " usage"); \ | 522 | rcu_dereference_sparse(p, space); \ |
523 | rcu_dereference_sparse(p, space); \ | 523 | smp_read_barrier_depends(); /* Dependency order vs. p above. */ \ |
524 | smp_read_barrier_depends(); \ | 524 | ((typeof(*p) __force __kernel *)(_________p1)); \ |
525 | ((typeof(*p) __force __kernel *)(_________p1)); \ | 525 | }) |
526 | }) | ||
527 | #define __rcu_dereference_protected(p, c, space) \ | 526 | #define __rcu_dereference_protected(p, c, space) \ |
528 | ({ \ | 527 | ({ \ |
529 | rcu_lockdep_assert(c, "suspicious rcu_dereference_protected()" \ | 528 | rcu_lockdep_assert(c, "suspicious rcu_dereference_protected() usage"); \ |
530 | " usage"); \ | 529 | rcu_dereference_sparse(p, space); \ |
531 | rcu_dereference_sparse(p, space); \ | 530 | ((typeof(*p) __force __kernel *)(p)); \ |
532 | ((typeof(*p) __force __kernel *)(p)); \ | 531 | }) |
533 | }) | ||
534 | 532 | ||
535 | #define __rcu_access_index(p, space) \ | 533 | #define __rcu_access_index(p, space) \ |
536 | ({ \ | 534 | ({ \ |
537 | typeof(p) _________p1 = ACCESS_ONCE(p); \ | 535 | typeof(p) _________p1 = ACCESS_ONCE(p); \ |
538 | rcu_dereference_sparse(p, space); \ | 536 | rcu_dereference_sparse(p, space); \ |
539 | (_________p1); \ | 537 | (_________p1); \ |
540 | }) | 538 | }) |
541 | #define __rcu_dereference_index_check(p, c) \ | 539 | #define __rcu_dereference_index_check(p, c) \ |
542 | ({ \ | 540 | ({ \ |
543 | typeof(p) _________p1 = ACCESS_ONCE(p); \ | 541 | typeof(p) _________p1 = ACCESS_ONCE(p); \ |
544 | rcu_lockdep_assert(c, \ | 542 | rcu_lockdep_assert(c, \ |
545 | "suspicious rcu_dereference_index_check()" \ | 543 | "suspicious rcu_dereference_index_check() usage"); \ |
546 | " usage"); \ | 544 | smp_read_barrier_depends(); /* Dependency order vs. p above. */ \ |
547 | smp_read_barrier_depends(); \ | 545 | (_________p1); \ |
548 | (_________p1); \ | 546 | }) |
549 | }) | ||
550 | 547 | ||
551 | /** | 548 | /** |
552 | * RCU_INITIALIZER() - statically initialize an RCU-protected global variable | 549 | * RCU_INITIALIZER() - statically initialize an RCU-protected global variable |
@@ -585,12 +582,7 @@ static inline void rcu_preempt_sleep_check(void) | |||
585 | * please be careful when making changes to rcu_assign_pointer() and the | 582 | * please be careful when making changes to rcu_assign_pointer() and the |
586 | * other macros that it invokes. | 583 | * other macros that it invokes. |
587 | */ | 584 | */ |
588 | #define rcu_assign_pointer(p, v) \ | 585 | #define rcu_assign_pointer(p, v) smp_store_release(&p, RCU_INITIALIZER(v)) |
589 | do { \ | ||
590 | smp_wmb(); \ | ||
591 | ACCESS_ONCE(p) = RCU_INITIALIZER(v); \ | ||
592 | } while (0) | ||
593 | |||
594 | 586 | ||
595 | /** | 587 | /** |
596 | * rcu_access_pointer() - fetch RCU pointer with no dereferencing | 588 | * rcu_access_pointer() - fetch RCU pointer with no dereferencing |
@@ -1015,11 +1007,21 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) | |||
1015 | #define kfree_rcu(ptr, rcu_head) \ | 1007 | #define kfree_rcu(ptr, rcu_head) \ |
1016 | __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head)) | 1008 | __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head)) |
1017 | 1009 | ||
1018 | #ifdef CONFIG_RCU_NOCB_CPU | 1010 | #if defined(CONFIG_TINY_RCU) || defined(CONFIG_RCU_NOCB_CPU_ALL) |
1011 | static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) | ||
1012 | { | ||
1013 | *delta_jiffies = ULONG_MAX; | ||
1014 | return 0; | ||
1015 | } | ||
1016 | #endif /* #if defined(CONFIG_TINY_RCU) || defined(CONFIG_RCU_NOCB_CPU_ALL) */ | ||
1017 | |||
1018 | #if defined(CONFIG_RCU_NOCB_CPU_ALL) | ||
1019 | static inline bool rcu_is_nocb_cpu(int cpu) { return true; } | ||
1020 | #elif defined(CONFIG_RCU_NOCB_CPU) | ||
1019 | bool rcu_is_nocb_cpu(int cpu); | 1021 | bool rcu_is_nocb_cpu(int cpu); |
1020 | #else | 1022 | #else |
1021 | static inline bool rcu_is_nocb_cpu(int cpu) { return false; } | 1023 | static inline bool rcu_is_nocb_cpu(int cpu) { return false; } |
1022 | #endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */ | 1024 | #endif |
1023 | 1025 | ||
1024 | 1026 | ||
1025 | /* Only for use by adaptive-ticks code. */ | 1027 | /* Only for use by adaptive-ticks code. */ |
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index 6f01771b571c..e8cb6e3b52a7 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h | |||
@@ -12,8 +12,8 @@ | |||
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, you can access it online at |
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 16 | * http://www.gnu.org/licenses/gpl-2.0.html. |
17 | * | 17 | * |
18 | * Copyright IBM Corporation, 2008 | 18 | * Copyright IBM Corporation, 2008 |
19 | * | 19 | * |
@@ -68,12 +68,6 @@ static inline void kfree_call_rcu(struct rcu_head *head, | |||
68 | call_rcu(head, func); | 68 | call_rcu(head, func); |
69 | } | 69 | } |
70 | 70 | ||
71 | static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) | ||
72 | { | ||
73 | *delta_jiffies = ULONG_MAX; | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static inline void rcu_note_context_switch(int cpu) | 71 | static inline void rcu_note_context_switch(int cpu) |
78 | { | 72 | { |
79 | rcu_sched_qs(cpu); | 73 | rcu_sched_qs(cpu); |
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index 72137ee8c603..e9c63884df0a 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h | |||
@@ -12,8 +12,8 @@ | |||
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, you can access it online at |
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 16 | * http://www.gnu.org/licenses/gpl-2.0.html. |
17 | * | 17 | * |
18 | * Copyright IBM Corporation, 2008 | 18 | * Copyright IBM Corporation, 2008 |
19 | * | 19 | * |
@@ -31,7 +31,9 @@ | |||
31 | #define __LINUX_RCUTREE_H | 31 | #define __LINUX_RCUTREE_H |
32 | 32 | ||
33 | void rcu_note_context_switch(int cpu); | 33 | void rcu_note_context_switch(int cpu); |
34 | #ifndef CONFIG_RCU_NOCB_CPU_ALL | ||
34 | int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies); | 35 | int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies); |
36 | #endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */ | ||
35 | void rcu_cpu_stall_reset(void); | 37 | void rcu_cpu_stall_reset(void); |
36 | 38 | ||
37 | /* | 39 | /* |
diff --git a/include/linux/srcu.h b/include/linux/srcu.h index 9b058eecd403..a2783cb5d275 100644 --- a/include/linux/srcu.h +++ b/include/linux/srcu.h | |||
@@ -12,8 +12,8 @@ | |||
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, you can access it online at |
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 16 | * http://www.gnu.org/licenses/gpl-2.0.html. |
17 | * | 17 | * |
18 | * Copyright (C) IBM Corporation, 2006 | 18 | * Copyright (C) IBM Corporation, 2006 |
19 | * Copyright (C) Fujitsu, 2012 | 19 | * Copyright (C) Fujitsu, 2012 |
diff --git a/include/linux/torture.h b/include/linux/torture.h new file mode 100644 index 000000000000..b2e2b468e511 --- /dev/null +++ b/include/linux/torture.h | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * Common functions for in-kernel torture tests. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, you can access it online at | ||
16 | * http://www.gnu.org/licenses/gpl-2.0.html. | ||
17 | * | ||
18 | * Copyright IBM Corporation, 2014 | ||
19 | * | ||
20 | * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||
21 | */ | ||
22 | |||
23 | #ifndef __LINUX_TORTURE_H | ||
24 | #define __LINUX_TORTURE_H | ||
25 | |||
26 | #include <linux/types.h> | ||
27 | #include <linux/cache.h> | ||
28 | #include <linux/spinlock.h> | ||
29 | #include <linux/threads.h> | ||
30 | #include <linux/cpumask.h> | ||
31 | #include <linux/seqlock.h> | ||
32 | #include <linux/lockdep.h> | ||
33 | #include <linux/completion.h> | ||
34 | #include <linux/debugobjects.h> | ||
35 | #include <linux/bug.h> | ||
36 | #include <linux/compiler.h> | ||
37 | |||
38 | /* Definitions for a non-string torture-test module parameter. */ | ||
39 | #define torture_param(type, name, init, msg) \ | ||
40 | static type name = init; \ | ||
41 | module_param(name, type, 0444); \ | ||
42 | MODULE_PARM_DESC(name, msg); | ||
43 | |||
44 | #define TORTURE_FLAG "-torture:" | ||
45 | #define TOROUT_STRING(s) \ | ||
46 | pr_alert("%s" TORTURE_FLAG s "\n", torture_type) | ||
47 | #define VERBOSE_TOROUT_STRING(s) \ | ||
48 | do { if (verbose) pr_alert("%s" TORTURE_FLAG " %s\n", torture_type, s); } while (0) | ||
49 | #define VERBOSE_TOROUT_ERRSTRING(s) \ | ||
50 | do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0) | ||
51 | |||
52 | /* Definitions for a non-string torture-test module parameter. */ | ||
53 | #define torture_parm(type, name, init, msg) \ | ||
54 | static type name = init; \ | ||
55 | module_param(name, type, 0444); \ | ||
56 | MODULE_PARM_DESC(name, msg); | ||
57 | |||
58 | /* Definitions for online/offline exerciser. */ | ||
59 | int torture_onoff_init(long ooholdoff, long oointerval); | ||
60 | char *torture_onoff_stats(char *page); | ||
61 | bool torture_onoff_failures(void); | ||
62 | |||
63 | /* Low-rider random number generator. */ | ||
64 | struct torture_random_state { | ||
65 | unsigned long trs_state; | ||
66 | long trs_count; | ||
67 | }; | ||
68 | #define DEFINE_TORTURE_RANDOM(name) struct torture_random_state name = { 0, 0 } | ||
69 | unsigned long torture_random(struct torture_random_state *trsp); | ||
70 | |||
71 | /* Task shuffler, which causes CPUs to occasionally go idle. */ | ||
72 | void torture_shuffle_task_register(struct task_struct *tp); | ||
73 | int torture_shuffle_init(long shuffint); | ||
74 | |||
75 | /* Test auto-shutdown handling. */ | ||
76 | void torture_shutdown_absorb(const char *title); | ||
77 | int torture_shutdown_init(int ssecs, void (*cleanup)(void)); | ||
78 | |||
79 | /* Task stuttering, which forces load/no-load transitions. */ | ||
80 | void stutter_wait(const char *title); | ||
81 | int torture_stutter_init(int s); | ||
82 | |||
83 | /* Initialization and cleanup. */ | ||
84 | void torture_init_begin(char *ttype, bool v, int *runnable); | ||
85 | void torture_init_end(void); | ||
86 | bool torture_cleanup(void); | ||
87 | bool torture_must_stop(void); | ||
88 | bool torture_must_stop_irq(void); | ||
89 | void torture_kthread_stopping(char *title); | ||
90 | int _torture_create_kthread(int (*fn)(void *arg), void *arg, char *s, char *m, | ||
91 | char *f, struct task_struct **tp); | ||
92 | void _torture_stop_kthread(char *m, struct task_struct **tp); | ||
93 | |||
94 | #define torture_create_kthread(n, arg, tp) \ | ||
95 | _torture_create_kthread(n, (arg), #n, "Creating " #n " task", \ | ||
96 | "Failed to create " #n, &(tp)) | ||
97 | #define torture_stop_kthread(n, tp) \ | ||
98 | _torture_stop_kthread("Stopping " #n " task", &(tp)) | ||
99 | |||
100 | #endif /* __LINUX_TORTURE_H */ | ||