Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/synch/spinlock.c

    r13108f24 r313b617  
    128128void spinlock_unlock_debug(spinlock_t *lock)
    129129{
    130         ASSERT(atomic_get(&lock->val) != 0);
     130        ASSERT_SPINLOCK(spinlock_locked(lock), lock);
    131131       
    132132        /*
     
    143143/** Lock spinlock conditionally
    144144 *
    145  * Lock spinlock conditionally.
    146  * If the spinlock is not available at the moment,
    147  * signal failure.
     145 * Lock spinlock conditionally. If the spinlock is not available
     146 * at the moment, signal failure.
    148147 *
    149148 * @param lock Pointer to spinlock_t structure.
     
    168167}
    169168
     169/** Find out whether the spinlock is currently locked.
     170 *
     171 * @param lock          Spinlock.
     172 * @return              True if the spinlock is locked, false otherwise.
     173 */
     174bool spinlock_locked(spinlock_t *lock)
     175{
     176        return atomic_get(&lock->val) != 0;
     177}
     178
    170179#endif
    171180
     181/** Initialize interrupts-disabled spinlock
     182 *
     183 * @param lock IRQ spinlock to be initialized.
     184 * @param name IRQ spinlock name.
     185 *
     186 */
     187void irq_spinlock_initialize(irq_spinlock_t *lock, const char *name)
     188{
     189        spinlock_initialize(&(lock->lock), name);
     190        lock->guard = false;
     191        lock->ipl = 0;
     192}
     193
     194/** Lock interrupts-disabled spinlock
     195 *
     196 * Lock a spinlock which requires disabled interrupts.
     197 *
     198 * @param lock    IRQ spinlock to be locked.
     199 * @param irq_dis If true, interrupts are actually disabled
     200 *                prior locking the spinlock. If false, interrupts
     201 *                are expected to be already disabled.
     202 *
     203 */
     204void irq_spinlock_lock(irq_spinlock_t *lock, bool irq_dis)
     205{
     206        if (irq_dis) {
     207                ipl_t ipl = interrupts_disable();
     208                spinlock_lock(&(lock->lock));
     209               
     210                lock->guard = true;
     211                lock->ipl = ipl;
     212        } else {
     213                ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock);
     214               
     215                spinlock_lock(&(lock->lock));
     216                ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
     217        }
     218}
     219
     220/** Unlock interrupts-disabled spinlock
     221 *
     222 * Unlock a spinlock which requires disabled interrupts.
     223 *
     224 * @param lock    IRQ spinlock to be unlocked.
     225 * @param irq_res If true, interrupts are restored to previously
     226 *                saved interrupt level.
     227 *
     228 */
     229void irq_spinlock_unlock(irq_spinlock_t *lock, bool irq_res)
     230{
     231        ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock);
     232       
     233        if (irq_res) {
     234                ASSERT_IRQ_SPINLOCK(lock->guard, lock);
     235               
     236                lock->guard = false;
     237                ipl_t ipl = lock->ipl;
     238               
     239                spinlock_unlock(&(lock->lock));
     240                interrupts_restore(ipl);
     241        } else {
     242                ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
     243                spinlock_unlock(&(lock->lock));
     244        }
     245}
     246
     247/** Lock interrupts-disabled spinlock
     248 *
     249 * Lock an interrupts-disabled spinlock conditionally. If the
     250 * spinlock is not available at the moment, signal failure.
     251 * Interrupts are expected to be already disabled.
     252 *
     253 * @param lock IRQ spinlock to be locked conditionally.
     254 *
     255 * @return Zero on failure, non-zero otherwise.
     256 *
     257 */
     258int irq_spinlock_trylock(irq_spinlock_t *lock)
     259{
     260        ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock);
     261        int rc = spinlock_trylock(&(lock->lock));
     262       
     263        ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
     264        return rc;
     265}
     266
     267/** Pass lock from one interrupts-disabled spinlock to another
     268 *
     269 * Pass lock from one IRQ spinlock to another IRQ spinlock
     270 * without enabling interrupts during the process.
     271 *
     272 * The first IRQ spinlock is supposed to be locked.
     273 *
     274 * @param unlock IRQ spinlock to be unlocked.
     275 * @param lock   IRQ spinlock to be locked.
     276 *
     277 */
     278void irq_spinlock_pass(irq_spinlock_t *unlock, irq_spinlock_t *lock)
     279{
     280        ASSERT_IRQ_SPINLOCK(interrupts_disabled(), unlock);
     281       
     282        /* Pass guard from unlock to lock */
     283        bool guard = unlock->guard;
     284        ipl_t ipl = unlock->ipl;
     285        unlock->guard = false;
     286       
     287        spinlock_unlock(&(unlock->lock));
     288        spinlock_lock(&(lock->lock));
     289       
     290        ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
     291       
     292        if (guard) {
     293                lock->guard = true;
     294                lock->ipl = ipl;
     295        }
     296}
     297
     298/** Hand-over-hand locking of interrupts-disabled spinlocks
     299 *
     300 * Implement hand-over-hand locking between two interrupts-disabled
     301 * spinlocks without enabling interrupts during the process.
     302 *
     303 * The first IRQ spinlock is supposed to be locked.
     304 *
     305 * @param unlock IRQ spinlock to be unlocked.
     306 * @param lock   IRQ spinlock to be locked.
     307 *
     308 */
     309void irq_spinlock_exchange(irq_spinlock_t *unlock, irq_spinlock_t *lock)
     310{
     311        ASSERT_IRQ_SPINLOCK(interrupts_disabled(), unlock);
     312       
     313        spinlock_lock(&(lock->lock));
     314        ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
     315       
     316        /* Pass guard from unlock to lock */
     317        if (unlock->guard) {
     318                lock->guard = true;
     319                lock->ipl = unlock->ipl;
     320                unlock->guard = false;
     321        }
     322       
     323        spinlock_unlock(&(unlock->lock));
     324}
     325
     326/** Find out whether the IRQ spinlock is currently locked.
     327 *
     328 * @param lock          IRQ spinlock.
     329 * @return              True if the IRQ spinlock is locked, false otherwise.
     330 */
     331bool irq_spinlock_locked(irq_spinlock_t *ilock)
     332{
     333        return spinlock_locked(&ilock->lock);
     334}
     335
    172336/** @}
    173337 */
Note: See TracChangeset for help on using the changeset viewer.