Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset f0fcb04 in mainline


Ignore:
Timestamp:
2012-07-29T19:26:32Z (9 years ago)
Author:
Adam Hraska <adam.hraska+hos@…>
Branches:
lfn, master
Children:
d4d36f9
Parents:
5b03a72
Message:

rcu: Replaced checking three variables to see if the detector needs to be notified in rcu_read_unlock() with a single bool cpu.signal_unlock.

Location:
kernel/generic
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/synch/rcu.h

    r5b03a72 rf0fcb04  
    200200                /*
    201201                 * 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.
    206203                 */
    207                 if ((THREAD && THREAD->rcu.was_preempted) || CPU->rcu.is_delaying_gp) {
     204                if (CPU->rcu.signal_unlock) {
    208205                        /* Rechecks with disabled interrupts. */
    209206                        _rcu_signal_read_unlock();
    210207                }
    211208        }
    212 
    213209       
    214210        preemption_enable();
  • kernel/generic/include/synch/rcu_types.h

    r5b03a72 rf0fcb04  
    107107        bool is_delaying_gp;
    108108       
     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       
    109115        /** Positive if there are callbacks pending in arriving_cbs. */
    110116        semaphore_t arrived_flag;
  • kernel/generic/src/synch/rcu.c

    r5b03a72 rf0fcb04  
    239239       
    240240        CPU->rcu.is_delaying_gp = false;
     241        CPU->rcu.signal_unlock = false;
    241242       
    242243        semaphore_initialize(&CPU->rcu.arrived_flag, 0);
     
    410411        ASSERT(PREEMPTION_DISABLED || interrupts_disabled());
    411412       
     413        /* todo: make NMI safe with cpu-local atomic ops. */
     414       
    412415        /*
    413416         * We have to disable interrupts in order to make checking
     
    457460                irq_spinlock_unlock(&rcu.preempt_lock, false);
    458461        }
     462       
     463        /* If there was something to signal to the detector we have done so. */
     464        CPU->rcu.signal_unlock = false;
     465       
    459466        interrupts_restore(ipl);
    460467}
     
    12011208                        /* Note to notify the detector from rcu_read_unlock(). */
    12021209                        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                       
    12031218                        atomic_inc(&rcu.delaying_cpu_cnt);
    12041219                } else {
     
    12741289{
    12751290        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. */
    12781303        THREAD->rcu.nesting_cnt = CPU->rcu.nesting_cnt;
    12791304        /* Interrupt handlers might use RCU while idle in scheduler(). */
     
    13001325        }
    13011326       
     1327       
    13021328        /*
    13031329         * The preempted reader has been noted globally. There are therefore
     
    13171343                semaphore_up(&rcu.remaining_readers);
    13181344        }
    1319        
     1345
    13201346        /*
    13211347         * Forcefully associate the detector with the highest priority
     
    13541380        /* Load the thread's saved nesting count from before it was preempted. */
    13551381        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;
    13561391}
    13571392
Note: See TracChangeset for help on using the changeset viewer.