Ignore:
File:
1 edited

Legend:

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

    r90c8b8d r7e752b2  
    5252 *
    5353 */
    54 void spinlock_initialize(spinlock_t *lock, char *name)
     54void spinlock_initialize(spinlock_t *lock, const char *name)
    5555{
    5656        atomic_set(&lock->val, 0);
     
    102102               
    103103                if (i++ > DEADLOCK_THRESHOLD) {
    104                         printf("cpu%u: looping on spinlock %" PRIp ":%s, "
    105                             "caller=%" PRIp "(%s)\n", CPU->id, lock, lock->name,
    106                             CALLER, symtab_fmt_name_lookup(CALLER));
     104                        printf("cpu%u: looping on spinlock %p:%s, "
     105                            "caller=%p (%s)\n", CPU->id, lock, lock->name,
     106                            (void *) CALLER, symtab_fmt_name_lookup(CALLER));
    107107                       
    108108                        i = 0;
     
    120120}
    121121
     122/** Unlock spinlock
     123 *
     124 * Unlock spinlock.
     125 *
     126 * @param sl Pointer to spinlock_t structure.
     127 */
     128void spinlock_unlock_debug(spinlock_t *lock)
     129{
     130        ASSERT_SPINLOCK(spinlock_locked(lock), lock);
     131       
     132        /*
     133         * Prevent critical section code from bleeding out this way down.
     134         */
     135        CS_LEAVE_BARRIER();
     136       
     137        atomic_set(&lock->val, 0);
     138        preemption_enable();
     139}
     140
    122141#endif
    123142
    124143/** Lock spinlock conditionally
    125144 *
    126  * Lock spinlock conditionally.
    127  * If the spinlock is not available at the moment,
    128  * signal failure.
     145 * Lock spinlock conditionally. If the spinlock is not available
     146 * at the moment, signal failure.
    129147 *
    130148 * @param lock Pointer to spinlock_t structure.
     
    149167}
    150168
     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
    151179#endif
    152180
     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
    153336/** @}
    154337 */
Note: See TracChangeset for help on using the changeset viewer.