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; |