Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 1501 → Rev 1502

/kernel/trunk/generic/src/synch/waitq.c
135,6 → 135,14
grab_locks:
spinlock_lock(&t->lock);
if ((wq = t->sleep_queue)) { /* assignment */
if (!(t->sleep_interruptible)) {
/*
* The sleep cannot be interrupted.
*/
spinlock_unlock(&t->lock);
goto out;
}
if (!spinlock_trylock(&wq->lock)) {
spinlock_unlock(&t->lock);
goto grab_locks; /* avoid deadlock */
159,7 → 167,7
 
/** Sleep until either wakeup, timeout or interruption occurs
*
* This is a sleep implementation which allows itself to be
* This is a sleep implementation which allows itself to time out or to be
* interrupted from the sleep, restoring a failover context.
*
* Sleepers are organised in a FIFO fashion in a structure called wait queue.
169,18 → 177,22
*
* @param wq Pointer to wait queue.
* @param usec Timeout in microseconds.
* @param nonblocking Blocking vs. non-blocking operation mode switch.
* @param flags Specify mode of the sleep.
*
* If usec is greater than zero, regardless of the value of nonblocking,
* the call will not return until either timeout or wakeup comes.
* The sleep can be interrupted only if the
* SYNCH_FLAGS_INTERRUPTIBLE bit is specified in flags.
* If usec is greater than zero, regardless of the value of the
* SYNCH_FLAGS_NON_BLOCKING bit in flags, the call will not return until either timeout,
* interruption or wakeup comes.
*
* If usec is zero and @nonblocking is zero (false), the call
* will not return until wakeup comes.
* If usec is zero and the SYNCH_FLAGS_NON_BLOCKING bit is not set in flags, the call
* will not return until wakeup or interruption comes.
*
* If usec is zero and nonblocking is non-zero (true), the call will
* If usec is zero and the SYNCH_FLAGS_NON_BLOCKING bit is set in flags, the call will
* immediately return, reporting either success or failure.
*
* @return Returns one of: ESYNCH_WOULD_BLOCK, ESYNCH_TIMEOUT,
* @return Returns one of: ESYNCH_WOULD_BLOCK, ESYNCH_TIMEOUT, ESYNCH_INTERRUPTED,
* ESYNCH_OK_ATOMIC, ESYNCH_OK_BLOCKED.
*
* @li ESYNCH_WOULD_BLOCK means that the sleep failed because at the time
197,13 → 209,13
* @li ESYNCH_OK_BLOCKED means that the sleep succeeded; the full sleep was
* attempted.
*/
int waitq_sleep_timeout(waitq_t *wq, __u32 usec, int nonblocking)
int waitq_sleep_timeout(waitq_t *wq, __u32 usec, int flags)
{
ipl_t ipl;
int rc;
ipl = waitq_sleep_prepare(wq);
rc = waitq_sleep_timeout_unsafe(wq, usec, nonblocking);
rc = waitq_sleep_timeout_unsafe(wq, usec, flags);
waitq_sleep_finish(wq, rc, ipl);
return rc;
}
276,11 → 288,11
*
* @param wq See waitq_sleep_timeout().
* @param usec See waitq_sleep_timeout().
* @param nonblocking See waitq_sleep_timeout().
* @param flags See waitq_sleep_timeout().
*
* @return See waitq_sleep_timeout().
*/
int waitq_sleep_timeout_unsafe(waitq_t *wq, __u32 usec, int nonblocking)
int waitq_sleep_timeout_unsafe(waitq_t *wq, __u32 usec, int flags)
{
/* checks whether to go to sleep at all */
if (wq->missed_wakeups) {
288,7 → 300,7
return ESYNCH_OK_ATOMIC;
}
else {
if (nonblocking && (usec == 0)) {
if ((flags & SYNCH_FLAGS_NON_BLOCKING) && (usec == 0)) {
/* return immediatelly instead of going to sleep */
return ESYNCH_WOULD_BLOCK;
}
299,14 → 311,19
*/
spinlock_lock(&THREAD->lock);
 
/*
* Set context that will be restored if the sleep
* of this thread is ever interrupted.
*/
if (!context_save(&THREAD->sleep_interruption_context)) {
/* Short emulation of scheduler() return code. */
spinlock_unlock(&THREAD->lock);
return ESYNCH_INTERRUPTED;
if (flags & SYNCH_FLAGS_INTERRUPTIBLE) {
/*
* Set context that will be restored if the sleep
* of this thread is ever interrupted.
*/
THREAD->sleep_interruptible = true;
if (!context_save(&THREAD->sleep_interruption_context)) {
/* Short emulation of scheduler() return code. */
spinlock_unlock(&THREAD->lock);
return ESYNCH_INTERRUPTED;
}
} else {
THREAD->sleep_interruptible = false;
}
 
if (usec) {