1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/types.h>
34#include <linux/kernel.h>
35#include <linux/init.h>
36#include <linux/spinlock.h>
37#include <linux/smp.h>
38#include <linux/interrupt.h>
39#include <linux/sched.h>
40#include <asm/atomic.h>
41#include <asm/bitops.h>
42#include <linux/module.h>
43#include <linux/completion.h>
44#include <linux/moduleparam.h>
45#include <linux/percpu.h>
46#include <linux/notifier.h>
47#include <linux/rcupdate.h>
48#include <linux/cpu.h>
49
50
51struct rcu_ctrlblk rcu_ctrlblk =
52 { .cur = -300, .completed = -300 , .lock = SEQCNT_ZERO };
53struct rcu_ctrlblk rcu_bh_ctrlblk =
54 { .cur = -300, .completed = -300 , .lock = SEQCNT_ZERO };
55
56
57struct rcu_state {
58 spinlock_t lock;
59 cpumask_t cpumask;
60
61};
62
63struct rcu_state rcu_state ____cacheline_maxaligned_in_smp =
64 {.lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE };
65struct rcu_state rcu_bh_state ____cacheline_maxaligned_in_smp =
66 {.lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE };
67
68DEFINE_PER_CPU(struct rcu_data, rcu_data) = { 0L };
69DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L };
70
71
72static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL};
73static int maxbatch = 10;
74
75
76
77
78
79
80
81
82
83
84
85
86void fastcall call_rcu(struct rcu_head *head,
87 void (*func)(struct rcu_head *rcu))
88{
89 unsigned long flags;
90 struct rcu_data *rdp;
91
92 head->func = func;
93 head->next = NULL;
94 local_irq_save(flags);
95 rdp = &__get_cpu_var(rcu_data);
96 *rdp->nxttail = head;
97 rdp->nxttail = &head->next;
98 local_irq_restore(flags);
99}
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117void fastcall call_rcu_bh(struct rcu_head *head,
118 void (*func)(struct rcu_head *rcu))
119{
120 unsigned long flags;
121 struct rcu_data *rdp;
122
123 head->func = func;
124 head->next = NULL;
125 local_irq_save(flags);
126 rdp = &__get_cpu_var(rcu_bh_data);
127 *rdp->nxttail = head;
128 rdp->nxttail = &head->next;
129 local_irq_restore(flags);
130}
131
132
133
134
135
136static void rcu_do_batch(struct rcu_data *rdp)
137{
138 struct rcu_head *next, *list;
139 int count = 0;
140
141 list = rdp->donelist;
142 while (list) {
143 next = rdp->donelist = list->next;
144 list->func(list);
145 list = next;
146 if (++count >= maxbatch)
147 break;
148 }
149 if (!rdp->donelist)
150 rdp->donetail = &rdp->donelist;
151 else
152 tasklet_schedule(&per_cpu(rcu_tasklet, rdp->cpu));
153}
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178static void rcu_start_batch(struct rcu_ctrlblk *rcp, struct rcu_state *rsp,
179 int next_pending)
180{
181 if (next_pending)
182 rcp->next_pending = 1;
183
184 if (rcp->next_pending &&
185 rcp->completed == rcp->cur) {
186
187 cpus_andnot(rsp->cpumask, cpu_online_map, nohz_cpu_mask);
188 write_seqcount_begin(&rcp->lock);
189 rcp->next_pending = 0;
190 rcp->cur++;
191 write_seqcount_end(&rcp->lock);
192 }
193}
194
195
196
197
198
199
200static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp, struct rcu_state *rsp)
201{
202 cpu_clear(cpu, rsp->cpumask);
203 if (cpus_empty(rsp->cpumask)) {
204
205 rcp->completed = rcp->cur;
206 rcu_start_batch(rcp, rsp, 0);
207 }
208}
209
210
211
212
213
214
215static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp,
216 struct rcu_state *rsp, struct rcu_data *rdp)
217{
218 if (rdp->quiescbatch != rcp->cur) {
219
220 rdp->qs_pending = 1;
221 rdp->last_qsctr = rdp->qsctr;
222 rdp->quiescbatch = rcp->cur;
223 return;
224 }
225
226
227
228
229
230 if (!rdp->qs_pending)
231 return;
232
233
234
235
236
237
238 if (rdp->qsctr == rdp->last_qsctr)
239 return;
240 rdp->qs_pending = 0;
241
242 spin_lock(&rsp->lock);
243
244
245
246
247 if (likely(rdp->quiescbatch == rcp->cur))
248 cpu_quiet(rdp->cpu, rcp, rsp);
249
250 spin_unlock(&rsp->lock);
251}
252
253
254#ifdef CONFIG_HOTPLUG_CPU
255
256
257
258
259
260static void rcu_move_batch(struct rcu_data *this_rdp, struct rcu_head *list,
261 struct rcu_head **tail)
262{
263 local_irq_disable();
264 *this_rdp->nxttail = list;
265 if (list)
266 this_rdp->nxttail = tail;
267 local_irq_enable();
268}
269
270static void __rcu_offline_cpu(struct rcu_data *this_rdp,
271 struct rcu_ctrlblk *rcp, struct rcu_state *rsp, struct rcu_data *rdp)
272{
273
274
275
276
277 spin_lock_bh(&rsp->lock);
278 if (rcp->cur != rcp->completed)
279 cpu_quiet(rdp->cpu, rcp, rsp);
280 spin_unlock_bh(&rsp->lock);
281 rcu_move_batch(this_rdp, rdp->curlist, rdp->curtail);
282 rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail);
283
284}
285static void rcu_offline_cpu(int cpu)
286{
287 struct rcu_data *this_rdp = &get_cpu_var(rcu_data);
288 struct rcu_data *this_bh_rdp = &get_cpu_var(rcu_bh_data);
289
290 __rcu_offline_cpu(this_rdp, &rcu_ctrlblk, &rcu_state,
291 &per_cpu(rcu_data, cpu));
292 __rcu_offline_cpu(this_bh_rdp, &rcu_bh_ctrlblk, &rcu_bh_state,
293 &per_cpu(rcu_bh_data, cpu));
294 put_cpu_var(rcu_data);
295 put_cpu_var(rcu_bh_data);
296 tasklet_kill_immediate(&per_cpu(rcu_tasklet, cpu), cpu);
297}
298
299#else
300
301static void rcu_offline_cpu(int cpu)
302{
303}
304
305#endif
306
307
308
309
310static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp,
311 struct rcu_state *rsp, struct rcu_data *rdp)
312{
313 if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch)) {
314 *rdp->donetail = rdp->curlist;
315 rdp->donetail = rdp->curtail;
316 rdp->curlist = NULL;
317 rdp->curtail = &rdp->curlist;
318 }
319
320 local_irq_disable();
321 if (rdp->nxtlist && !rdp->curlist) {
322 int next_pending, seq;
323
324 rdp->curlist = rdp->nxtlist;
325 rdp->curtail = rdp->nxttail;
326 rdp->nxtlist = NULL;
327 rdp->nxttail = &rdp->nxtlist;
328 local_irq_enable();
329
330
331
332
333 do {
334 seq = read_seqcount_begin(&rcp->lock);
335
336 rdp->batch = rcp->cur + 1;
337 next_pending = rcp->next_pending;
338 } while (read_seqcount_retry(&rcp->lock, seq));
339
340 if (!next_pending) {
341
342 spin_lock(&rsp->lock);
343 rcu_start_batch(rcp, rsp, 1);
344 spin_unlock(&rsp->lock);
345 }
346 } else {
347 local_irq_enable();
348 }
349 rcu_check_quiescent_state(rcp, rsp, rdp);
350 if (rdp->donelist)
351 rcu_do_batch(rdp);
352}
353
354static void rcu_process_callbacks(unsigned long unused)
355{
356 __rcu_process_callbacks(&rcu_ctrlblk, &rcu_state,
357 &__get_cpu_var(rcu_data));
358 __rcu_process_callbacks(&rcu_bh_ctrlblk, &rcu_bh_state,
359 &__get_cpu_var(rcu_bh_data));
360}
361
362void rcu_check_callbacks(int cpu, int user)
363{
364 if (user ||
365 (idle_cpu(cpu) && !in_softirq() &&
366 hardirq_count() <= (1 << HARDIRQ_SHIFT))) {
367 rcu_qsctr_inc(cpu);
368 rcu_bh_qsctr_inc(cpu);
369 } else if (!in_softirq())
370 rcu_bh_qsctr_inc(cpu);
371 tasklet_schedule(&per_cpu(rcu_tasklet, cpu));
372}
373
374static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp,
375 struct rcu_data *rdp)
376{
377 memset(rdp, 0, sizeof(*rdp));
378 rdp->curtail = &rdp->curlist;
379 rdp->nxttail = &rdp->nxtlist;
380 rdp->donetail = &rdp->donelist;
381 rdp->quiescbatch = rcp->completed;
382 rdp->qs_pending = 0;
383 rdp->cpu = cpu;
384}
385
386static void __devinit rcu_online_cpu(int cpu)
387{
388 struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
389 struct rcu_data *bh_rdp = &per_cpu(rcu_bh_data, cpu);
390
391 rcu_init_percpu_data(cpu, &rcu_ctrlblk, rdp);
392 rcu_init_percpu_data(cpu, &rcu_bh_ctrlblk, bh_rdp);
393 tasklet_init(&per_cpu(rcu_tasklet, cpu), rcu_process_callbacks, 0UL);
394}
395
396static int __devinit rcu_cpu_notify(struct notifier_block *self,
397 unsigned long action, void *hcpu)
398{
399 long cpu = (long)hcpu;
400 switch (action) {
401 case CPU_UP_PREPARE:
402 rcu_online_cpu(cpu);
403 break;
404 case CPU_DEAD:
405 rcu_offline_cpu(cpu);
406 break;
407 default:
408 break;
409 }
410 return NOTIFY_OK;
411}
412
413static struct notifier_block __devinitdata rcu_nb = {
414 .notifier_call = rcu_cpu_notify,
415};
416
417
418
419
420
421
422
423void __init rcu_init(void)
424{
425 rcu_cpu_notify(&rcu_nb, CPU_UP_PREPARE,
426 (void *)(long)smp_processor_id());
427
428 register_cpu_notifier(&rcu_nb);
429}
430
431struct rcu_synchronize {
432 struct rcu_head head;
433 struct completion completion;
434};
435
436
437static void wakeme_after_rcu(struct rcu_head *head)
438{
439 struct rcu_synchronize *rcu;
440
441 rcu = container_of(head, struct rcu_synchronize, head);
442 complete(&rcu->completion);
443}
444
445
446
447
448
449
450
451
452
453
454void synchronize_kernel(void)
455{
456 struct rcu_synchronize rcu;
457
458 init_completion(&rcu.completion);
459
460 call_rcu(&rcu.head, wakeme_after_rcu);
461
462
463 wait_for_completion(&rcu.completion);
464}
465
466module_param(maxbatch, int, 0);
467EXPORT_SYMBOL(call_rcu);
468EXPORT_SYMBOL(call_rcu_bh);
469EXPORT_SYMBOL(synchronize_kernel);
470