Ignore:
File:
1 edited

Legend:

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

    r9d58539 rcc106e4  
    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_impl(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.