diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-03-31 14:05:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-03-31 14:05:24 -0400 |
commit | b3fd4ea9df2d5c39cd6ce08faf965ed669eb3b56 (patch) | |
tree | de45e2aff3106f4fa413ea3f08a7f8c969c0479b /include/linux/rcupdate.h | |
parent | 462bf234a82ae1ae9d7628f59bc81022591e1348 (diff) | |
parent | 7de700e6806cafa30c70bc84478431a11197a5ea (diff) |
Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull RCU updates from Ingo Molnar:
"Main changes:
- Torture-test changes, including refactoring of rcutorture and
introduction of a vestigial locktorture.
- Real-time latency fixes.
- Documentation updates.
- Miscellaneous fixes"
* 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (77 commits)
rcu: Provide grace-period piggybacking API
rcu: Ensure kernel/rcu/rcu.h can be sourced/used stand-alone
rcu: Fix sparse warning for rcu_expedited from kernel/ksysfs.c
notifier: Substitute rcu_access_pointer() for rcu_dereference_raw()
Documentation/memory-barriers.txt: Clarify release/acquire ordering
rcutorture: Save kvm.sh output to log
rcutorture: Add a lock_busted to test the test
rcutorture: Place kvm-test-1-run.sh output into res directory
rcutorture: Rename TREE_RCU-Kconfig.txt
locktorture: Add kvm-recheck.sh plug-in for locktorture
rcutorture: Gracefully handle NULL cleanup hooks
locktorture: Add vestigial locktorture configuration
rcutorture: Introduce "rcu" directory level underneath configs
rcutorture: Rename kvm-test-1-rcu.sh
rcutorture: Remove RCU dependencies from ver_functions.sh API
rcutorture: Create CFcommon file for common Kconfig parameters
rcutorture: Create config files for scripted test-the-test testing
rcutorture: Add an rcu_busted to test the test
locktorture: Add a lock-torture kernel module
rcutorture: Abstract kvm-recheck.sh
...
Diffstat (limited to 'include/linux/rcupdate.h')
-rw-r--r-- | include/linux/rcupdate.h | 94 |
1 files changed, 48 insertions, 46 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index adff3c99dcaa..00a7fd61b3c6 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. */ |