diff options
Diffstat (limited to 'kernel/rcupdate.c')
-rw-r--r-- | kernel/rcupdate.c | 179 |
1 files changed, 160 insertions, 19 deletions
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 49d808e833b0..4d169835fb36 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/cpu.h> | 44 | #include <linux/cpu.h> |
45 | #include <linux/mutex.h> | 45 | #include <linux/mutex.h> |
46 | #include <linux/module.h> | 46 | #include <linux/module.h> |
47 | #include <linux/kernel_stat.h> | ||
48 | #include <linux/hardirq.h> | 47 | #include <linux/hardirq.h> |
49 | 48 | ||
50 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 49 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
@@ -64,9 +63,6 @@ struct lockdep_map rcu_sched_lock_map = | |||
64 | EXPORT_SYMBOL_GPL(rcu_sched_lock_map); | 63 | EXPORT_SYMBOL_GPL(rcu_sched_lock_map); |
65 | #endif | 64 | #endif |
66 | 65 | ||
67 | int rcu_scheduler_active __read_mostly; | ||
68 | EXPORT_SYMBOL_GPL(rcu_scheduler_active); | ||
69 | |||
70 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 66 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
71 | 67 | ||
72 | int debug_lockdep_rcu_enabled(void) | 68 | int debug_lockdep_rcu_enabled(void) |
@@ -97,21 +93,6 @@ EXPORT_SYMBOL_GPL(rcu_read_lock_bh_held); | |||
97 | #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ | 93 | #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ |
98 | 94 | ||
99 | /* | 95 | /* |
100 | * This function is invoked towards the end of the scheduler's initialization | ||
101 | * process. Before this is called, the idle task might contain | ||
102 | * RCU read-side critical sections (during which time, this idle | ||
103 | * task is booting the system). After this function is called, the | ||
104 | * idle tasks are prohibited from containing RCU read-side critical | ||
105 | * sections. | ||
106 | */ | ||
107 | void rcu_scheduler_starting(void) | ||
108 | { | ||
109 | WARN_ON(num_online_cpus() != 1); | ||
110 | WARN_ON(nr_context_switches() > 0); | ||
111 | rcu_scheduler_active = 1; | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * Awaken the corresponding synchronize_rcu() instance now that a | 96 | * Awaken the corresponding synchronize_rcu() instance now that a |
116 | * grace period has elapsed. | 97 | * grace period has elapsed. |
117 | */ | 98 | */ |
@@ -133,3 +114,163 @@ int rcu_my_thread_group_empty(void) | |||
133 | } | 114 | } |
134 | EXPORT_SYMBOL_GPL(rcu_my_thread_group_empty); | 115 | EXPORT_SYMBOL_GPL(rcu_my_thread_group_empty); |
135 | #endif /* #ifdef CONFIG_PROVE_RCU */ | 116 | #endif /* #ifdef CONFIG_PROVE_RCU */ |
117 | |||
118 | #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD | ||
119 | static inline void debug_init_rcu_head(struct rcu_head *head) | ||
120 | { | ||
121 | debug_object_init(head, &rcuhead_debug_descr); | ||
122 | } | ||
123 | |||
124 | static inline void debug_rcu_head_free(struct rcu_head *head) | ||
125 | { | ||
126 | debug_object_free(head, &rcuhead_debug_descr); | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * fixup_init is called when: | ||
131 | * - an active object is initialized | ||
132 | */ | ||
133 | static int rcuhead_fixup_init(void *addr, enum debug_obj_state state) | ||
134 | { | ||
135 | struct rcu_head *head = addr; | ||
136 | |||
137 | switch (state) { | ||
138 | case ODEBUG_STATE_ACTIVE: | ||
139 | /* | ||
140 | * Ensure that queued callbacks are all executed. | ||
141 | * If we detect that we are nested in a RCU read-side critical | ||
142 | * section, we should simply fail, otherwise we would deadlock. | ||
143 | */ | ||
144 | if (rcu_preempt_depth() != 0 || preempt_count() != 0 || | ||
145 | irqs_disabled()) { | ||
146 | WARN_ON(1); | ||
147 | return 0; | ||
148 | } | ||
149 | rcu_barrier(); | ||
150 | rcu_barrier_sched(); | ||
151 | rcu_barrier_bh(); | ||
152 | debug_object_init(head, &rcuhead_debug_descr); | ||
153 | return 1; | ||
154 | default: | ||
155 | return 0; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * fixup_activate is called when: | ||
161 | * - an active object is activated | ||
162 | * - an unknown object is activated (might be a statically initialized object) | ||
163 | * Activation is performed internally by call_rcu(). | ||
164 | */ | ||
165 | static int rcuhead_fixup_activate(void *addr, enum debug_obj_state state) | ||
166 | { | ||
167 | struct rcu_head *head = addr; | ||
168 | |||
169 | switch (state) { | ||
170 | |||
171 | case ODEBUG_STATE_NOTAVAILABLE: | ||
172 | /* | ||
173 | * This is not really a fixup. We just make sure that it is | ||
174 | * tracked in the object tracker. | ||
175 | */ | ||
176 | debug_object_init(head, &rcuhead_debug_descr); | ||
177 | debug_object_activate(head, &rcuhead_debug_descr); | ||
178 | return 0; | ||
179 | |||
180 | case ODEBUG_STATE_ACTIVE: | ||
181 | /* | ||
182 | * Ensure that queued callbacks are all executed. | ||
183 | * If we detect that we are nested in a RCU read-side critical | ||
184 | * section, we should simply fail, otherwise we would deadlock. | ||
185 | */ | ||
186 | if (rcu_preempt_depth() != 0 || preempt_count() != 0 || | ||
187 | irqs_disabled()) { | ||
188 | WARN_ON(1); | ||
189 | return 0; | ||
190 | } | ||
191 | rcu_barrier(); | ||
192 | rcu_barrier_sched(); | ||
193 | rcu_barrier_bh(); | ||
194 | debug_object_activate(head, &rcuhead_debug_descr); | ||
195 | return 1; | ||
196 | default: | ||
197 | return 0; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * fixup_free is called when: | ||
203 | * - an active object is freed | ||
204 | */ | ||
205 | static int rcuhead_fixup_free(void *addr, enum debug_obj_state state) | ||
206 | { | ||
207 | struct rcu_head *head = addr; | ||
208 | |||
209 | switch (state) { | ||
210 | case ODEBUG_STATE_ACTIVE: | ||
211 | /* | ||
212 | * Ensure that queued callbacks are all executed. | ||
213 | * If we detect that we are nested in a RCU read-side critical | ||
214 | * section, we should simply fail, otherwise we would deadlock. | ||
215 | */ | ||
216 | #ifndef CONFIG_PREEMPT | ||
217 | WARN_ON(1); | ||
218 | return 0; | ||
219 | #else | ||
220 | if (rcu_preempt_depth() != 0 || preempt_count() != 0 || | ||
221 | irqs_disabled()) { | ||
222 | WARN_ON(1); | ||
223 | return 0; | ||
224 | } | ||
225 | rcu_barrier(); | ||
226 | rcu_barrier_sched(); | ||
227 | rcu_barrier_bh(); | ||
228 | debug_object_free(head, &rcuhead_debug_descr); | ||
229 | return 1; | ||
230 | #endif | ||
231 | default: | ||
232 | return 0; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | /** | ||
237 | * init_rcu_head_on_stack() - initialize on-stack rcu_head for debugobjects | ||
238 | * @head: pointer to rcu_head structure to be initialized | ||
239 | * | ||
240 | * This function informs debugobjects of a new rcu_head structure that | ||
241 | * has been allocated as an auto variable on the stack. This function | ||
242 | * is not required for rcu_head structures that are statically defined or | ||
243 | * that are dynamically allocated on the heap. This function has no | ||
244 | * effect for !CONFIG_DEBUG_OBJECTS_RCU_HEAD kernel builds. | ||
245 | */ | ||
246 | void init_rcu_head_on_stack(struct rcu_head *head) | ||
247 | { | ||
248 | debug_object_init_on_stack(head, &rcuhead_debug_descr); | ||
249 | } | ||
250 | EXPORT_SYMBOL_GPL(init_rcu_head_on_stack); | ||
251 | |||
252 | /** | ||
253 | * destroy_rcu_head_on_stack() - destroy on-stack rcu_head for debugobjects | ||
254 | * @head: pointer to rcu_head structure to be initialized | ||
255 | * | ||
256 | * This function informs debugobjects that an on-stack rcu_head structure | ||
257 | * is about to go out of scope. As with init_rcu_head_on_stack(), this | ||
258 | * function is not required for rcu_head structures that are statically | ||
259 | * defined or that are dynamically allocated on the heap. Also as with | ||
260 | * init_rcu_head_on_stack(), this function has no effect for | ||
261 | * !CONFIG_DEBUG_OBJECTS_RCU_HEAD kernel builds. | ||
262 | */ | ||
263 | void destroy_rcu_head_on_stack(struct rcu_head *head) | ||
264 | { | ||
265 | debug_object_free(head, &rcuhead_debug_descr); | ||
266 | } | ||
267 | EXPORT_SYMBOL_GPL(destroy_rcu_head_on_stack); | ||
268 | |||
269 | struct debug_obj_descr rcuhead_debug_descr = { | ||
270 | .name = "rcu_head", | ||
271 | .fixup_init = rcuhead_fixup_init, | ||
272 | .fixup_activate = rcuhead_fixup_activate, | ||
273 | .fixup_free = rcuhead_fixup_free, | ||
274 | }; | ||
275 | EXPORT_SYMBOL_GPL(rcuhead_debug_descr); | ||
276 | #endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */ | ||