Changeset f0fcb04 in mainline
- Timestamp:
- 2012-07-29T19:26:32Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d4d36f9
- Parents:
- 5b03a72
- Location:
- kernel/generic
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/synch/rcu.h
r5b03a72 rf0fcb04 200 200 /* 201 201 * The thread was preempted while in a critical section or 202 * the detector is eagerly waiting for this cpu's reader 203 * to finish. 204 * 205 * Note that THREAD may be 0 in scheduler() and not just during boot. 202 * the detector is eagerly waiting for this cpu's reader to finish. 206 203 */ 207 if ( (THREAD && THREAD->rcu.was_preempted) || CPU->rcu.is_delaying_gp) {204 if (CPU->rcu.signal_unlock) { 208 205 /* Rechecks with disabled interrupts. */ 209 206 _rcu_signal_read_unlock(); 210 207 } 211 208 } 212 213 209 214 210 preemption_enable(); -
kernel/generic/include/synch/rcu_types.h
r5b03a72 rf0fcb04 107 107 bool is_delaying_gp; 108 108 109 /** True if we should signal the detector that we exited a reader section. 110 * 111 * Equal to (THREAD->rcu.was_preempted || CPU->rcu.is_delaying_gp). 112 */ 113 bool signal_unlock; 114 109 115 /** Positive if there are callbacks pending in arriving_cbs. */ 110 116 semaphore_t arrived_flag; -
kernel/generic/src/synch/rcu.c
r5b03a72 rf0fcb04 239 239 240 240 CPU->rcu.is_delaying_gp = false; 241 CPU->rcu.signal_unlock = false; 241 242 242 243 semaphore_initialize(&CPU->rcu.arrived_flag, 0); … … 410 411 ASSERT(PREEMPTION_DISABLED || interrupts_disabled()); 411 412 413 /* todo: make NMI safe with cpu-local atomic ops. */ 414 412 415 /* 413 416 * We have to disable interrupts in order to make checking … … 457 460 irq_spinlock_unlock(&rcu.preempt_lock, false); 458 461 } 462 463 /* If there was something to signal to the detector we have done so. */ 464 CPU->rcu.signal_unlock = false; 465 459 466 interrupts_restore(ipl); 460 467 } … … 1201 1208 /* Note to notify the detector from rcu_read_unlock(). */ 1202 1209 CPU->rcu.is_delaying_gp = true; 1210 /* 1211 * Set signal_unlock only after setting is_delaying_gp so 1212 * that NMI handlers do not accidentally clear it in unlock() 1213 * before seeing and acting upon is_delaying_gp. 1214 */ 1215 compiler_barrier(); 1216 CPU->rcu.signal_unlock = true; 1217 1203 1218 atomic_inc(&rcu.delaying_cpu_cnt); 1204 1219 } else { … … 1274 1289 { 1275 1290 ASSERT(interrupts_disabled()); 1276 1277 /* Save the thread's nesting count when its not running. */ 1291 /* todo: make is_delaying_gp and was_preempted NMI safe via local atomics.*/ 1292 1293 /* 1294 * Prevent NMI handlers from interfering. The detector will be notified 1295 * here if CPU->rcu.is_delaying_gp and the current thread is no longer 1296 * running so there is nothing to signal to the detector. 1297 */ 1298 CPU->rcu.signal_unlock = false; 1299 /* Separates clearing of .signal_unlock from CPU->rcu.nesting_cnt = 0. */ 1300 compiler_barrier(); 1301 1302 /* Save the thread's nesting count when it is not running. */ 1278 1303 THREAD->rcu.nesting_cnt = CPU->rcu.nesting_cnt; 1279 1304 /* Interrupt handlers might use RCU while idle in scheduler(). */ … … 1300 1325 } 1301 1326 1327 1302 1328 /* 1303 1329 * The preempted reader has been noted globally. There are therefore … … 1317 1343 semaphore_up(&rcu.remaining_readers); 1318 1344 } 1319 1345 1320 1346 /* 1321 1347 * Forcefully associate the detector with the highest priority … … 1354 1380 /* Load the thread's saved nesting count from before it was preempted. */ 1355 1381 CPU->rcu.nesting_cnt = THREAD->rcu.nesting_cnt; 1382 /* 1383 * In the unlikely event that a NMI occurs between the loading of the 1384 * variables and setting signal_unlock, the NMI handler may invoke 1385 * rcu_read_unlock() and clear signal_unlock. In that case we will 1386 * incorrectly overwrite signal_unlock from false to true. This event 1387 * situation benign and the next rcu_read_unlock() will at worst 1388 * needlessly invoke _rcu_signal_unlock(). 1389 */ 1390 CPU->rcu.signal_unlock = THREAD->rcu.was_preempted || CPU->rcu.is_delaying_gp; 1356 1391 } 1357 1392
Note:
See TracChangeset
for help on using the changeset viewer.