Changeset 4ec9ea41 in mainline
- Timestamp:
- 2012-07-27T13:37:31Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 14c9aa6
- Parents:
- 2bcf6c6
- Location:
- kernel
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/synch/rcu.h
r2bcf6c6 r4ec9ea41 111 111 bool expedite_arriving; 112 112 113 /** Protected by global rcu.barrier_mtx. */ 114 rcu_item_t barrier_item; 115 113 116 /** Interruptable attached reclaimer thread. */ 114 117 struct thread *reclaimer_thr; … … 202 205 extern bool rcu_read_locked(void); 203 206 extern void rcu_synchronize(void); 207 extern void rcu_synchronize_expedite(void); 204 208 extern void rcu_call(rcu_item_t *rcu_item, rcu_func_t func); 209 extern void rcu_barrier(void); 205 210 206 211 extern void rcu_print_stat(void); … … 215 220 extern void rcu_before_thread_runs(void); 216 221 217 /* Debugging/testing support. Not part of public API. Do not use! */218 222 extern uint64_t rcu_completed_gps(void); 219 223 extern void _rcu_call(bool expedite, rcu_item_t *rcu_item, rcu_func_t func); 224 extern void _rcu_synchronize(bool expedite); 220 225 221 226 #endif -
kernel/generic/src/synch/rcu.c
r2bcf6c6 r4ec9ea41 41 41 #include <synch/semaphore.h> 42 42 #include <synch/spinlock.h> 43 #include <synch/mutex.h> 43 44 #include <proc/thread.h> 44 45 #include <cpu/cpu_mask.h> … … 128 129 atomic_t delaying_cpu_cnt; 129 130 131 /** Excludes simultaneous rcu_barrier() calls. */ 132 mutex_t barrier_mtx; 133 /** Number of cpus that we are waiting for to complete rcu_barrier(). */ 134 atomic_t barrier_wait_cnt; 135 /** rcu_barrier() waits for the completion of barrier callbacks on this wq.*/ 136 waitq_t barrier_wq; 137 130 138 /** Interruptible attached detector thread pointer. */ 131 139 thread_t *detector_thr; … … 146 154 static void rcu_read_unlock_impl(size_t *pnesting_cnt); 147 155 static void synch_complete(rcu_item_t *rcu_item); 156 static void add_barrier_cb(void *arg); 157 static void barrier_complete(rcu_item_t *barrier_item); 148 158 static void check_qs(void); 149 159 static void record_qs(void); … … 196 206 rcu.preempt_blocking_det = false; 197 207 208 mutex_initialize(&rcu.barrier_mtx, MUTEX_PASSIVE); 209 atomic_set(&rcu.barrier_wait_cnt, 0); 210 waitq_initialize(&rcu.barrier_wq); 211 198 212 atomic_set(&rcu.delaying_cpu_cnt, 0); 199 213 … … 297 311 void rcu_stop(void) 298 312 { 299 /* todo: stop accepting new callbacks instead of just letting them linger?*/300 301 313 /* Stop and wait for reclaimers. */ 302 314 for (unsigned int cpu_id = 0; cpu_id < config.cpu_active; ++cpu_id) { … … 539 551 void rcu_synchronize(void) 540 552 { 553 _rcu_synchronize(false); 554 } 555 556 /** Blocks until all preexisting readers exit their critical sections. */ 557 void rcu_synchronize_expedite(void) 558 { 559 _rcu_synchronize(true); 560 } 561 562 /** Blocks until all preexisting readers exit their critical sections. */ 563 void _rcu_synchronize(bool expedite) 564 { 541 565 /* Calling from a reader section will deadlock. */ 542 566 ASSERT(THREAD == 0 || 0 == THREAD->rcu.nesting_cnt); … … 545 569 546 570 waitq_initialize(&completion.wq); 547 rcu_call(&completion.rcu_item, synch_complete);571 _rcu_call(expedite, &completion.rcu_item, synch_complete); 548 572 waitq_sleep(&completion.wq); 549 573 waitq_complete_wakeup(&completion.wq); … … 556 580 ASSERT(completion); 557 581 waitq_wakeup(&completion->wq, WAKEUP_FIRST); 582 } 583 584 /** Waits for all outstanding rcu calls to complete. */ 585 void rcu_barrier(void) 586 { 587 /* 588 * Serialize rcu_barrier() calls so we don't overwrite cpu.barrier_item 589 * currently in use by rcu_barrier(). 590 */ 591 mutex_lock(&rcu.barrier_mtx); 592 593 /* 594 * Ensure we queue a barrier callback on all cpus before the already 595 * enqueued barrier callbacks start signaling completion. 596 */ 597 atomic_set(&rcu.barrier_wait_cnt, 1); 598 599 DEFINE_CPU_MASK(cpu_mask); 600 cpu_mask_active(cpu_mask); 601 602 cpu_mask_for_each(*cpu_mask, cpu_id) { 603 smp_call(cpu_id, add_barrier_cb, 0); 604 } 605 606 if (0 < atomic_predec(&rcu.barrier_wait_cnt)) { 607 waitq_sleep(&rcu.barrier_wq); 608 } 609 610 mutex_unlock(&rcu.barrier_mtx); 611 } 612 613 /** Issues a rcu_barrier() callback on the local cpu. 614 * 615 * Executed with interrupts disabled. 616 */ 617 static void add_barrier_cb(void *arg) 618 { 619 ASSERT(interrupts_disabled() || PREEMPTION_DISABLED); 620 atomic_inc(&rcu.barrier_wait_cnt); 621 rcu_call(&CPU->rcu.barrier_item, barrier_complete); 622 } 623 624 /** Local cpu's rcu_barrier() completion callback. */ 625 static void barrier_complete(rcu_item_t *barrier_item) 626 { 627 /* Is this the last barrier callback completed? */ 628 if (0 == atomic_predec(&rcu.barrier_wait_cnt)) { 629 /* Notify rcu_barrier() that we're done. */ 630 waitq_wakeup(&rcu.barrier_wq, WAKEUP_FIRST); 631 } 558 632 } 559 633 -
kernel/test/synch/rcu1.c
r2bcf6c6 r4ec9ea41 806 806 807 807 /*-------------------------------------------------------------------*/ 808 typedef struct { 809 rcu_item_t rcu_item; 810 atomic_t done; 811 } barrier_t; 812 813 static void barrier_callback(rcu_item_t *item) 814 { 815 barrier_t *b = member_to_inst(item, barrier_t, rcu_item); 816 atomic_set(&b->done, 1); 817 } 818 819 static bool do_barrier(void) 820 { 821 TPRINTF("\nrcu_barrier: Wait for outstanding rcu callbacks to complete\n"); 822 823 barrier_t *barrier = malloc(sizeof(barrier_t), FRAME_ATOMIC); 824 825 if (!barrier) { 826 TPRINTF("[out-of-mem]\n"); 827 return false; 828 } 829 830 atomic_set(&barrier->done, 0); 831 832 rcu_call(&barrier->rcu_item, barrier_callback); 833 rcu_barrier(); 834 835 if (1 == atomic_get(&barrier->done)) { 836 free(barrier); 837 return true; 838 } else { 839 TPRINTF("rcu_barrier() exited prematurely.\n"); 840 /* Leak some mem. */ 841 return false; 842 } 843 } 844 845 /*-------------------------------------------------------------------*/ 808 846 809 847 typedef struct { … … 969 1007 { 1, do_reader_preempt, "do_reader_preempt" }, 970 1008 { 1, do_synch, "do_synch" }, 1009 { 1, do_barrier, "do_barrier" }, 971 1010 { 1, do_reader_exit, "do_reader_exit" }, 972 1011 { 1, do_nop_readers, "do_nop_readers" },
Note:
See TracChangeset
for help on using the changeset viewer.