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

Changeset 46a5b37 in mainline


Ignore:
Timestamp:
2012-07-06T13:04:04Z (10 years ago)
Author:
Adam Hraska <adam.hraska+hos@…>
Branches:
lfn, master, serial
Children:
518dd43
Parents:
ef1603b
Message:

synch: Condvars can now wait with spinlocks and not just a mutex.

Location:
kernel/generic
Files:
2 edited

Legend:

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

    ref1603b r46a5b37  
    3939#include <synch/waitq.h>
    4040#include <synch/mutex.h>
     41#include <synch/spinlock.h>
    4142#include <abi/synch.h>
    4243
     
    5556extern int _condvar_wait_timeout(condvar_t *cv, mutex_t *mtx, uint32_t usec,
    5657    int flags);
     58extern int _condvar_wait_timeout_spinlock(condvar_t *cv, spinlock_t *lock,
     59        uint32_t usec, int flags);
     60extern int _condvar_wait_timeout_irq_spinlock(condvar_t *cv,
     61        irq_spinlock_t *irq_lock, uint32_t usec, int flags);
     62
    5763
    5864#endif
  • kernel/generic/src/synch/condvar.c

    ref1603b r46a5b37  
    3838#include <synch/condvar.h>
    3939#include <synch/mutex.h>
     40#include <synch/spinlock.h>
    4041#include <synch/waitq.h>
    4142#include <arch.h>
     
    101102}
    102103
     104/** Wait for the condition to become true with a locked spinlock.
     105 *
     106 * The function is not aware of irq_spinlock. Therefore do not even
     107 * try passing irq_spinlock_t to it. Use _condvar_wait_timeout_irq_spinlock()
     108 * instead.
     109 *
     110 * @param cv            Condition variable.
     111 * @param lock          Locked spinlock.
     112 * @param usec          Timeout value in microseconds.
     113 * @param flags         Select mode of operation.
     114 *
     115 * For exact description of meaning of possible combinations of usec and flags,
     116 * see comment for waitq_sleep_timeout().  Note that when
     117 * SYNCH_FLAGS_NON_BLOCKING is specified here, ESYNCH_WOULD_BLOCK is always
     118 * returned.
     119 *
     120 * @return See comment for waitq_sleep_timeout().
     121 */
     122int _condvar_wait_timeout_spinlock(condvar_t *cv, spinlock_t *lock,
     123        uint32_t usec, int flags)
     124{
     125        int rc;
     126        ipl_t ipl;
     127       
     128        ipl = waitq_sleep_prepare(&cv->wq);
     129
     130        spinlock_unlock(lock);
     131
     132        cv->wq.missed_wakeups = 0;      /* Enforce blocking. */
     133        rc = waitq_sleep_timeout_unsafe(&cv->wq, usec, flags);
     134
     135        waitq_sleep_finish(&cv->wq, rc, ipl);
     136       
     137        spinlock_lock(lock);
     138       
     139        return rc;
     140}
     141
     142/** Wait for the condition to become true with a locked irq spinlock.
     143 *
     144 * @param cv            Condition variable.
     145 * @param lock          Locked irq spinlock.
     146 * @param usec          Timeout value in microseconds.
     147 * @param flags         Select mode of operation.
     148 *
     149 * For exact description of meaning of possible combinations of usec and flags,
     150 * see comment for waitq_sleep_timeout().  Note that when
     151 * SYNCH_FLAGS_NON_BLOCKING is specified here, ESYNCH_WOULD_BLOCK is always
     152 * returned.
     153 *
     154 * @return See comment for waitq_sleep_timeout().
     155 */
     156int _condvar_wait_timeout_irq_spinlock(condvar_t *cv, irq_spinlock_t *irq_lock,
     157        uint32_t usec, int flags)
     158{
     159        int rc;
     160        /* Save spinlock's state so we can restore it correctly later on. */
     161        ipl_t ipl = irq_lock->ipl;
     162        bool guard = irq_lock->guard;
     163       
     164        irq_lock->guard = false;
     165       
     166        /*
     167         * waitq_prepare() restores interrupts to the current state,
     168         * ie disabled. Therefore, interrupts will remain disabled while
     169         * it spins waiting for a pending timeout handler to complete.
     170         * Although it spins with interrupts disabled there can only
     171         * be a pending timeout if we failed to cancel an imminent
     172         * timeout (on another cpu) during a wakeup. As a result the
     173         * timeout handler is guaranteed to run (it is most likely already
     174         * running) and there is no danger of a deadlock.
     175         */
     176        rc = _condvar_wait_timeout_spinlock(cv, &irq_lock->lock, usec, flags);
     177       
     178        irq_lock->guard = guard;
     179        irq_lock->ipl = ipl;
     180       
     181        return rc;
     182}
     183
     184
    103185/** @}
    104186 */
Note: See TracChangeset for help on using the changeset viewer.