diff options
| author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2009-09-13 12:15:11 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-09-17 18:06:53 -0400 |
| commit | 16e3081191837a6a04733de5cd5d1d1b303140d4 (patch) | |
| tree | 6b64a4613b9ac57da30518626a259b6aeeef4944 | |
| parent | c3422bea5f09b0e85704f51f2b01271630b8940b (diff) | |
rcu: Fix synchronize_rcu() for TREE_PREEMPT_RCU
The redirection of synchronize_sched() to synchronize_rcu() was
appropriate for TREE_RCU, but not for TREE_PREEMPT_RCU.
Fix this by creating an underlying synchronize_sched(). TREE_RCU
then redirects synchronize_rcu() to synchronize_sched(), while
TREE_PREEMPT_RCU has its own version of synchronize_rcu().
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: laijs@cn.fujitsu.com
Cc: dipankar@in.ibm.com
Cc: akpm@linux-foundation.org
Cc: mathieu.desnoyers@polymtl.ca
Cc: josh@joshtriplett.org
Cc: dvhltc@us.ibm.com
Cc: niv@us.ibm.com
Cc: peterz@infradead.org
Cc: rostedt@goodmis.org
Cc: Valdis.Kletnieks@vt.edu
LKML-Reference: <12528585111916-git-send-email->
Signed-off-by: Ingo Molnar <mingo@elte.hu>
| -rw-r--r-- | include/linux/rcupdate.h | 23 | ||||
| -rw-r--r-- | include/linux/rcutree.h | 4 | ||||
| -rw-r--r-- | kernel/rcupdate.c | 44 |
3 files changed, 50 insertions, 21 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 95e0615f4d7..39dce83c486 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
| @@ -52,8 +52,13 @@ struct rcu_head { | |||
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | /* Exported common interfaces */ | 54 | /* Exported common interfaces */ |
| 55 | #ifdef CONFIG_TREE_PREEMPT_RCU | ||
| 55 | extern void synchronize_rcu(void); | 56 | extern void synchronize_rcu(void); |
| 57 | #else /* #ifdef CONFIG_TREE_PREEMPT_RCU */ | ||
| 58 | #define synchronize_rcu synchronize_sched | ||
| 59 | #endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */ | ||
| 56 | extern void synchronize_rcu_bh(void); | 60 | extern void synchronize_rcu_bh(void); |
| 61 | extern void synchronize_sched(void); | ||
| 57 | extern void rcu_barrier(void); | 62 | extern void rcu_barrier(void); |
| 58 | extern void rcu_barrier_bh(void); | 63 | extern void rcu_barrier_bh(void); |
| 59 | extern void rcu_barrier_sched(void); | 64 | extern void rcu_barrier_sched(void); |
| @@ -262,24 +267,6 @@ struct rcu_synchronize { | |||
| 262 | extern void wakeme_after_rcu(struct rcu_head *head); | 267 | extern void wakeme_after_rcu(struct rcu_head *head); |
| 263 | 268 | ||
| 264 | /** | 269 | /** |
| 265 | * synchronize_sched - block until all CPUs have exited any non-preemptive | ||
| 266 | * kernel code sequences. | ||
| 267 | * | ||
| 268 | * This means that all preempt_disable code sequences, including NMI and | ||
| 269 | * hardware-interrupt handlers, in progress on entry will have completed | ||
| 270 | * before this primitive returns. However, this does not guarantee that | ||
| 271 | * softirq handlers will have completed, since in some kernels, these | ||
| 272 | * handlers can run in process context, and can block. | ||
| 273 | * | ||
| 274 | * This primitive provides the guarantees made by the (now removed) | ||
| 275 | * synchronize_kernel() API. In contrast, synchronize_rcu() only | ||
| 276 | * guarantees that rcu_read_lock() sections will have completed. | ||
| 277 | * In "classic RCU", these two guarantees happen to be one and | ||
| 278 | * the same, but can differ in realtime RCU implementations. | ||
| 279 | */ | ||
| 280 | #define synchronize_sched() __synchronize_sched() | ||
| 281 | |||
| 282 | /** | ||
| 283 | * call_rcu - Queue an RCU callback for invocation after a grace period. | 270 | * call_rcu - Queue an RCU callback for invocation after a grace period. |
| 284 | * @head: structure to be used for queueing the RCU updates. | 271 | * @head: structure to be used for queueing the RCU updates. |
| 285 | * @func: actual update function to be invoked after the grace period | 272 | * @func: actual update function to be invoked after the grace period |
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index a8930771782..00d08c0cbcc 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h | |||
| @@ -53,6 +53,8 @@ static inline void __rcu_read_unlock(void) | |||
| 53 | preempt_enable(); | 53 | preempt_enable(); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | #define __synchronize_sched() synchronize_rcu() | ||
| 57 | |||
| 56 | static inline void exit_rcu(void) | 58 | static inline void exit_rcu(void) |
| 57 | { | 59 | { |
| 58 | } | 60 | } |
| @@ -68,8 +70,6 @@ static inline void __rcu_read_unlock_bh(void) | |||
| 68 | local_bh_enable(); | 70 | local_bh_enable(); |
| 69 | } | 71 | } |
| 70 | 72 | ||
| 71 | #define __synchronize_sched() synchronize_rcu() | ||
| 72 | |||
| 73 | extern void call_rcu_sched(struct rcu_head *head, | 73 | extern void call_rcu_sched(struct rcu_head *head, |
| 74 | void (*func)(struct rcu_head *rcu)); | 74 | void (*func)(struct rcu_head *rcu)); |
| 75 | 75 | ||
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index bd5d5c8e514..28d2f24e787 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
| @@ -74,6 +74,8 @@ void wakeme_after_rcu(struct rcu_head *head) | |||
| 74 | complete(&rcu->completion); | 74 | complete(&rcu->completion); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | #ifdef CONFIG_TREE_PREEMPT_RCU | ||
| 78 | |||
| 77 | /** | 79 | /** |
| 78 | * synchronize_rcu - wait until a grace period has elapsed. | 80 | * synchronize_rcu - wait until a grace period has elapsed. |
| 79 | * | 81 | * |
| @@ -87,7 +89,7 @@ void synchronize_rcu(void) | |||
| 87 | { | 89 | { |
| 88 | struct rcu_synchronize rcu; | 90 | struct rcu_synchronize rcu; |
| 89 | 91 | ||
| 90 | if (rcu_blocking_is_gp()) | 92 | if (!rcu_scheduler_active) |
| 91 | return; | 93 | return; |
| 92 | 94 | ||
| 93 | init_completion(&rcu.completion); | 95 | init_completion(&rcu.completion); |
| @@ -98,6 +100,46 @@ void synchronize_rcu(void) | |||
| 98 | } | 100 | } |
| 99 | EXPORT_SYMBOL_GPL(synchronize_rcu); | 101 | EXPORT_SYMBOL_GPL(synchronize_rcu); |
| 100 | 102 | ||
| 103 | #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ | ||
| 104 | |||
| 105 | /** | ||
| 106 | * synchronize_sched - wait until an rcu-sched grace period has elapsed. | ||
| 107 | * | ||
| 108 | * Control will return to the caller some time after a full rcu-sched | ||
| 109 | * grace period has elapsed, in other words after all currently executing | ||
| 110 | * rcu-sched read-side critical sections have completed. These read-side | ||
| 111 | * critical sections are delimited by rcu_read_lock_sched() and | ||
| 112 | * rcu_read_unlock_sched(), and may be nested. Note that preempt_disable(), | ||
| 113 | * local_irq_disable(), and so on may be used in place of | ||
| 114 | * rcu_read_lock_sched(). | ||
| 115 | * | ||
| 116 | * This means that all preempt_disable code sequences, including NMI and | ||
| 117 | * hardware-interrupt handlers, in progress on entry will have completed | ||
| 118 | * before this primitive returns. However, this does not guarantee that | ||
| 119 | * softirq handlers will have completed, since in some kernels, these | ||
| 120 | * handlers can run in process context, and can block. | ||
| 121 | * | ||
| 122 | * This primitive provides the guarantees made by the (now removed) | ||
| 123 | * synchronize_kernel() API. In contrast, synchronize_rcu() only | ||
| 124 | * guarantees that rcu_read_lock() sections will have completed. | ||
| 125 | * In "classic RCU", these two guarantees happen to be one and | ||
| 126 | * the same, but can differ in realtime RCU implementations. | ||
| 127 | */ | ||
| 128 | void synchronize_sched(void) | ||
| 129 | { | ||
| 130 | struct rcu_synchronize rcu; | ||
| 131 | |||
| 132 | if (rcu_blocking_is_gp()) | ||
| 133 | return; | ||
| 134 | |||
| 135 | init_completion(&rcu.completion); | ||
| 136 | /* Will wake me after RCU finished. */ | ||
| 137 | call_rcu_sched(&rcu.head, wakeme_after_rcu); | ||
| 138 | /* Wait for it. */ | ||
| 139 | wait_for_completion(&rcu.completion); | ||
| 140 | } | ||
| 141 | EXPORT_SYMBOL_GPL(synchronize_sched); | ||
| 142 | |||
| 101 | /** | 143 | /** |
| 102 | * synchronize_rcu_bh - wait until an rcu_bh grace period has elapsed. | 144 | * synchronize_rcu_bh - wait until an rcu_bh grace period has elapsed. |
| 103 | * | 145 | * |
