source: mainline/kernel/generic/src/synch/rcu.c@ 853d613

lfn serial ticket/834-toolchain-update topic/fix-logger-deadlock topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 853d613 was 853d613, checked in by Adam Hraska <adam.hraska+hos@…>, 14 years ago

rcu: Fixed the race of smp_call sampling functions when accessing the pending reader cpu mask in A-RCU. Added some comments.

  • Property mode set to 100644
File size: 50.2 KB
Line 
1/*
2 * Copyright (c) 2012 Adam Hraska
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29
30/** @addtogroup sync
31 * @{
32 */
33
34/**
35 * @file
36 * @brief Preemptible read-copy update. Usable from interrupt handlers.
37 */
38
39#include <synch/rcu.h>
40#include <synch/condvar.h>
41#include <synch/semaphore.h>
42#include <synch/spinlock.h>
43#include <synch/mutex.h>
44#include <proc/thread.h>
45#include <cpu/cpu_mask.h>
46#include <cpu.h>
47#include <smp/smp_call.h>
48#include <compiler/barrier.h>
49#include <atomic.h>
50#include <arch.h>
51#include <macros.h>
52
53/*
54 * Number of milliseconds to give to preexisting readers to finish
55 * when non-expedited grace period detection is in progress.
56 */
57#define DETECT_SLEEP_MS 10
58/*
59 * Max number of pending callbacks in the local cpu's queue before
60 * aggressively expediting the current grace period
61 */
62#define EXPEDITE_THRESHOLD 2000
63/*
64 * Max number of callbacks to execute in one go with preemption
65 * enabled. If there are more callbacks to be executed they will
66 * be run with preemption disabled in order to prolong reclaimer's
67 * time slice and give it a chance to catch up with callback producers.
68 */
69#define CRITICAL_THRESHOLD 30000
70/* Half the number of values a uint32 can hold. */
71#define UINT32_MAX_HALF 2147483648U
72
73/**
74 * The current grace period number. Increases monotonically.
75 * Lock rcu.gp_lock or rcu.preempt_lock to get a current value.
76 */
77rcu_gp_t _rcu_cur_gp;
78
79/** Global RCU data. */
80typedef struct rcu_data {
81 /** Detector uses so signal reclaimers that a grace period ended. */
82 condvar_t gp_ended;
83 /** Reclaimers use to notify the detector to accelerate GP detection. */
84 condvar_t expedite_now;
85 /**
86 * Protects: req_gp_end_cnt, req_expedited_cnt, completed_gp, _rcu_cur_gp;
87 * or: completed_gp, _rcu_cur_gp
88 */
89 SPINLOCK_DECLARE(gp_lock);
90 /**
91 * The number of the most recently completed grace period. At most
92 * one behind _rcu_cur_gp. If equal to _rcu_cur_gp, a grace period
93 * detection is not in progress and the detector is idle.
94 */
95 rcu_gp_t completed_gp;
96
97 /** Protects the following 3 fields. */
98 IRQ_SPINLOCK_DECLARE(preempt_lock);
99 /** Preexisting readers that have been preempted. */
100 list_t cur_preempted;
101 /** Reader that have been preempted and might delay the next grace period.*/
102 list_t next_preempted;
103 /**
104 * The detector is waiting for the last preempted reader
105 * in cur_preempted to announce that it exited its reader
106 * section by up()ing remaining_readers.
107 */
108 bool preempt_blocking_det;
109
110#ifdef RCU_PREEMPT_A
111
112 /**
113 * The detector waits on this semaphore for any preempted readers
114 * delaying the grace period once all cpus pass a quiescent state.
115 */
116 semaphore_t remaining_readers;
117
118#elif defined(RCU_PREEMPT_PODZIMEK)
119
120 /** Reclaimers notify the detector when they request more grace periods.*/
121 condvar_t req_gp_changed;
122 /** Number of grace period ends the detector was requested to announce. */
123 size_t req_gp_end_cnt;
124 /** Number of consecutive grace periods to detect quickly and aggressively.*/
125 size_t req_expedited_cnt;
126 /**
127 * Number of cpus with readers that are delaying the current GP.
128 * They will up() remaining_readers.
129 */
130 atomic_t delaying_cpu_cnt;
131 /**
132 * The detector waits on this semaphore for any readers delaying the GP.
133 *
134 * Each of the cpus with readers that are delaying the current GP
135 * must up() this sema once they reach a quiescent state. If there
136 * are any readers in cur_preempted (ie preempted preexisting) and
137 * they are already delaying GP detection, the last to unlock its
138 * reader section must up() this sema once.
139 */
140 semaphore_t remaining_readers;
141#endif
142
143 /** Excludes simultaneous rcu_barrier() calls. */
144 mutex_t barrier_mtx;
145 /** Number of cpus that we are waiting for to complete rcu_barrier(). */
146 atomic_t barrier_wait_cnt;
147 /** rcu_barrier() waits for the completion of barrier callbacks on this wq.*/
148 waitq_t barrier_wq;
149
150 /** Interruptible attached detector thread pointer. */
151 thread_t *detector_thr;
152
153 /* Some statistics. */
154 size_t stat_expedited_cnt;
155 size_t stat_delayed_cnt;
156 size_t stat_preempt_blocking_cnt;
157 /* Does not contain self/local calls. */
158 size_t stat_smp_call_cnt;
159} rcu_data_t;
160
161
162static rcu_data_t rcu;
163
164static void start_reclaimers(void);
165static void synch_complete(rcu_item_t *rcu_item);
166static inline void rcu_call_impl(bool expedite, rcu_item_t *rcu_item,
167 rcu_func_t func);
168static void add_barrier_cb(void *arg);
169static void barrier_complete(rcu_item_t *barrier_item);
170static bool arriving_cbs_empty(void);
171static bool next_cbs_empty(void);
172static bool cur_cbs_empty(void);
173static bool all_cbs_empty(void);
174static void reclaimer(void *arg);
175static bool wait_for_pending_cbs(void);
176static bool advance_cbs(void);
177static void exec_completed_cbs(rcu_gp_t last_completed_gp);
178static void exec_cbs(rcu_item_t **phead);
179static bool wait_for_cur_cbs_gp_end(bool expedite, rcu_gp_t *last_completed_gp);
180static void upd_missed_gp_in_wait(rcu_gp_t completed_gp);
181
182#ifdef RCU_PREEMPT_PODZIMEK
183static void start_detector(void);
184static void read_unlock_impl(size_t *pnesting_cnt);
185static void req_detection(size_t req_cnt);
186static bool cv_wait_for_gp(rcu_gp_t wait_on_gp);
187static void detector(void *);
188static bool wait_for_detect_req(void);
189static void end_cur_gp(void);
190static bool wait_for_readers(void);
191static bool gp_sleep(void);
192static void interrupt_delaying_cpus(cpu_mask_t *cpu_mask);
193static bool wait_for_delaying_cpus(void);
194#elif defined(RCU_PREEMPT_A)
195static bool wait_for_readers(bool expedite);
196static bool gp_sleep(bool *expedite);
197#endif
198
199static void start_new_gp(void);
200static void rm_quiescent_cpus(cpu_mask_t *cpu_mask);
201static void sample_cpus(cpu_mask_t *reader_cpus, void *arg);
202static void sample_local_cpu(void *);
203static bool wait_for_preempt_reader(void);
204static void note_preempted_reader(void);
205static void rm_preempted_reader(void);
206static void upd_max_cbs_in_slice(void);
207
208
209
210/** Initializes global RCU structures. */
211void rcu_init(void)
212{
213 condvar_initialize(&rcu.gp_ended);
214 condvar_initialize(&rcu.expedite_now);
215
216 spinlock_initialize(&rcu.gp_lock, "rcu.gp_lock");
217 _rcu_cur_gp = 0;
218 rcu.completed_gp = 0;
219
220 irq_spinlock_initialize(&rcu.preempt_lock, "rcu.preempt_lock");
221 list_initialize(&rcu.cur_preempted);
222 list_initialize(&rcu.next_preempted);
223 rcu.preempt_blocking_det = false;
224
225 mutex_initialize(&rcu.barrier_mtx, MUTEX_PASSIVE);
226 atomic_set(&rcu.barrier_wait_cnt, 0);
227 waitq_initialize(&rcu.barrier_wq);
228
229 semaphore_initialize(&rcu.remaining_readers, 0);
230
231#ifdef RCU_PREEMPT_PODZIMEK
232 condvar_initialize(&rcu.req_gp_changed);
233
234 rcu.req_gp_end_cnt = 0;
235 rcu.req_expedited_cnt = 0;
236 atomic_set(&rcu.delaying_cpu_cnt, 0);
237#endif
238
239 rcu.detector_thr = NULL;
240
241 rcu.stat_expedited_cnt = 0;
242 rcu.stat_delayed_cnt = 0;
243 rcu.stat_preempt_blocking_cnt = 0;
244 rcu.stat_smp_call_cnt = 0;
245}
246
247/** Initializes per-CPU RCU data. If on the boot cpu inits global data too.*/
248void rcu_cpu_init(void)
249{
250 if (config.cpu_active == 1) {
251 rcu_init();
252 }
253
254 CPU->rcu.last_seen_gp = 0;
255
256#ifdef RCU_PREEMPT_PODZIMEK
257 CPU->rcu.nesting_cnt = 0;
258 CPU->rcu.is_delaying_gp = false;
259 CPU->rcu.signal_unlock = false;
260#endif
261
262 CPU->rcu.cur_cbs = NULL;
263 CPU->rcu.cur_cbs_cnt = 0;
264 CPU->rcu.next_cbs = NULL;
265 CPU->rcu.next_cbs_cnt = 0;
266 CPU->rcu.arriving_cbs = NULL;
267 CPU->rcu.parriving_cbs_tail = &CPU->rcu.arriving_cbs;
268 CPU->rcu.arriving_cbs_cnt = 0;
269
270 CPU->rcu.cur_cbs_gp = 0;
271 CPU->rcu.next_cbs_gp = 0;
272
273 semaphore_initialize(&CPU->rcu.arrived_flag, 0);
274
275 /* BSP creates reclaimer threads before AP's rcu_cpu_init() runs. */
276 if (config.cpu_active == 1)
277 CPU->rcu.reclaimer_thr = NULL;
278
279 CPU->rcu.stat_max_cbs = 0;
280 CPU->rcu.stat_avg_cbs = 0;
281 CPU->rcu.stat_missed_gps = 0;
282 CPU->rcu.stat_missed_gp_in_wait = 0;
283 CPU->rcu.stat_max_slice_cbs = 0;
284 CPU->rcu.last_arriving_cnt = 0;
285}
286
287/** Completes RCU init. Creates and runs the detector and reclaimer threads.*/
288void rcu_kinit_init(void)
289{
290#ifdef RCU_PREEMPT_PODZIMEK
291 start_detector();
292#endif
293
294 start_reclaimers();
295}
296
297/** Initializes any per-thread RCU structures. */
298void rcu_thread_init(thread_t *thread)
299{
300 thread->rcu.nesting_cnt = 0;
301
302#ifdef RCU_PREEMPT_PODZIMEK
303 thread->rcu.was_preempted = false;
304#endif
305
306 link_initialize(&thread->rcu.preempt_link);
307}
308
309
310/** Cleans up global RCU resources and stops dispatching callbacks.
311 *
312 * Call when shutting down the kernel. Outstanding callbacks will
313 * not be processed. Instead they will linger forever.
314 */
315void rcu_stop(void)
316{
317 /* Stop and wait for reclaimers. */
318 for (unsigned int cpu_id = 0; cpu_id < config.cpu_active; ++cpu_id) {
319 ASSERT(cpus[cpu_id].rcu.reclaimer_thr != NULL);
320
321 if (cpus[cpu_id].rcu.reclaimer_thr) {
322 thread_interrupt(cpus[cpu_id].rcu.reclaimer_thr);
323 thread_join(cpus[cpu_id].rcu.reclaimer_thr);
324 thread_detach(cpus[cpu_id].rcu.reclaimer_thr);
325 cpus[cpu_id].rcu.reclaimer_thr = NULL;
326 }
327 }
328
329#ifdef RCU_PREEMPT_PODZIMEK
330 /* Stop the detector and wait. */
331 if (rcu.detector_thr) {
332 thread_interrupt(rcu.detector_thr);
333 thread_join(rcu.detector_thr);
334 thread_detach(rcu.detector_thr);
335 rcu.detector_thr = NULL;
336 }
337#endif
338}
339
340/** Returns the number of elapsed grace periods since boot. */
341uint64_t rcu_completed_gps(void)
342{
343 spinlock_lock(&rcu.gp_lock);
344 uint64_t completed = rcu.completed_gp;
345 spinlock_unlock(&rcu.gp_lock);
346
347 return completed;
348}
349
350/** Creates and runs cpu-bound reclaimer threads. */
351static void start_reclaimers(void)
352{
353 for (unsigned int cpu_id = 0; cpu_id < config.cpu_count; ++cpu_id) {
354 char name[THREAD_NAME_BUFLEN] = {0};
355
356 snprintf(name, THREAD_NAME_BUFLEN - 1, "rcu-rec/%u", cpu_id);
357
358 cpus[cpu_id].rcu.reclaimer_thr =
359 thread_create(reclaimer, NULL, TASK, THREAD_FLAG_NONE, name);
360
361 if (!cpus[cpu_id].rcu.reclaimer_thr)
362 panic("Failed to create RCU reclaimer thread on cpu%u.", cpu_id);
363
364 thread_wire(cpus[cpu_id].rcu.reclaimer_thr, &cpus[cpu_id]);
365 thread_ready(cpus[cpu_id].rcu.reclaimer_thr);
366 }
367}
368
369#ifdef RCU_PREEMPT_PODZIMEK
370
371/** Starts the detector thread. */
372static void start_detector(void)
373{
374 rcu.detector_thr =
375 thread_create(detector, NULL, TASK, THREAD_FLAG_NONE, "rcu-det");
376
377 if (!rcu.detector_thr)
378 panic("Failed to create RCU detector thread.");
379
380 thread_ready(rcu.detector_thr);
381}
382
383/** Returns true if in an rcu reader section. */
384bool rcu_read_locked(void)
385{
386 preemption_disable();
387 bool locked = 0 < CPU->rcu.nesting_cnt;
388 preemption_enable();
389
390 return locked;
391}
392
393/** Unlocks the local reader section using the given nesting count.
394 *
395 * Preemption or interrupts must be disabled.
396 *
397 * @param pnesting_cnt Either &CPU->rcu.tmp_nesting_cnt or
398 * THREAD->rcu.nesting_cnt.
399 */
400static void read_unlock_impl(size_t *pnesting_cnt)
401{
402 ASSERT(PREEMPTION_DISABLED || interrupts_disabled());
403
404 if (0 == --(*pnesting_cnt)) {
405 _rcu_record_qs();
406
407 /*
408 * The thread was preempted while in a critical section or
409 * the detector is eagerly waiting for this cpu's reader
410 * to finish.
411 *
412 * Note that THREAD may be NULL in scheduler() and not just during boot.
413 */
414 if ((THREAD && THREAD->rcu.was_preempted) || CPU->rcu.is_delaying_gp) {
415 /* Rechecks with disabled interrupts. */
416 _rcu_signal_read_unlock();
417 }
418 }
419}
420
421/** If necessary, signals the detector that we exited a reader section. */
422void _rcu_signal_read_unlock(void)
423{
424 ASSERT(PREEMPTION_DISABLED || interrupts_disabled());
425
426 /* todo: make NMI safe with cpu-local atomic ops. */
427
428 /*
429 * We have to disable interrupts in order to make checking
430 * and resetting was_preempted and is_delaying_gp atomic
431 * with respect to local interrupt handlers. Otherwise
432 * an interrupt could beat us to calling semaphore_up()
433 * before we reset the appropriate flag.
434 */
435 ipl_t ipl = interrupts_disable();
436
437 /*
438 * If the detector is eagerly waiting for this cpu's reader to unlock,
439 * notify it that the reader did so.
440 */
441 if (CPU->rcu.is_delaying_gp) {
442 CPU->rcu.is_delaying_gp = false;
443 semaphore_up(&rcu.remaining_readers);
444 }
445
446 /*
447 * This reader was preempted while in a reader section.
448 * We might be holding up the current GP. Notify the
449 * detector if so.
450 */
451 if (THREAD && THREAD->rcu.was_preempted) {
452 ASSERT(link_used(&THREAD->rcu.preempt_link));
453 THREAD->rcu.was_preempted = false;
454
455 rm_preempted_reader();
456 }
457
458 /* If there was something to signal to the detector we have done so. */
459 CPU->rcu.signal_unlock = false;
460
461 interrupts_restore(ipl);
462}
463
464#endif /* RCU_PREEMPT_PODZIMEK */
465
466typedef struct synch_item {
467 waitq_t wq;
468 rcu_item_t rcu_item;
469} synch_item_t;
470
471/** Blocks until all preexisting readers exit their critical sections. */
472void rcu_synchronize(void)
473{
474 _rcu_synchronize(false);
475}
476
477/** Blocks until all preexisting readers exit their critical sections. */
478void rcu_synchronize_expedite(void)
479{
480 _rcu_synchronize(true);
481}
482
483/** Blocks until all preexisting readers exit their critical sections. */
484void _rcu_synchronize(bool expedite)
485{
486 /* Calling from a reader section will deadlock. */
487 ASSERT(!rcu_read_locked());
488
489 synch_item_t completion;
490
491 waitq_initialize(&completion.wq);
492 _rcu_call(expedite, &completion.rcu_item, synch_complete);
493 waitq_sleep(&completion.wq);
494}
495
496/** rcu_synchronize's callback. */
497static void synch_complete(rcu_item_t *rcu_item)
498{
499 synch_item_t *completion = member_to_inst(rcu_item, synch_item_t, rcu_item);
500 ASSERT(completion);
501 waitq_wakeup(&completion->wq, WAKEUP_FIRST);
502}
503
504/** Waits for all outstanding rcu calls to complete. */
505void rcu_barrier(void)
506{
507 /*
508 * Serialize rcu_barrier() calls so we don't overwrite cpu.barrier_item
509 * currently in use by rcu_barrier().
510 */
511 mutex_lock(&rcu.barrier_mtx);
512
513 /*
514 * Ensure we queue a barrier callback on all cpus before the already
515 * enqueued barrier callbacks start signaling completion.
516 */
517 atomic_set(&rcu.barrier_wait_cnt, 1);
518
519 DEFINE_CPU_MASK(cpu_mask);
520 cpu_mask_active(cpu_mask);
521
522 cpu_mask_for_each(*cpu_mask, cpu_id) {
523 smp_call(cpu_id, add_barrier_cb, NULL);
524 }
525
526 if (0 < atomic_predec(&rcu.barrier_wait_cnt)) {
527 waitq_sleep(&rcu.barrier_wq);
528 }
529
530 mutex_unlock(&rcu.barrier_mtx);
531}
532
533/** Issues a rcu_barrier() callback on the local cpu.
534 *
535 * Executed with interrupts disabled.
536 */
537static void add_barrier_cb(void *arg)
538{
539 ASSERT(interrupts_disabled() || PREEMPTION_DISABLED);
540 atomic_inc(&rcu.barrier_wait_cnt);
541 rcu_call(&CPU->rcu.barrier_item, barrier_complete);
542}
543
544/** Local cpu's rcu_barrier() completion callback. */
545static void barrier_complete(rcu_item_t *barrier_item)
546{
547 /* Is this the last barrier callback completed? */
548 if (0 == atomic_predec(&rcu.barrier_wait_cnt)) {
549 /* Notify rcu_barrier() that we're done. */
550 waitq_wakeup(&rcu.barrier_wq, WAKEUP_FIRST);
551 }
552}
553
554/** Adds a callback to invoke after all preexisting readers finish.
555 *
556 * May be called from within interrupt handlers or RCU reader sections.
557 *
558 * @param rcu_item Used by RCU to track the call. Must remain
559 * until the user callback function is entered.
560 * @param func User callback function that will be invoked once a full
561 * grace period elapsed, ie at a time when all preexisting
562 * readers have finished. The callback should be short and must
563 * not block. If you must sleep, enqueue your work in the system
564 * work queue from the callback (ie workq_global_enqueue()).
565 */
566void rcu_call(rcu_item_t *rcu_item, rcu_func_t func)
567{
568 rcu_call_impl(false, rcu_item, func);
569}
570
571/** rcu_call() implementation. See rcu_call() for comments. */
572void _rcu_call(bool expedite, rcu_item_t *rcu_item, rcu_func_t func)
573{
574 rcu_call_impl(expedite, rcu_item, func);
575}
576
577/** rcu_call() inline-able implementation. See rcu_call() for comments. */
578static inline void rcu_call_impl(bool expedite, rcu_item_t *rcu_item,
579 rcu_func_t func)
580{
581 ASSERT(rcu_item);
582
583 rcu_item->func = func;
584 rcu_item->next = NULL;
585
586 preemption_disable();
587
588 ipl_t ipl = interrupts_disable();
589
590 rcu_cpu_data_t *r = &CPU->rcu;
591 *r->parriving_cbs_tail = rcu_item;
592 r->parriving_cbs_tail = &rcu_item->next;
593
594 size_t cnt = ++r->arriving_cbs_cnt;
595 interrupts_restore(ipl);
596
597 if (expedite) {
598 r->expedite_arriving = true;
599 }
600
601 /* Added first callback - notify the reclaimer. */
602 if (cnt == 1 && !semaphore_count_get(&r->arrived_flag)) {
603 semaphore_up(&r->arrived_flag);
604 }
605
606 preemption_enable();
607}
608
609static bool cur_cbs_empty(void)
610{
611 ASSERT(THREAD && THREAD->wired);
612 return NULL == CPU->rcu.cur_cbs;
613}
614
615static bool next_cbs_empty(void)
616{
617 ASSERT(THREAD && THREAD->wired);
618 return NULL == CPU->rcu.next_cbs;
619}
620
621/** Disable interrupts to get an up-to-date result. */
622static bool arriving_cbs_empty(void)
623{
624 ASSERT(THREAD && THREAD->wired);
625 /*
626 * Accessing with interrupts enabled may at worst lead to
627 * a false negative if we race with a local interrupt handler.
628 */
629 return NULL == CPU->rcu.arriving_cbs;
630}
631
632static bool all_cbs_empty(void)
633{
634 return cur_cbs_empty() && next_cbs_empty() && arriving_cbs_empty();
635}
636
637
638/** Reclaimer thread dispatches locally queued callbacks once a GP ends. */
639static void reclaimer(void *arg)
640{
641 ASSERT(THREAD && THREAD->wired);
642 ASSERT(THREAD == CPU->rcu.reclaimer_thr);
643
644 rcu_gp_t last_compl_gp = 0;
645 bool ok = true;
646
647 while (ok && wait_for_pending_cbs()) {
648 ASSERT(CPU->rcu.reclaimer_thr == THREAD);
649
650 exec_completed_cbs(last_compl_gp);
651
652 bool expedite = advance_cbs();
653
654 ok = wait_for_cur_cbs_gp_end(expedite, &last_compl_gp);
655 }
656}
657
658/** Waits until there are callbacks waiting to be dispatched. */
659static bool wait_for_pending_cbs(void)
660{
661 if (!all_cbs_empty())
662 return true;
663
664 bool ok = true;
665
666 while (arriving_cbs_empty() && ok) {
667 ok = semaphore_down_interruptable(&CPU->rcu.arrived_flag);
668 }
669
670 return ok;
671}
672
673static void upd_stat_missed_gp(rcu_gp_t compl)
674{
675 if (CPU->rcu.cur_cbs_gp < compl) {
676 CPU->rcu.stat_missed_gps += (size_t)(compl - CPU->rcu.cur_cbs_gp);
677 }
678}
679
680/** Executes all callbacks for the given completed grace period. */
681static void exec_completed_cbs(rcu_gp_t last_completed_gp)
682{
683 upd_stat_missed_gp(last_completed_gp);
684
685 /* Both next_cbs and cur_cbs GP elapsed. */
686 if (CPU->rcu.next_cbs_gp <= last_completed_gp) {
687 ASSERT(CPU->rcu.cur_cbs_gp <= CPU->rcu.next_cbs_gp);
688
689 size_t exec_cnt = CPU->rcu.cur_cbs_cnt + CPU->rcu.next_cbs_cnt;
690
691 if (exec_cnt < CRITICAL_THRESHOLD) {
692 exec_cbs(&CPU->rcu.cur_cbs);
693 exec_cbs(&CPU->rcu.next_cbs);
694 } else {
695 /*
696 * Getting overwhelmed with too many callbacks to run.
697 * Disable preemption in order to prolong our time slice
698 * and catch up with updaters posting new callbacks.
699 */
700 preemption_disable();
701 exec_cbs(&CPU->rcu.cur_cbs);
702 exec_cbs(&CPU->rcu.next_cbs);
703 preemption_enable();
704 }
705
706 CPU->rcu.cur_cbs_cnt = 0;
707 CPU->rcu.next_cbs_cnt = 0;
708 } else if (CPU->rcu.cur_cbs_gp <= last_completed_gp) {
709
710 if (CPU->rcu.cur_cbs_cnt < CRITICAL_THRESHOLD) {
711 exec_cbs(&CPU->rcu.cur_cbs);
712 } else {
713 /*
714 * Getting overwhelmed with too many callbacks to run.
715 * Disable preemption in order to prolong our time slice
716 * and catch up with updaters posting new callbacks.
717 */
718 preemption_disable();
719 exec_cbs(&CPU->rcu.cur_cbs);
720 preemption_enable();
721 }
722
723 CPU->rcu.cur_cbs_cnt = 0;
724 }
725}
726
727/** Executes callbacks in the single-linked list. The list is left empty. */
728static void exec_cbs(rcu_item_t **phead)
729{
730 rcu_item_t *rcu_item = *phead;
731
732 while (rcu_item) {
733 /* func() may free rcu_item. Get a local copy. */
734 rcu_item_t *next = rcu_item->next;
735 rcu_func_t func = rcu_item->func;
736
737 func(rcu_item);
738
739 rcu_item = next;
740 }
741
742 *phead = NULL;
743}
744
745static void upd_stat_cb_cnts(size_t arriving_cnt)
746{
747 CPU->rcu.stat_max_cbs = max(arriving_cnt, CPU->rcu.stat_max_cbs);
748 if (0 < arriving_cnt) {
749 CPU->rcu.stat_avg_cbs =
750 (99 * CPU->rcu.stat_avg_cbs + 1 * arriving_cnt) / 100;
751 }
752}
753
754/** Prepares another batch of callbacks to dispatch at the nest grace period.
755 *
756 * @return True if the next batch of callbacks must be expedited quickly.
757 */
758static bool advance_cbs(void)
759{
760 /* Move next_cbs to cur_cbs. */
761 CPU->rcu.cur_cbs = CPU->rcu.next_cbs;
762 CPU->rcu.cur_cbs_cnt = CPU->rcu.next_cbs_cnt;
763 CPU->rcu.cur_cbs_gp = CPU->rcu.next_cbs_gp;
764
765 /* Move arriving_cbs to next_cbs. Empties arriving_cbs. */
766 ipl_t ipl = interrupts_disable();
767
768 /*
769 * Too many callbacks queued. Better speed up the detection
770 * or risk exhausting all system memory.
771 */
772 bool expedite = (EXPEDITE_THRESHOLD < CPU->rcu.arriving_cbs_cnt)
773 || CPU->rcu.expedite_arriving;
774
775 CPU->rcu.expedite_arriving = false;
776
777 CPU->rcu.next_cbs = CPU->rcu.arriving_cbs;
778 CPU->rcu.next_cbs_cnt = CPU->rcu.arriving_cbs_cnt;
779
780 CPU->rcu.arriving_cbs = NULL;
781 CPU->rcu.parriving_cbs_tail = &CPU->rcu.arriving_cbs;
782 CPU->rcu.arriving_cbs_cnt = 0;
783
784 interrupts_restore(ipl);
785
786 /* Update statistics of arrived callbacks. */
787 upd_stat_cb_cnts(CPU->rcu.next_cbs_cnt);
788
789 /*
790 * Make changes prior to queuing next_cbs visible to readers.
791 * See comment in wait_for_readers().
792 */
793 memory_barrier(); /* MB A, B */
794
795 /* At the end of next_cbs_gp, exec next_cbs. Determine what GP that is. */
796
797 if (!next_cbs_empty()) {
798 spinlock_lock(&rcu.gp_lock);
799
800 /* Exec next_cbs at the end of the next GP. */
801 CPU->rcu.next_cbs_gp = _rcu_cur_gp + 1;
802
803 /*
804 * There are no callbacks to invoke before next_cbs. Instruct
805 * wait_for_cur_cbs_gp() to notify us of the nearest GP end.
806 * That could be sooner than next_cbs_gp (if the current GP
807 * had not yet completed), so we'll create a shorter batch
808 * of callbacks next time around.
809 */
810 if (cur_cbs_empty()) {
811 CPU->rcu.cur_cbs_gp = rcu.completed_gp + 1;
812 }
813
814 spinlock_unlock(&rcu.gp_lock);
815 } else {
816 CPU->rcu.next_cbs_gp = CPU->rcu.cur_cbs_gp;
817 }
818
819 ASSERT(CPU->rcu.cur_cbs_gp <= CPU->rcu.next_cbs_gp);
820
821 return expedite;
822}
823
824
825#ifdef RCU_PREEMPT_A
826
827/** Waits for the grace period associated with callbacks cub_cbs to elapse.
828 *
829 * @param expedite Instructs the detector to aggressively speed up grace
830 * period detection without any delay.
831 * @param completed_gp Returns the most recent completed grace period
832 * number.
833 * @return false if the thread was interrupted and should stop.
834 */
835static bool wait_for_cur_cbs_gp_end(bool expedite, rcu_gp_t *completed_gp)
836{
837 spinlock_lock(&rcu.gp_lock);
838
839 ASSERT(CPU->rcu.cur_cbs_gp <= CPU->rcu.next_cbs_gp);
840 ASSERT(CPU->rcu.cur_cbs_gp <= _rcu_cur_gp + 1);
841
842 while (rcu.completed_gp < CPU->rcu.cur_cbs_gp) {
843 /* GP has not yet started - start a new one. */
844 if (rcu.completed_gp == _rcu_cur_gp) {
845 start_new_gp();
846 spinlock_unlock(&rcu.gp_lock);
847
848 if (!wait_for_readers(expedite))
849 return false;
850
851 spinlock_lock(&rcu.gp_lock);
852 /* Notify any reclaimers this GP had ended. */
853 rcu.completed_gp = _rcu_cur_gp;
854 condvar_broadcast(&rcu.gp_ended);
855 } else {
856 /* GP detection is in progress.*/
857
858 if (expedite)
859 condvar_signal(&rcu.expedite_now);
860
861 /* Wait for the GP to complete. */
862 int ret = _condvar_wait_timeout_spinlock(&rcu.gp_ended, &rcu.gp_lock,
863 SYNCH_NO_TIMEOUT, SYNCH_FLAGS_INTERRUPTIBLE);
864
865 if (ret == ESYNCH_INTERRUPTED) {
866 spinlock_unlock(&rcu.gp_lock);
867 return false;
868 }
869 }
870 }
871
872 upd_missed_gp_in_wait(rcu.completed_gp);
873
874 *completed_gp = rcu.completed_gp;
875 spinlock_unlock(&rcu.gp_lock);
876
877 return true;
878}
879
880static bool wait_for_readers(bool expedite)
881{
882 DEFINE_CPU_MASK(reader_cpus);
883
884 cpu_mask_active(reader_cpus);
885 rm_quiescent_cpus(reader_cpus);
886
887 while (!cpu_mask_is_none(reader_cpus)) {
888 /* Give cpus a chance to context switch (a QS) and batch callbacks. */
889 if(!gp_sleep(&expedite))
890 return false;
891
892 rm_quiescent_cpus(reader_cpus);
893 sample_cpus(reader_cpus, reader_cpus);
894 }
895
896 /* Update statistic. */
897 if (expedite) {
898 ++rcu.stat_expedited_cnt;
899 }
900
901 /*
902 * All cpus have passed through a QS and see the most recent _rcu_cur_gp.
903 * As a result newly preempted readers will associate with next_preempted
904 * and the number of old readers in cur_preempted will monotonically
905 * decrease. Wait for those old/preexisting readers.
906 */
907 return wait_for_preempt_reader();
908}
909
910static bool gp_sleep(bool *expedite)
911{
912 if (*expedite) {
913 scheduler();
914 return true;
915 } else {
916 spinlock_lock(&rcu.gp_lock);
917
918 int ret = 0;
919 ret = _condvar_wait_timeout_spinlock(&rcu.expedite_now, &rcu.gp_lock,
920 DETECT_SLEEP_MS * 1000, SYNCH_FLAGS_INTERRUPTIBLE);
921
922 /* rcu.expedite_now was signaled. */
923 if (ret == ESYNCH_OK_BLOCKED) {
924 *expedite = true;
925 }
926
927 spinlock_unlock(&rcu.gp_lock);
928
929 return (ret != ESYNCH_INTERRUPTED);
930 }
931}
932
933static void sample_local_cpu(void *arg)
934{
935 ASSERT(interrupts_disabled());
936 cpu_mask_t *reader_cpus = (cpu_mask_t *)arg;
937
938 bool locked = RCU_CNT_INC <= THE->rcu_nesting;
939 /* smp_call machinery makes the most current _rcu_cur_gp visible. */
940 bool passed_qs = (CPU->rcu.last_seen_gp == _rcu_cur_gp);
941
942 if (locked && !passed_qs) {
943 /*
944 * This cpu has not yet passed a quiescent state during this grace
945 * period and it is currently in a reader section. We'll have to
946 * try to sample this cpu again later.
947 */
948 } else {
949 /* Either not in a reader section or already passed a QS. */
950 cpu_mask_reset(reader_cpus, CPU->id);
951 /* Contain new reader sections and make prior changes visible to them.*/
952 memory_barrier();
953 CPU->rcu.last_seen_gp = _rcu_cur_gp;
954 }
955}
956
957/** Called by the scheduler() when switching away from the current thread. */
958void rcu_after_thread_ran(void)
959{
960 ASSERT(interrupts_disabled());
961
962 /*
963 * In order not to worry about NMI seeing rcu_nesting change work
964 * with a local copy.
965 */
966 size_t nesting_cnt = ACCESS_ONCE(THE->rcu_nesting);
967
968 /* Preempted a reader critical section for the first time. */
969 if (RCU_CNT_INC <= nesting_cnt && !(nesting_cnt & RCU_WAS_PREEMPTED)) {
970 nesting_cnt |= RCU_WAS_PREEMPTED;
971 note_preempted_reader();
972 }
973
974 /* Save the thread's nesting count when it is not running. */
975 THREAD->rcu.nesting_cnt = nesting_cnt;
976 ACCESS_ONCE(THE->rcu_nesting) = 0;
977
978 if (CPU->rcu.last_seen_gp != _rcu_cur_gp) {
979 /*
980 * Contain any memory accesses of old readers before announcing a QS.
981 * Also make changes from the previous GP visible to this cpu.
982 * Moreover it separates writing to last_seen_gp from
983 * note_preempted_reader().
984 */
985 memory_barrier();
986 /*
987 * The preempted reader has been noted globally. There are therefore
988 * no readers running on this cpu so this is a quiescent state.
989 *
990 * Reading the multiword _rcu_cur_gp non-atomically is benign.
991 * At worst, the read value will be different from the actual value.
992 * As a result, both the detector and this cpu will believe
993 * this cpu has not yet passed a QS although it really did.
994 */
995 CPU->rcu.last_seen_gp = _rcu_cur_gp;
996 }
997
998 /*
999 * Forcefully associate the reclaimer with the highest priority
1000 * even if preempted due to its time slice running out.
1001 */
1002 if (THREAD == CPU->rcu.reclaimer_thr) {
1003 THREAD->priority = -1;
1004 }
1005
1006 upd_max_cbs_in_slice();
1007}
1008
1009/** Called by the scheduler() when switching to a newly scheduled thread. */
1010void rcu_before_thread_runs(void)
1011{
1012 ASSERT(PREEMPTION_DISABLED || interrupts_disabled());
1013 ASSERT(!rcu_read_locked());
1014
1015 /* Load the thread's saved nesting count from before it was preempted. */
1016 THE->rcu_nesting = THREAD->rcu.nesting_cnt;
1017}
1018
1019/** Called from scheduler() when exiting the current thread.
1020 *
1021 * Preemption or interrupts are disabled and the scheduler() already
1022 * switched away from the current thread, calling rcu_after_thread_ran().
1023 */
1024void rcu_thread_exiting(void)
1025{
1026 ASSERT(PREEMPTION_DISABLED || interrupts_disabled());
1027 /*
1028 * The thread forgot to exit its reader critical section.
1029 * It is a bug, but rather than letting the entire system lock up
1030 * forcefully leave the reader section. The thread is not holding
1031 * any references anyway since it is exiting so it is safe.
1032 */
1033 if (RCU_CNT_INC <= THREAD->rcu.nesting_cnt) {
1034 /* Emulate _rcu_preempted_unlock() with the proper nesting count. */
1035 if (THREAD->rcu.nesting_cnt & RCU_WAS_PREEMPTED) {
1036 ipl_t ipl = interrupts_disable();
1037 rm_preempted_reader();
1038 interrupts_restore(ipl);
1039 }
1040
1041 printf("Bug: thread (id %" PRIu64 " \"%s\") exited while in RCU read"
1042 " section.\n", THREAD->tid, THREAD->name);
1043 }
1044}
1045
1046/** Returns true if in an rcu reader section. */
1047bool rcu_read_locked(void)
1048{
1049 return RCU_CNT_INC <= THE->rcu_nesting;
1050}
1051
1052/** Invoked when a preempted reader finally exits its reader section. */
1053void _rcu_preempted_unlock(void)
1054{
1055 ipl_t ipl = interrupts_disable();
1056
1057 if (THE->rcu_nesting == RCU_WAS_PREEMPTED) {
1058 THE->rcu_nesting = 0;
1059 rm_preempted_reader();
1060 }
1061
1062 interrupts_restore(ipl);
1063}
1064
1065#elif defined(RCU_PREEMPT_PODZIMEK)
1066
1067/** Waits for the grace period associated with callbacks cub_cbs to elapse.
1068 *
1069 * @param expedite Instructs the detector to aggressively speed up grace
1070 * period detection without any delay.
1071 * @param completed_gp Returns the most recent completed grace period
1072 * number.
1073 * @return false if the thread was interrupted and should stop.
1074 */
1075static bool wait_for_cur_cbs_gp_end(bool expedite, rcu_gp_t *completed_gp)
1076{
1077 /*
1078 * Use a possibly outdated version of completed_gp to bypass checking
1079 * with the lock.
1080 *
1081 * Note that loading and storing rcu.completed_gp is not atomic
1082 * (it is 64bit wide). Reading a clobbered value that is less than
1083 * rcu.completed_gp is harmless - we'll recheck with a lock. The
1084 * only way to read a clobbered value that is greater than the actual
1085 * value is if the detector increases the higher-order word first and
1086 * then decreases the lower-order word (or we see stores in that order),
1087 * eg when incrementing from 2^32 - 1 to 2^32. The loaded value
1088 * suddenly jumps by 2^32. It would take hours for such an increase
1089 * to occur so it is safe to discard the value. We allow increases
1090 * of up to half the maximum to generously accommodate for loading an
1091 * outdated lower word.
1092 */
1093 rcu_gp_t compl_gp = ACCESS_ONCE(rcu.completed_gp);
1094 if (CPU->rcu.cur_cbs_gp <= compl_gp
1095 && compl_gp <= CPU->rcu.cur_cbs_gp + UINT32_MAX_HALF) {
1096 *completed_gp = compl_gp;
1097 return true;
1098 }
1099
1100 spinlock_lock(&rcu.gp_lock);
1101
1102 if (CPU->rcu.cur_cbs_gp <= rcu.completed_gp) {
1103 *completed_gp = rcu.completed_gp;
1104 spinlock_unlock(&rcu.gp_lock);
1105 return true;
1106 }
1107
1108 ASSERT(CPU->rcu.cur_cbs_gp <= CPU->rcu.next_cbs_gp);
1109 ASSERT(_rcu_cur_gp <= CPU->rcu.cur_cbs_gp);
1110
1111 /*
1112 * Notify the detector of how many GP ends we intend to wait for, so
1113 * it can avoid going to sleep unnecessarily. Optimistically assume
1114 * new callbacks will arrive while we're waiting; hence +1.
1115 */
1116 size_t remaining_gp_ends = (size_t) (CPU->rcu.next_cbs_gp - _rcu_cur_gp);
1117 req_detection(remaining_gp_ends + (arriving_cbs_empty() ? 0 : 1));
1118
1119 /*
1120 * Ask the detector to speed up GP detection if there are too many
1121 * pending callbacks and other reclaimers have not already done so.
1122 */
1123 if (expedite) {
1124 if(0 == rcu.req_expedited_cnt)
1125 condvar_signal(&rcu.expedite_now);
1126
1127 /*
1128 * Expedite only cub_cbs. If there really is a surge of callbacks
1129 * the arriving batch will expedite the GP for the huge number
1130 * of callbacks currently in next_cbs
1131 */
1132 rcu.req_expedited_cnt = 1;
1133 }
1134
1135 /* Wait for cur_cbs_gp to end. */
1136 bool interrupted = cv_wait_for_gp(CPU->rcu.cur_cbs_gp);
1137
1138 *completed_gp = rcu.completed_gp;
1139 spinlock_unlock(&rcu.gp_lock);
1140
1141 if (!interrupted)
1142 upd_missed_gp_in_wait(*completed_gp);
1143
1144 return !interrupted;
1145}
1146
1147/** Waits for an announcement of the end of the grace period wait_on_gp. */
1148static bool cv_wait_for_gp(rcu_gp_t wait_on_gp)
1149{
1150 ASSERT(spinlock_locked(&rcu.gp_lock));
1151
1152 bool interrupted = false;
1153
1154 /* Wait until wait_on_gp ends. */
1155 while (rcu.completed_gp < wait_on_gp && !interrupted) {
1156 int ret = _condvar_wait_timeout_spinlock(&rcu.gp_ended, &rcu.gp_lock,
1157 SYNCH_NO_TIMEOUT, SYNCH_FLAGS_INTERRUPTIBLE);
1158 interrupted = (ret == ESYNCH_INTERRUPTED);
1159 }
1160
1161 return interrupted;
1162}
1163
1164/** Requests the detector to detect at least req_cnt consecutive grace periods.*/
1165static void req_detection(size_t req_cnt)
1166{
1167 if (rcu.req_gp_end_cnt < req_cnt) {
1168 bool detector_idle = (0 == rcu.req_gp_end_cnt);
1169 rcu.req_gp_end_cnt = req_cnt;
1170
1171 if (detector_idle) {
1172 ASSERT(_rcu_cur_gp == rcu.completed_gp);
1173 condvar_signal(&rcu.req_gp_changed);
1174 }
1175 }
1176}
1177
1178
1179/** The detector thread detects and notifies reclaimers of grace period ends. */
1180static void detector(void *arg)
1181{
1182 spinlock_lock(&rcu.gp_lock);
1183
1184 while (wait_for_detect_req()) {
1185 /*
1186 * Announce new GP started. Readers start lazily acknowledging that
1187 * they passed a QS.
1188 */
1189 start_new_gp();
1190
1191 spinlock_unlock(&rcu.gp_lock);
1192
1193 if (!wait_for_readers())
1194 goto unlocked_out;
1195
1196 spinlock_lock(&rcu.gp_lock);
1197
1198 /* Notify reclaimers that they may now invoke queued callbacks. */
1199 end_cur_gp();
1200 }
1201
1202 spinlock_unlock(&rcu.gp_lock);
1203
1204unlocked_out:
1205 return;
1206}
1207
1208/** Waits for a request from a reclaimer thread to detect a grace period. */
1209static bool wait_for_detect_req(void)
1210{
1211 ASSERT(spinlock_locked(&rcu.gp_lock));
1212
1213 bool interrupted = false;
1214
1215 while (0 == rcu.req_gp_end_cnt && !interrupted) {
1216 int ret = _condvar_wait_timeout_spinlock(&rcu.req_gp_changed,
1217 &rcu.gp_lock, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_INTERRUPTIBLE);
1218
1219 interrupted = (ret == ESYNCH_INTERRUPTED);
1220 }
1221
1222 return !interrupted;
1223}
1224
1225
1226static void end_cur_gp(void)
1227{
1228 ASSERT(spinlock_locked(&rcu.gp_lock));
1229
1230 rcu.completed_gp = _rcu_cur_gp;
1231 --rcu.req_gp_end_cnt;
1232
1233 condvar_broadcast(&rcu.gp_ended);
1234}
1235
1236/** Waits for readers that started before the current GP started to finish. */
1237static bool wait_for_readers(void)
1238{
1239 DEFINE_CPU_MASK(reading_cpus);
1240
1241 /* All running cpus have potential readers. */
1242 cpu_mask_active(reading_cpus);
1243
1244 /*
1245 * Give readers time to pass through a QS. Also, batch arriving
1246 * callbacks in order to amortize detection overhead.
1247 */
1248 if (!gp_sleep())
1249 return false;
1250
1251 /* Non-intrusively determine which cpus have yet to pass a QS. */
1252 rm_quiescent_cpus(reading_cpus);
1253
1254 /* Actively interrupt cpus delaying the current GP and demand a QS. */
1255 interrupt_delaying_cpus(reading_cpus);
1256
1257 /* Wait for the interrupted cpus to notify us that they reached a QS. */
1258 if (!wait_for_delaying_cpus())
1259 return false;
1260 /*
1261 * All cpus recorded a QS or are still idle. Any new readers will be added
1262 * to next_preempt if preempted, ie the number of readers in cur_preempted
1263 * monotonically descreases.
1264 */
1265
1266 /* Wait for the last reader in cur_preempted to notify us it is done. */
1267 if (!wait_for_preempt_reader())
1268 return false;
1269
1270 return true;
1271}
1272
1273/** Sleeps a while if the current grace period is not to be expedited. */
1274static bool gp_sleep(void)
1275{
1276 spinlock_lock(&rcu.gp_lock);
1277
1278 int ret = 0;
1279 while (0 == rcu.req_expedited_cnt && 0 == ret) {
1280 /* minor bug: sleeps for the same duration if woken up spuriously. */
1281 ret = _condvar_wait_timeout_spinlock(&rcu.expedite_now, &rcu.gp_lock,
1282 DETECT_SLEEP_MS * 1000, SYNCH_FLAGS_INTERRUPTIBLE);
1283 }
1284
1285 if (0 < rcu.req_expedited_cnt) {
1286 --rcu.req_expedited_cnt;
1287 /* Update statistic. */
1288 ++rcu.stat_expedited_cnt;
1289 }
1290
1291 spinlock_unlock(&rcu.gp_lock);
1292
1293 return (ret != ESYNCH_INTERRUPTED);
1294}
1295
1296/** Actively interrupts and checks the offending cpus for quiescent states. */
1297static void interrupt_delaying_cpus(cpu_mask_t *cpu_mask)
1298{
1299 atomic_set(&rcu.delaying_cpu_cnt, 0);
1300
1301 sample_cpus(cpu_mask, NULL);
1302}
1303
1304/** Invoked on a cpu delaying grace period detection.
1305 *
1306 * Induces a quiescent state for the cpu or it instructs remaining
1307 * readers to notify the detector once they finish.
1308 */
1309static void sample_local_cpu(void *arg)
1310{
1311 ASSERT(interrupts_disabled());
1312 ASSERT(!CPU->rcu.is_delaying_gp);
1313
1314 /* Cpu did not pass a quiescent state yet. */
1315 if (CPU->rcu.last_seen_gp != _rcu_cur_gp) {
1316 /* Interrupted a reader in a reader critical section. */
1317 if (0 < CPU->rcu.nesting_cnt) {
1318 ASSERT(!CPU->idle);
1319 /* Note to notify the detector from rcu_read_unlock(). */
1320 CPU->rcu.is_delaying_gp = true;
1321 /*
1322 * Set signal_unlock only after setting is_delaying_gp so
1323 * that NMI handlers do not accidentally clear it in unlock()
1324 * before seeing and acting upon is_delaying_gp.
1325 */
1326 compiler_barrier();
1327 CPU->rcu.signal_unlock = true;
1328
1329 atomic_inc(&rcu.delaying_cpu_cnt);
1330 } else {
1331 /*
1332 * The cpu did not enter any rcu reader sections since
1333 * the start of the current GP. Record a quiescent state.
1334 *
1335 * Or, we interrupted rcu_read_unlock_impl() right before
1336 * it recorded a QS. Record a QS for it. The memory barrier
1337 * contains the reader section's mem accesses before
1338 * updating last_seen_gp.
1339 *
1340 * Or, we interrupted rcu_read_lock() right after it recorded
1341 * a QS for the previous GP but before it got a chance to
1342 * increment its nesting count. The memory barrier again
1343 * stops the CS code from spilling out of the CS.
1344 */
1345 memory_barrier();
1346 CPU->rcu.last_seen_gp = _rcu_cur_gp;
1347 }
1348 } else {
1349 /*
1350 * This cpu already acknowledged that it had passed through
1351 * a quiescent state since the start of cur_gp.
1352 */
1353 }
1354
1355 /*
1356 * smp_call() makes sure any changes propagate back to the caller.
1357 * In particular, it makes the most current last_seen_gp visible
1358 * to the detector.
1359 */
1360}
1361
1362/** Waits for cpus delaying the current grace period if there are any. */
1363static bool wait_for_delaying_cpus(void)
1364{
1365 int delaying_cpu_cnt = atomic_get(&rcu.delaying_cpu_cnt);
1366
1367 for (int i = 0; i < delaying_cpu_cnt; ++i){
1368 if (!semaphore_down_interruptable(&rcu.remaining_readers))
1369 return false;
1370 }
1371
1372 /* Update statistic. */
1373 rcu.stat_delayed_cnt += delaying_cpu_cnt;
1374
1375 return true;
1376}
1377
1378/** Called by the scheduler() when switching away from the current thread. */
1379void rcu_after_thread_ran(void)
1380{
1381 ASSERT(interrupts_disabled());
1382 /* todo: make is_delaying_gp and was_preempted NMI safe via local atomics.*/
1383
1384 /*
1385 * Prevent NMI handlers from interfering. The detector will be notified
1386 * here if CPU->rcu.is_delaying_gp and the current thread is no longer
1387 * running so there is nothing to signal to the detector.
1388 */
1389 CPU->rcu.signal_unlock = false;
1390 /* Separates clearing of .signal_unlock from CPU->rcu.nesting_cnt = 0. */
1391 compiler_barrier();
1392
1393 /* Save the thread's nesting count when it is not running. */
1394 THREAD->rcu.nesting_cnt = CPU->rcu.nesting_cnt;
1395 /* Interrupt handlers might use RCU while idle in scheduler(). */
1396 CPU->rcu.nesting_cnt = 0;
1397
1398 /* Preempted a reader critical section for the first time. */
1399 if (0 < THREAD->rcu.nesting_cnt && !THREAD->rcu.was_preempted) {
1400 THREAD->rcu.was_preempted = true;
1401 note_preempted_reader();
1402 }
1403
1404 /*
1405 * The preempted reader has been noted globally. There are therefore
1406 * no readers running on this cpu so this is a quiescent state.
1407 */
1408 _rcu_record_qs();
1409
1410 /*
1411 * This cpu is holding up the current GP. Let the detector know
1412 * it has just passed a quiescent state.
1413 *
1414 * The detector waits separately for preempted readers, so we have
1415 * to notify the detector even if we have just preempted a reader.
1416 */
1417 if (CPU->rcu.is_delaying_gp) {
1418 CPU->rcu.is_delaying_gp = false;
1419 semaphore_up(&rcu.remaining_readers);
1420 }
1421
1422 /*
1423 * Forcefully associate the detector with the highest priority
1424 * even if preempted due to its time slice running out.
1425 *
1426 * todo: Replace with strict scheduler priority classes.
1427 */
1428 if (THREAD == rcu.detector_thr) {
1429 THREAD->priority = -1;
1430 }
1431 else if (THREAD == CPU->rcu.reclaimer_thr) {
1432 THREAD->priority = -1;
1433 }
1434
1435 upd_max_cbs_in_slice();
1436}
1437
1438/** Called by the scheduler() when switching to a newly scheduled thread. */
1439void rcu_before_thread_runs(void)
1440{
1441 ASSERT(PREEMPTION_DISABLED || interrupts_disabled());
1442 ASSERT(0 == CPU->rcu.nesting_cnt);
1443
1444 /* Load the thread's saved nesting count from before it was preempted. */
1445 CPU->rcu.nesting_cnt = THREAD->rcu.nesting_cnt;
1446 /*
1447 * In the unlikely event that a NMI occurs between the loading of the
1448 * variables and setting signal_unlock, the NMI handler may invoke
1449 * rcu_read_unlock() and clear signal_unlock. In that case we will
1450 * incorrectly overwrite signal_unlock from false to true. This event
1451 * situation benign and the next rcu_read_unlock() will at worst
1452 * needlessly invoke _rcu_signal_unlock().
1453 */
1454 CPU->rcu.signal_unlock = THREAD->rcu.was_preempted || CPU->rcu.is_delaying_gp;
1455}
1456
1457/** Called from scheduler() when exiting the current thread.
1458 *
1459 * Preemption or interrupts are disabled and the scheduler() already
1460 * switched away from the current thread, calling rcu_after_thread_ran().
1461 */
1462void rcu_thread_exiting(void)
1463{
1464 ASSERT(THREAD != NULL);
1465 ASSERT(THREAD->state == Exiting);
1466 ASSERT(PREEMPTION_DISABLED || interrupts_disabled());
1467
1468 /*
1469 * The thread forgot to exit its reader critical section.
1470 * It is a bug, but rather than letting the entire system lock up
1471 * forcefully leave the reader section. The thread is not holding
1472 * any references anyway since it is exiting so it is safe.
1473 */
1474 if (0 < THREAD->rcu.nesting_cnt) {
1475 THREAD->rcu.nesting_cnt = 1;
1476 read_unlock_impl(&THREAD->rcu.nesting_cnt);
1477
1478 printf("Bug: thread (id %" PRIu64 " \"%s\") exited while in RCU read"
1479 " section.\n", THREAD->tid, THREAD->name);
1480 }
1481}
1482
1483
1484#endif /* RCU_PREEMPT_PODZIMEK */
1485
1486/** Announces the start of a new grace period for preexisting readers to ack. */
1487static void start_new_gp(void)
1488{
1489 ASSERT(spinlock_locked(&rcu.gp_lock));
1490
1491 irq_spinlock_lock(&rcu.preempt_lock, true);
1492
1493 /* Start a new GP. Announce to readers that a quiescent state is needed. */
1494 ++_rcu_cur_gp;
1495
1496 /*
1497 * Readers preempted before the start of this GP (next_preempted)
1498 * are preexisting readers now that a GP started and will hold up
1499 * the current GP until they exit their reader sections.
1500 *
1501 * Preempted readers from the previous GP have finished so
1502 * cur_preempted is empty, but see comment in _rcu_record_qs().
1503 */
1504 list_concat(&rcu.cur_preempted, &rcu.next_preempted);
1505
1506 irq_spinlock_unlock(&rcu.preempt_lock, true);
1507}
1508
1509/** Remove those cpus from the mask that have already passed a quiescent
1510 * state since the start of the current grace period.
1511 */
1512static void rm_quiescent_cpus(cpu_mask_t *cpu_mask)
1513{
1514 /*
1515 * Ensure the announcement of the start of a new GP (ie up-to-date
1516 * cur_gp) propagates to cpus that are just coming out of idle
1517 * mode before we sample their idle state flag.
1518 *
1519 * Cpus guarantee that after they set CPU->idle = true they will not
1520 * execute any RCU reader sections without first setting idle to
1521 * false and issuing a memory barrier. Therefore, if rm_quiescent_cpus()
1522 * later on sees an idle cpu, but the cpu is just exiting its idle mode,
1523 * the cpu must not have yet executed its memory barrier (otherwise
1524 * it would pair up with this mem barrier and we would see idle == false).
1525 * That memory barrier will pair up with the one below and ensure
1526 * that a reader on the now-non-idle cpu will see the most current
1527 * cur_gp. As a result, such a reader will never attempt to semaphore_up(
1528 * pending_readers) during this GP, which allows the detector to
1529 * ignore that cpu (the detector thinks it is idle). Moreover, any
1530 * changes made by RCU updaters will have propagated to readers
1531 * on the previously idle cpu -- again thanks to issuing a memory
1532 * barrier after returning from idle mode.
1533 *
1534 * idle -> non-idle cpu | detector | reclaimer
1535 * ------------------------------------------------------
1536 * rcu reader 1 | | rcu_call()
1537 * MB X | |
1538 * idle = true | | rcu_call()
1539 * (no rcu readers allowed ) | | MB A in advance_cbs()
1540 * MB Y | (...) | (...)
1541 * (no rcu readers allowed) | | MB B in advance_cbs()
1542 * idle = false | ++cur_gp |
1543 * (no rcu readers allowed) | MB C |
1544 * MB Z | signal gp_end |
1545 * rcu reader 2 | | exec_cur_cbs()
1546 *
1547 *
1548 * MB Y orders visibility of changes to idle for detector's sake.
1549 *
1550 * MB Z pairs up with MB C. The cpu making a transition from idle
1551 * will see the most current value of cur_gp and will not attempt
1552 * to notify the detector even if preempted during this GP.
1553 *
1554 * MB Z pairs up with MB A from the previous batch. Updaters' changes
1555 * are visible to reader 2 even when the detector thinks the cpu is idle
1556 * but it is not anymore.
1557 *
1558 * MB X pairs up with MB B. Late mem accesses of reader 1 are contained
1559 * and visible before idling and before any callbacks are executed
1560 * by reclaimers.
1561 *
1562 * In summary, the detector does not know of or wait for reader 2, but
1563 * it does not have to since it is a new reader that will not access
1564 * data from previous GPs and will see any changes.
1565 */
1566 memory_barrier(); /* MB C */
1567
1568 cpu_mask_for_each(*cpu_mask, cpu_id) {
1569 /*
1570 * The cpu already checked for and passed through a quiescent
1571 * state since the beginning of this GP.
1572 *
1573 * _rcu_cur_gp is modified by local detector thread only.
1574 * Therefore, it is up-to-date even without a lock.
1575 *
1576 * cpu.last_seen_gp may not be up-to-date. At worst, we will
1577 * unnecessarily sample its last_seen_gp with a smp_call.
1578 */
1579 bool cpu_acked_gp = (cpus[cpu_id].rcu.last_seen_gp == _rcu_cur_gp);
1580
1581 /*
1582 * Either the cpu is idle or it is exiting away from idle mode
1583 * and already sees the most current _rcu_cur_gp. See comment
1584 * in wait_for_readers().
1585 */
1586 bool cpu_idle = cpus[cpu_id].idle;
1587
1588 if (cpu_acked_gp || cpu_idle) {
1589 cpu_mask_reset(cpu_mask, cpu_id);
1590 }
1591 }
1592}
1593
1594/** Serially invokes sample_local_cpu(arg) on each cpu of reader_cpus. */
1595static void sample_cpus(cpu_mask_t *reader_cpus, void *arg)
1596{
1597 cpu_mask_for_each(*reader_cpus, cpu_id) {
1598 smp_call(cpu_id, sample_local_cpu, arg);
1599
1600 /* Update statistic. */
1601 if (CPU->id != cpu_id)
1602 ++rcu.stat_smp_call_cnt;
1603 }
1604}
1605
1606static void upd_missed_gp_in_wait(rcu_gp_t completed_gp)
1607{
1608 ASSERT(CPU->rcu.cur_cbs_gp <= completed_gp);
1609
1610 size_t delta = (size_t)(completed_gp - CPU->rcu.cur_cbs_gp);
1611 CPU->rcu.stat_missed_gp_in_wait += delta;
1612}
1613
1614/** Globally note that the current thread was preempted in a reader section. */
1615static void note_preempted_reader(void)
1616{
1617 irq_spinlock_lock(&rcu.preempt_lock, false);
1618
1619 if (CPU->rcu.last_seen_gp != _rcu_cur_gp) {
1620 /* The reader started before the GP started - we must wait for it.*/
1621 list_append(&THREAD->rcu.preempt_link, &rcu.cur_preempted);
1622 } else {
1623 /*
1624 * The reader started after the GP started and this cpu
1625 * already noted a quiescent state. We might block the next GP.
1626 */
1627 list_append(&THREAD->rcu.preempt_link, &rcu.next_preempted);
1628 }
1629
1630 irq_spinlock_unlock(&rcu.preempt_lock, false);
1631}
1632
1633/** Remove the current thread from the global list of preempted readers. */
1634static void rm_preempted_reader(void)
1635{
1636 irq_spinlock_lock(&rcu.preempt_lock, false);
1637
1638 ASSERT(link_used(&THREAD->rcu.preempt_link));
1639
1640 bool prev_empty = list_empty(&rcu.cur_preempted);
1641 list_remove(&THREAD->rcu.preempt_link);
1642 bool now_empty = list_empty(&rcu.cur_preempted);
1643
1644 /* This was the last reader in cur_preempted. */
1645 bool last_removed = now_empty && !prev_empty;
1646
1647 /*
1648 * Preempted readers are blocking the detector and
1649 * this was the last reader blocking the current GP.
1650 */
1651 if (last_removed && rcu.preempt_blocking_det) {
1652 rcu.preempt_blocking_det = false;
1653 semaphore_up(&rcu.remaining_readers);
1654 }
1655
1656 irq_spinlock_unlock(&rcu.preempt_lock, false);
1657}
1658
1659/** Waits for any preempted readers blocking this grace period to finish.*/
1660static bool wait_for_preempt_reader(void)
1661{
1662 irq_spinlock_lock(&rcu.preempt_lock, true);
1663
1664 bool reader_exists = !list_empty(&rcu.cur_preempted);
1665 rcu.preempt_blocking_det = reader_exists;
1666
1667 irq_spinlock_unlock(&rcu.preempt_lock, true);
1668
1669 if (reader_exists) {
1670 /* Update statistic. */
1671 ++rcu.stat_preempt_blocking_cnt;
1672
1673 return semaphore_down_interruptable(&rcu.remaining_readers);
1674 }
1675
1676 return true;
1677}
1678
1679static void upd_max_cbs_in_slice(void)
1680{
1681 rcu_cpu_data_t *cr = &CPU->rcu;
1682
1683 if (cr->arriving_cbs_cnt > cr->last_arriving_cnt) {
1684 size_t arrived_cnt = cr->arriving_cbs_cnt - cr->last_arriving_cnt;
1685 cr->stat_max_slice_cbs = max(arrived_cnt, cr->stat_max_slice_cbs);
1686 }
1687
1688 cr->last_arriving_cnt = cr->arriving_cbs_cnt;
1689}
1690
1691/** Prints RCU run-time statistics. */
1692void rcu_print_stat(void)
1693{
1694 /*
1695 * Don't take locks. Worst case is we get out-dated values.
1696 * CPU local values are updated without any locks, so there
1697 * are no locks to lock in order to get up-to-date values.
1698 */
1699
1700#ifdef RCU_PREEMPT_PODZIMEK
1701 const char *algo = "podzimek-preempt-rcu";
1702#elif defined(RCU_PREEMPT_A)
1703 const char *algo = "a-preempt-rcu";
1704#endif
1705
1706 printf("Config: expedite_threshold=%d, critical_threshold=%d,"
1707 " detect_sleep=%dms, %s\n",
1708 EXPEDITE_THRESHOLD, CRITICAL_THRESHOLD, DETECT_SLEEP_MS, algo);
1709 printf("Completed GPs: %" PRIu64 "\n", rcu.completed_gp);
1710 printf("Expedited GPs: %zu\n", rcu.stat_expedited_cnt);
1711 printf("Delayed GPs: %zu (cpus w/ still running readers after gp sleep)\n",
1712 rcu.stat_delayed_cnt);
1713 printf("Preempt blocked GPs: %zu (waited for preempted readers; "
1714 "running or not)\n", rcu.stat_preempt_blocking_cnt);
1715 printf("Smp calls: %zu\n", rcu.stat_smp_call_cnt);
1716
1717 printf("Max arrived callbacks per GP and CPU:\n");
1718 for (unsigned int i = 0; i < config.cpu_count; ++i) {
1719 printf(" %zu", cpus[i].rcu.stat_max_cbs);
1720 }
1721
1722 printf("\nAvg arrived callbacks per GP and CPU (nonempty batches only):\n");
1723 for (unsigned int i = 0; i < config.cpu_count; ++i) {
1724 printf(" %zu", cpus[i].rcu.stat_avg_cbs);
1725 }
1726
1727 printf("\nMax arrived callbacks per time slice and CPU:\n");
1728 for (unsigned int i = 0; i < config.cpu_count; ++i) {
1729 printf(" %zu", cpus[i].rcu.stat_max_slice_cbs);
1730 }
1731
1732 printf("\nMissed GP notifications per CPU:\n");
1733 for (unsigned int i = 0; i < config.cpu_count; ++i) {
1734 printf(" %zu", cpus[i].rcu.stat_missed_gps);
1735 }
1736
1737 printf("\nMissed GP notifications per CPU while waking up:\n");
1738 for (unsigned int i = 0; i < config.cpu_count; ++i) {
1739 printf(" %zu", cpus[i].rcu.stat_missed_gp_in_wait);
1740 }
1741 printf("\n");
1742}
1743
1744/** @}
1745 */
Note: See TracBrowser for help on using the repository browser.