Changeset 0cf813d in mainline
- Timestamp:
- 2012-07-16T15:37:11Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1c1da4b
- Parents:
- 057e77f
- Location:
- kernel/generic
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/compiler/barrier.h
r057e77f r0cf813d 5 5 #define compiler_barrier() asm volatile ("" ::: "memory") 6 6 7 /** Forces the compiler to access (ie load/store) the variable only once. */ 7 8 #define ACCESS_ONCE(var) (*((volatile typeof(var)*)&(var))) 8 9 -
kernel/generic/include/synch/rcu.h
r057e77f r0cf813d 71 71 */ 72 72 rcu_item_t *cur_cbs; 73 /** Number of callbacks in cur_cbs. */ 74 size_t cur_cbs_cnt; 73 75 /** Callbacks to invoke once the next grace period ends, ie next_cbs_gp. 74 76 * Accessed by the local reclaimer only. 75 77 */ 76 78 rcu_item_t *next_cbs; 79 /** Number of callbacks in next_cbs. */ 80 size_t next_cbs_cnt; 77 81 /** New callbacks are place at the end of this list. */ 78 82 rcu_item_t *arriving_cbs; … … 114 118 size_t stat_avg_cbs; 115 119 size_t stat_missed_gps; 120 size_t stat_missed_gp_in_wait; 121 size_t stat_max_slice_cbs; 122 size_t last_arriving_cnt; 116 123 } rcu_cpu_data_t; 117 124 -
kernel/generic/src/synch/rcu.c
r057e77f r0cf813d 54 54 * when non-expedited grace period detection is in progress. 55 55 */ 56 #define DETECT_SLEEP_MS 556 #define DETECT_SLEEP_MS 10 57 57 /* 58 58 * Max number of pending callbacks in the local cpu's queue before 59 59 * aggressively expediting the current grace period 60 60 */ 61 #define EXPEDITE_THRESHOLD 1000 61 #define EXPEDITE_THRESHOLD 2000 62 /* 63 * Max number of callbacks to execute in one go with preemption 64 * enabled. If there are more callbacks to be executed they will 65 * be run with preemption disabled in order to prolong reclaimer's 66 * time slice and give it a chance to catch up with callback producers. 67 */ 68 #define CRITICAL_THRESHOLD 30000 62 69 /* Half the number of values a uint32 can hold. */ 63 70 #define UINT32_MAX_HALF 2147483648U 64 71 65 72 66 /* cGlobal RCU data. */73 /** Global RCU data. */ 67 74 typedef struct rcu_data { 68 75 /** Detector uses so signal reclaimers that a grace period ended. */ … … 102 109 rcu_gp_t completed_gp; 103 110 104 /** Protect the following 3 fields. */111 /** Protects the following 3 fields. */ 105 112 IRQ_SPINLOCK_DECLARE(preempt_lock); 106 113 /** Preexisting readers that have been preempted. */ … … 121 128 atomic_t delaying_cpu_cnt; 122 129 123 /** Interrupt able attached detector thread pointer. */130 /** Interruptible attached detector thread pointer. */ 124 131 thread_t *detector_thr; 125 132 … … 153 160 static void req_detection(size_t req_cnt); 154 161 static bool wait_for_cur_cbs_gp_end(bool expedite, rcu_gp_t *last_completed_gp); 162 static void upd_missed_gp_in_wait(rcu_gp_t completed_gp); 155 163 static bool cv_wait_for_gp(rcu_gp_t wait_on_gp); 156 164 static void detector(void *); … … 165 173 static bool wait_for_delaying_cpus(void); 166 174 static bool wait_for_preempt_reader(void); 175 static void upd_max_cbs_in_slice(void); 167 176 168 177 … … 210 219 211 220 CPU->rcu.cur_cbs = 0; 221 CPU->rcu.cur_cbs_cnt = 0; 212 222 CPU->rcu.next_cbs = 0; 223 CPU->rcu.next_cbs_cnt = 0; 213 224 CPU->rcu.arriving_cbs = 0; 214 225 CPU->rcu.parriving_cbs_tail = &CPU->rcu.arriving_cbs; 215 216 226 CPU->rcu.arriving_cbs_cnt = 0; 217 227 … … 222 232 223 233 semaphore_initialize(&CPU->rcu.arrived_flag, 0); 224 CPU->rcu.reclaimer_thr = 0; 234 235 /* BSP creates reclaimer threads before AP's rcu_cpu_init() runs. */ 236 if (config.cpu_active == 1) 237 CPU->rcu.reclaimer_thr = 0; 225 238 226 239 CPU->rcu.stat_max_cbs = 0; 227 240 CPU->rcu.stat_avg_cbs = 0; 228 241 CPU->rcu.stat_missed_gps = 0; 242 CPU->rcu.stat_missed_gp_in_wait = 0; 243 CPU->rcu.stat_max_slice_cbs = 0; 244 CPU->rcu.last_arriving_cnt = 0; 229 245 } 230 246 … … 611 627 { 612 628 ASSERT(THREAD && THREAD->wired); 629 ASSERT(THREAD == CPU->rcu.reclaimer_thr); 613 630 614 631 rcu_gp_t last_compl_gp = 0; … … 616 633 617 634 while (ok && wait_for_pending_cbs()) { 635 ASSERT(CPU->rcu.reclaimer_thr == THREAD); 636 618 637 exec_completed_cbs(last_compl_gp); 619 638 620 639 bool expedite = advance_cbs(); 621 640 … … 651 670 upd_stat_missed_gp(last_completed_gp); 652 671 653 if (CPU->rcu.cur_cbs_gp <= last_completed_gp) { 654 exec_cbs(&CPU->rcu.cur_cbs); 655 } 656 672 /* Both next_cbs and cur_cbs GP elapsed. */ 657 673 if (CPU->rcu.next_cbs_gp <= last_completed_gp) { 658 exec_cbs(&CPU->rcu.next_cbs); 674 ASSERT(CPU->rcu.cur_cbs_gp <= CPU->rcu.next_cbs_gp); 675 676 size_t exec_cnt = CPU->rcu.cur_cbs_cnt + CPU->rcu.next_cbs_cnt; 677 678 if (exec_cnt < CRITICAL_THRESHOLD) { 679 exec_cbs(&CPU->rcu.cur_cbs); 680 exec_cbs(&CPU->rcu.next_cbs); 681 } else { 682 /* 683 * Getting overwhelmed with too many callbacks to run. 684 * Disable preemption in order to prolong our time slice 685 * and catch up with updaters posting new callbacks. 686 */ 687 preemption_disable(); 688 exec_cbs(&CPU->rcu.cur_cbs); 689 exec_cbs(&CPU->rcu.next_cbs); 690 preemption_enable(); 691 } 692 693 CPU->rcu.cur_cbs_cnt = 0; 694 CPU->rcu.next_cbs_cnt = 0; 695 } else if (CPU->rcu.cur_cbs_gp <= last_completed_gp) { 696 697 if (CPU->rcu.cur_cbs_cnt < CRITICAL_THRESHOLD) { 698 exec_cbs(&CPU->rcu.cur_cbs); 699 } else { 700 /* 701 * Getting overwhelmed with too many callbacks to run. 702 * Disable preemption in order to prolong our time slice 703 * and catch up with updaters posting new callbacks. 704 */ 705 preemption_disable(); 706 exec_cbs(&CPU->rcu.cur_cbs); 707 preemption_enable(); 708 } 709 710 CPU->rcu.cur_cbs_cnt = 0; 659 711 } 660 712 } … … 696 748 /* Move next_cbs to cur_cbs. */ 697 749 CPU->rcu.cur_cbs = CPU->rcu.next_cbs; 750 CPU->rcu.cur_cbs_cnt = CPU->rcu.next_cbs_cnt; 698 751 CPU->rcu.cur_cbs_gp = CPU->rcu.next_cbs_gp; 699 752 … … 708 761 || CPU->rcu.expedite_arriving; 709 762 710 /* Update statistics. */711 upd_stat_cb_cnts(CPU->rcu.arriving_cbs_cnt);712 713 763 CPU->rcu.expedite_arriving = false; 764 714 765 CPU->rcu.next_cbs = CPU->rcu.arriving_cbs; 766 CPU->rcu.next_cbs_cnt = CPU->rcu.arriving_cbs_cnt; 767 715 768 CPU->rcu.arriving_cbs = 0; 716 769 CPU->rcu.parriving_cbs_tail = &CPU->rcu.arriving_cbs; … … 718 771 719 772 interrupts_restore(ipl); 773 774 /* Update statistics of arrived callbacks. */ 775 upd_stat_cb_cnts(CPU->rcu.next_cbs_cnt); 720 776 721 777 /* … … 824 880 /* Wait for cur_cbs_gp to end. */ 825 881 bool interrupted = cv_wait_for_gp(CPU->rcu.cur_cbs_gp); 826 882 827 883 *completed_gp = rcu.completed_gp; 828 884 spinlock_unlock(&rcu.gp_lock); 829 885 886 upd_missed_gp_in_wait(*completed_gp); 887 830 888 return !interrupted; 831 889 } 890 891 static void upd_missed_gp_in_wait(rcu_gp_t completed_gp) 892 { 893 ASSERT(CPU->rcu.cur_cbs_gp <= completed_gp); 894 895 size_t delta = (size_t)(completed_gp - CPU->rcu.cur_cbs_gp); 896 CPU->rcu.stat_missed_gp_in_wait += delta; 897 } 898 832 899 833 900 /** Requests the detector to detect at least req_cnt consecutive grace periods.*/ … … 838 905 rcu.req_gp_end_cnt = req_cnt; 839 906 840 //printf("reqs:%d,idle:%d ", req_cnt, detector_idle);841 842 907 if (detector_idle) { 843 908 ASSERT(rcu.cur_gp == rcu.completed_gp); 844 909 condvar_signal(&rcu.req_gp_changed); 845 910 } 846 } else {847 //printf("myreqs:%d,detr:%d ", req_cnt, rcu.req_gp_end_cnt);848 911 } 849 912 } … … 1266 1329 THREAD->priority = -1; 1267 1330 } 1331 else if (THREAD == CPU->rcu.reclaimer_thr) { 1332 THREAD->priority = -1; 1333 } 1334 1335 upd_max_cbs_in_slice(); 1336 } 1337 1338 static void upd_max_cbs_in_slice(void) 1339 { 1340 rcu_cpu_data_t *cr = &CPU->rcu; 1341 1342 if (cr->arriving_cbs_cnt > cr->last_arriving_cnt) { 1343 size_t arrived_cnt = cr->arriving_cbs_cnt - cr->last_arriving_cnt; 1344 cr->stat_max_slice_cbs = max(arrived_cnt, cr->stat_max_slice_cbs); 1345 } 1346 1347 cr->last_arriving_cnt = cr->arriving_cbs_cnt; 1268 1348 } 1269 1349 … … 1281 1361 void rcu_print_stat(void) 1282 1362 { 1283 /* Don't take locks. Worst case is we get out-dated values. */ 1284 printf("Configuration: expedite_threshold=%d, detect_sleep=%dms\n", 1285 EXPEDITE_THRESHOLD, DETECT_SLEEP_MS); 1363 /* 1364 * Don't take locks. Worst case is we get out-dated values. 1365 * CPU local values are updated without any locks, so there 1366 * are no locks to lock in order to get up-to-date values. 1367 */ 1368 1369 printf("Configuration: expedite_threshold=%d, critical_threshold=%d," 1370 " detect_sleep=%dms\n", 1371 EXPEDITE_THRESHOLD, CRITICAL_THRESHOLD, DETECT_SLEEP_MS); 1286 1372 printf("Completed GPs: %" PRIu64 "\n", rcu.completed_gp); 1287 1373 printf("Expedited GPs: %zu\n", rcu.stat_expedited_cnt); … … 1292 1378 printf("Smp calls: %zu\n", rcu.stat_smp_call_cnt); 1293 1379 1294 printf("Max callbacks per GP:\n");1295 for (unsigned i = 0; i < config.cpu_count; ++i) {1380 printf("Max arrived callbacks per GP and CPU:\n"); 1381 for (unsigned int i = 0; i < config.cpu_count; ++i) { 1296 1382 printf(" %zu", cpus[i].rcu.stat_max_cbs); 1297 1383 } 1298 1384 1299 printf("\nAvg callbacks per GP(nonempty batches only):\n");1300 for (unsigned i = 0; i < config.cpu_count; ++i) {1385 printf("\nAvg arrived callbacks per GP and CPU (nonempty batches only):\n"); 1386 for (unsigned int i = 0; i < config.cpu_count; ++i) { 1301 1387 printf(" %zu", cpus[i].rcu.stat_avg_cbs); 1302 1388 } 1303 1389 1304 printf("\nMissed GP notifications:\n"); 1305 for (unsigned i = 0; i < config.cpu_count; ++i) { 1390 printf("\nMax arrived callbacks per time slice and CPU:\n"); 1391 for (unsigned int i = 0; i < config.cpu_count; ++i) { 1392 printf(" %zu", cpus[i].rcu.stat_max_slice_cbs); 1393 } 1394 1395 printf("\nMissed GP notifications per CPU:\n"); 1396 for (unsigned int i = 0; i < config.cpu_count; ++i) { 1306 1397 printf(" %zu", cpus[i].rcu.stat_missed_gps); 1307 1398 } 1399 1400 printf("\nMissed GP notifications per CPU while waking up:\n"); 1401 for (unsigned int i = 0; i < config.cpu_count; ++i) { 1402 printf(" %zu", cpus[i].rcu.stat_missed_gp_in_wait); 1403 } 1308 1404 printf("\n"); 1309 1405 }
Note:
See TracChangeset
for help on using the changeset viewer.