diff options
| author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2011-05-27 01:14:36 -0400 |
|---|---|---|
| committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2011-09-29 00:36:42 -0400 |
| commit | 2c42818e962e2858334bf45bfc56662b3752df34 (patch) | |
| tree | 192364123c9aeeab282c53168e51eddece9d8be4 /include/linux | |
| parent | f039d1f1884b2fe9c13d28f59d8330f0b0518fc4 (diff) | |
rcu: Abstract common code for RCU grace-period-wait primitives
Pull the code that waits for an RCU grace period into a single function,
which is then called by synchronize_rcu() and friends in the case of
TREE_RCU and TREE_PREEMPT_RCU, and from rcu_barrier() and friends in
the case of TINY_RCU and TINY_PREEMPT_RCU.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/rcupdate.h | 130 | ||||
| -rw-r--r-- | include/linux/rcutiny.h | 16 | ||||
| -rw-r--r-- | include/linux/rcutree.h | 2 |
3 files changed, 90 insertions, 58 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 87bd390df73f..ae5327de41aa 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
| @@ -66,11 +66,73 @@ static inline void rcutorture_record_progress(unsigned long vernum) | |||
| 66 | #define ULONG_CMP_LT(a, b) (ULONG_MAX / 2 < (a) - (b)) | 66 | #define ULONG_CMP_LT(a, b) (ULONG_MAX / 2 < (a) - (b)) |
| 67 | 67 | ||
| 68 | /* Exported common interfaces */ | 68 | /* Exported common interfaces */ |
| 69 | |||
| 70 | #ifdef CONFIG_PREEMPT_RCU | ||
| 71 | |||
| 72 | /** | ||
| 73 | * call_rcu() - Queue an RCU callback for invocation after a grace period. | ||
| 74 | * @head: structure to be used for queueing the RCU updates. | ||
| 75 | * @func: actual callback function to be invoked after the grace period | ||
| 76 | * | ||
| 77 | * The callback function will be invoked some time after a full grace | ||
| 78 | * period elapses, in other words after all pre-existing RCU read-side | ||
| 79 | * critical sections have completed. However, the callback function | ||
| 80 | * might well execute concurrently with RCU read-side critical sections | ||
| 81 | * that started after call_rcu() was invoked. RCU read-side critical | ||
| 82 | * sections are delimited by rcu_read_lock() and rcu_read_unlock(), | ||
| 83 | * and may be nested. | ||
| 84 | */ | ||
| 85 | extern void call_rcu(struct rcu_head *head, | ||
| 86 | void (*func)(struct rcu_head *head)); | ||
| 87 | |||
| 88 | #else /* #ifdef CONFIG_PREEMPT_RCU */ | ||
| 89 | |||
| 90 | /* In classic RCU, call_rcu() is just call_rcu_sched(). */ | ||
| 91 | #define call_rcu call_rcu_sched | ||
| 92 | |||
| 93 | #endif /* #else #ifdef CONFIG_PREEMPT_RCU */ | ||
| 94 | |||
| 95 | /** | ||
| 96 | * call_rcu_bh() - Queue an RCU for invocation after a quicker grace period. | ||
| 97 | * @head: structure to be used for queueing the RCU updates. | ||
| 98 | * @func: actual callback function to be invoked after the grace period | ||
| 99 | * | ||
| 100 | * The callback function will be invoked some time after a full grace | ||
| 101 | * period elapses, in other words after all currently executing RCU | ||
| 102 | * read-side critical sections have completed. call_rcu_bh() assumes | ||
| 103 | * that the read-side critical sections end on completion of a softirq | ||
| 104 | * handler. This means that read-side critical sections in process | ||
| 105 | * context must not be interrupted by softirqs. This interface is to be | ||
| 106 | * used when most of the read-side critical sections are in softirq context. | ||
| 107 | * RCU read-side critical sections are delimited by : | ||
| 108 | * - rcu_read_lock() and rcu_read_unlock(), if in interrupt context. | ||
| 109 | * OR | ||
| 110 | * - rcu_read_lock_bh() and rcu_read_unlock_bh(), if in process context. | ||
| 111 | * These may be nested. | ||
| 112 | */ | ||
| 113 | extern void call_rcu_bh(struct rcu_head *head, | ||
| 114 | void (*func)(struct rcu_head *head)); | ||
| 115 | |||
| 116 | /** | ||
| 117 | * call_rcu_sched() - Queue an RCU for invocation after sched grace period. | ||
| 118 | * @head: structure to be used for queueing the RCU updates. | ||
| 119 | * @func: actual callback function to be invoked after the grace period | ||
| 120 | * | ||
| 121 | * The callback function will be invoked some time after a full grace | ||
| 122 | * period elapses, in other words after all currently executing RCU | ||
| 123 | * read-side critical sections have completed. call_rcu_sched() assumes | ||
| 124 | * that the read-side critical sections end on enabling of preemption | ||
| 125 | * or on voluntary preemption. | ||
| 126 | * RCU read-side critical sections are delimited by : | ||
| 127 | * - rcu_read_lock_sched() and rcu_read_unlock_sched(), | ||
| 128 | * OR | ||
| 129 | * anything that disables preemption. | ||
| 130 | * These may be nested. | ||
| 131 | */ | ||
| 69 | extern void call_rcu_sched(struct rcu_head *head, | 132 | extern void call_rcu_sched(struct rcu_head *head, |
| 70 | void (*func)(struct rcu_head *rcu)); | 133 | void (*func)(struct rcu_head *rcu)); |
| 134 | |||
| 71 | extern void synchronize_sched(void); | 135 | extern void synchronize_sched(void); |
| 72 | extern void rcu_barrier_bh(void); | ||
| 73 | extern void rcu_barrier_sched(void); | ||
| 74 | 136 | ||
| 75 | static inline void __rcu_read_lock_bh(void) | 137 | static inline void __rcu_read_lock_bh(void) |
| 76 | { | 138 | { |
| @@ -143,6 +205,15 @@ static inline void rcu_exit_nohz(void) | |||
| 143 | 205 | ||
| 144 | #endif /* #else #ifdef CONFIG_NO_HZ */ | 206 | #endif /* #else #ifdef CONFIG_NO_HZ */ |
| 145 | 207 | ||
| 208 | /* | ||
| 209 | * Infrastructure to implement the synchronize_() primitives in | ||
| 210 | * TREE_RCU and rcu_barrier_() primitives in TINY_RCU. | ||
| 211 | */ | ||
| 212 | |||
| 213 | typedef void call_rcu_func_t(struct rcu_head *head, | ||
| 214 | void (*func)(struct rcu_head *head)); | ||
| 215 | void wait_rcu_gp(call_rcu_func_t crf); | ||
| 216 | |||
| 146 | #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) | 217 | #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) |
| 147 | #include <linux/rcutree.h> | 218 | #include <linux/rcutree.h> |
| 148 | #elif defined(CONFIG_TINY_RCU) || defined(CONFIG_TINY_PREEMPT_RCU) | 219 | #elif defined(CONFIG_TINY_RCU) || defined(CONFIG_TINY_PREEMPT_RCU) |
| @@ -723,61 +794,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) | |||
| 723 | #define RCU_INIT_POINTER(p, v) \ | 794 | #define RCU_INIT_POINTER(p, v) \ |
| 724 | p = (typeof(*v) __force __rcu *)(v) | 795 | p = (typeof(*v) __force __rcu *)(v) |
| 725 | 796 | ||
| 726 | /* Infrastructure to implement the synchronize_() primitives. */ | ||
| 727 | |||
| 728 | struct rcu_synchronize { | ||
| 729 | struct rcu_head head; | ||
| 730 | struct completion completion; | ||
| 731 | }; | ||
| 732 | |||
| 733 | extern void wakeme_after_rcu(struct rcu_head *head); | ||
| 734 | |||
| 735 | #ifdef CONFIG_PREEMPT_RCU | ||
| 736 | |||
| 737 | /** | ||
| 738 | * call_rcu() - Queue an RCU callback for invocation after a grace period. | ||
| 739 | * @head: structure to be used for queueing the RCU updates. | ||
| 740 | * @func: actual callback function to be invoked after the grace period | ||
| 741 | * | ||
| 742 | * The callback function will be invoked some time after a full grace | ||
| 743 | * period elapses, in other words after all pre-existing RCU read-side | ||
| 744 | * critical sections have completed. However, the callback function | ||
| 745 | * might well execute concurrently with RCU read-side critical sections | ||
| 746 | * that started after call_rcu() was invoked. RCU read-side critical | ||
| 747 | * sections are delimited by rcu_read_lock() and rcu_read_unlock(), | ||
| 748 | * and may be nested. | ||
| 749 | */ | ||
| 750 | extern void call_rcu(struct rcu_head *head, | ||
| 751 | void (*func)(struct rcu_head *head)); | ||
| 752 | |||
| 753 | #else /* #ifdef CONFIG_PREEMPT_RCU */ | ||
| 754 | |||
| 755 | /* In classic RCU, call_rcu() is just call_rcu_sched(). */ | ||
| 756 | #define call_rcu call_rcu_sched | ||
| 757 | |||
| 758 | #endif /* #else #ifdef CONFIG_PREEMPT_RCU */ | ||
| 759 | |||
| 760 | /** | ||
| 761 | * call_rcu_bh() - Queue an RCU for invocation after a quicker grace period. | ||
| 762 | * @head: structure to be used for queueing the RCU updates. | ||
| 763 | * @func: actual callback function to be invoked after the grace period | ||
| 764 | * | ||
| 765 | * The callback function will be invoked some time after a full grace | ||
| 766 | * period elapses, in other words after all currently executing RCU | ||
| 767 | * read-side critical sections have completed. call_rcu_bh() assumes | ||
| 768 | * that the read-side critical sections end on completion of a softirq | ||
| 769 | * handler. This means that read-side critical sections in process | ||
| 770 | * context must not be interrupted by softirqs. This interface is to be | ||
| 771 | * used when most of the read-side critical sections are in softirq context. | ||
| 772 | * RCU read-side critical sections are delimited by : | ||
| 773 | * - rcu_read_lock() and rcu_read_unlock(), if in interrupt context. | ||
| 774 | * OR | ||
| 775 | * - rcu_read_lock_bh() and rcu_read_unlock_bh(), if in process context. | ||
| 776 | * These may be nested. | ||
| 777 | */ | ||
| 778 | extern void call_rcu_bh(struct rcu_head *head, | ||
| 779 | void (*func)(struct rcu_head *head)); | ||
| 780 | |||
| 781 | /* | 797 | /* |
| 782 | * debug_rcu_head_queue()/debug_rcu_head_unqueue() are used internally | 798 | * debug_rcu_head_queue()/debug_rcu_head_unqueue() are used internally |
| 783 | * by call_rcu() and rcu callback execution, and are therefore not part of the | 799 | * by call_rcu() and rcu callback execution, and are therefore not part of the |
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index 52b3e0281fd0..4eab233a00cd 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h | |||
| @@ -31,6 +31,16 @@ static inline void rcu_init(void) | |||
| 31 | { | 31 | { |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | static inline void rcu_barrier_bh(void) | ||
| 35 | { | ||
| 36 | wait_rcu_gp(call_rcu_bh); | ||
| 37 | } | ||
| 38 | |||
| 39 | static inline void rcu_barrier_sched(void) | ||
| 40 | { | ||
| 41 | wait_rcu_gp(call_rcu_sched); | ||
| 42 | } | ||
| 43 | |||
| 34 | #ifdef CONFIG_TINY_RCU | 44 | #ifdef CONFIG_TINY_RCU |
| 35 | 45 | ||
| 36 | static inline void synchronize_rcu_expedited(void) | 46 | static inline void synchronize_rcu_expedited(void) |
| @@ -45,9 +55,13 @@ static inline void rcu_barrier(void) | |||
| 45 | 55 | ||
| 46 | #else /* #ifdef CONFIG_TINY_RCU */ | 56 | #else /* #ifdef CONFIG_TINY_RCU */ |
| 47 | 57 | ||
| 48 | void rcu_barrier(void); | ||
| 49 | void synchronize_rcu_expedited(void); | 58 | void synchronize_rcu_expedited(void); |
| 50 | 59 | ||
| 60 | static inline void rcu_barrier(void) | ||
| 61 | { | ||
| 62 | wait_rcu_gp(call_rcu); | ||
| 63 | } | ||
| 64 | |||
| 51 | #endif /* #else #ifdef CONFIG_TINY_RCU */ | 65 | #endif /* #else #ifdef CONFIG_TINY_RCU */ |
| 52 | 66 | ||
| 53 | static inline void synchronize_rcu_bh(void) | 67 | static inline void synchronize_rcu_bh(void) |
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index e65d06634dd8..67458468f1a8 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h | |||
| @@ -67,6 +67,8 @@ static inline void synchronize_rcu_bh_expedited(void) | |||
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | extern void rcu_barrier(void); | 69 | extern void rcu_barrier(void); |
| 70 | extern void rcu_barrier_bh(void); | ||
| 71 | extern void rcu_barrier_sched(void); | ||
| 70 | 72 | ||
| 71 | extern unsigned long rcutorture_testseq; | 73 | extern unsigned long rcutorture_testseq; |
| 72 | extern unsigned long rcutorture_vernum; | 74 | extern unsigned long rcutorture_vernum; |
