/kernel/trunk/generic/src/proc/thread.c |
---|
303,7 → 303,6 |
t->call_me_with = NULL; |
timeout_initialize(&t->sleep_timeout); |
t->sleep_interruptible = false; |
t->sleep_queue = NULL; |
t->timeout_pending = 0; |
386,7 → 385,7 |
waitq_initialize(&wq); |
(void) waitq_sleep_timeout(&wq, usec, SYNCH_FLAGS_NON_BLOCKING); |
(void) waitq_sleep_timeout(&wq, usec, SYNCH_NON_BLOCKING); |
} |
/** Register thread out-of-context invocation |
/kernel/trunk/generic/src/synch/waitq.c |
---|
135,14 → 135,6 |
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 */ |
167,7 → 159,7 |
/** Sleep until either wakeup, timeout or interruption occurs |
* |
* This is a sleep implementation which allows itself to time out or to be |
* This is a sleep implementation which allows itself to be |
* interrupted from the sleep, restoring a failover context. |
* |
* Sleepers are organised in a FIFO fashion in a structure called wait queue. |
177,22 → 169,18 |
* |
* @param wq Pointer to wait queue. |
* @param usec Timeout in microseconds. |
* @param flags Specify mode of the sleep. |
* @param nonblocking Blocking vs. non-blocking operation mode switch. |
* |
* 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 greater than zero, regardless of the value of nonblocking, |
* the call will not return until either timeout or 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 zero (false), the call |
* will not return until wakeup comes. |
* |
* If usec is zero and the SYNCH_FLAGS_NON_BLOCKING bit is set in flags, the call will |
* If usec is zero and nonblocking is non-zero (true), the call will |
* immediately return, reporting either success or failure. |
* |
* @return Returns one of: ESYNCH_WOULD_BLOCK, ESYNCH_TIMEOUT, ESYNCH_INTERRUPTED, |
* @return Returns one of: ESYNCH_WOULD_BLOCK, ESYNCH_TIMEOUT, |
* ESYNCH_OK_ATOMIC, ESYNCH_OK_BLOCKED. |
* |
* @li ESYNCH_WOULD_BLOCK means that the sleep failed because at the time |
209,13 → 197,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 flags) |
int waitq_sleep_timeout(waitq_t *wq, __u32 usec, int nonblocking) |
{ |
ipl_t ipl; |
int rc; |
ipl = waitq_sleep_prepare(wq); |
rc = waitq_sleep_timeout_unsafe(wq, usec, flags); |
rc = waitq_sleep_timeout_unsafe(wq, usec, nonblocking); |
waitq_sleep_finish(wq, rc, ipl); |
return rc; |
} |
288,11 → 276,11 |
* |
* @param wq See waitq_sleep_timeout(). |
* @param usec See waitq_sleep_timeout(). |
* @param flags See waitq_sleep_timeout(). |
* @param nonblocking See waitq_sleep_timeout(). |
* |
* @return See waitq_sleep_timeout(). |
*/ |
int waitq_sleep_timeout_unsafe(waitq_t *wq, __u32 usec, int flags) |
int waitq_sleep_timeout_unsafe(waitq_t *wq, __u32 usec, int nonblocking) |
{ |
/* checks whether to go to sleep at all */ |
if (wq->missed_wakeups) { |
300,7 → 288,7 |
return ESYNCH_OK_ATOMIC; |
} |
else { |
if ((flags & SYNCH_FLAGS_NON_BLOCKING) && (usec == 0)) { |
if (nonblocking && (usec == 0)) { |
/* return immediatelly instead of going to sleep */ |
return ESYNCH_WOULD_BLOCK; |
} |
311,20 → 299,15 |
*/ |
spinlock_lock(&THREAD->lock); |
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) { |
/* We use the timeout variant. */ |
/kernel/trunk/generic/src/synch/futex.c |
---|
99,12 → 99,12 |
* |
* @param uaddr Userspace address of the futex counter. |
* @param usec If non-zero, number of microseconds this thread is willing to sleep. |
* @param flags Select mode of operation. |
* @param trydown If usec is zero and trydown is non-zero, conditional operation will be attempted. |
* |
* @return One of ESYNCH_TIMEOUT, ESYNCH_OK_ATOMIC and ESYNCH_OK_BLOCKED. See synch.h. |
* If there is no physical mapping for uaddr ENOENT is returned. |
*/ |
__native sys_futex_sleep_timeout(__address uaddr, __u32 usec, int flags) |
__native sys_futex_sleep_timeout(__address uaddr, __u32 usec, int trydown) |
{ |
futex_t *futex; |
__address paddr; |
130,7 → 130,7 |
futex = futex_find(paddr); |
return (__native) waitq_sleep_timeout(&futex->wq, usec, flags | SYNCH_FLAGS_INTERRUPTIBLE); |
return (__native) waitq_sleep_timeout(&futex->wq, usec, trydown); |
} |
/** Wakeup one thread waiting in futex wait queue. |
/kernel/trunk/generic/src/synch/condvar.c |
---|
74,16 → 74,13 |
* @param cv Condition variable. |
* @param mtx Mutex. |
* @param usec Timeout value in microseconds. |
* @param flags Select mode of operation. |
* |
* For exact description of meaning of possible combinations |
* of usec and flags, see comment for waitq_sleep_timeout(). |
* Note that when SYNCH_FLAGS_NON_BLOCKING is specified here, |
* ESYNCH_WOULD_BLOCK is always returned. |
* For exact description of meaning of possible values of usec, |
* see comment for waitq_sleep_timeout(). |
* |
* @return See comment for waitq_sleep_timeout(). |
*/ |
int _condvar_wait_timeout(condvar_t *cv, mutex_t *mtx, __u32 usec, int flags) |
int _condvar_wait_timeout(condvar_t *cv, mutex_t *mtx, __u32 usec) |
{ |
int rc; |
ipl_t ipl; |
92,7 → 89,7 |
mutex_unlock(mtx); |
cv->wq.missed_wakeups = 0; /* Enforce blocking. */ |
rc = waitq_sleep_timeout_unsafe(&cv->wq, usec, flags); |
rc = waitq_sleep_timeout_unsafe(&cv->wq, usec, SYNCH_BLOCKING); |
mutex_lock(mtx); |
waitq_sleep_finish(&cv->wq, rc, ipl); |
/kernel/trunk/generic/src/synch/mutex.c |
---|
53,16 → 53,16 |
* |
* @param mtx Mutex. |
* @param usec Timeout in microseconds. |
* @param flags Specify mode of operation. |
* @param trylock Switches between blocking and non-blocking mode. |
* |
* For exact description of possible combinations of |
* usec and flags, see comment for waitq_sleep_timeout(). |
* usec and trylock, see comment for waitq_sleep_timeout(). |
* |
* @return See comment for waitq_sleep_timeout(). |
*/ |
int _mutex_lock_timeout(mutex_t *mtx, __u32 usec, int flags) |
int _mutex_lock_timeout(mutex_t *mtx, __u32 usec, int trylock) |
{ |
return _semaphore_down_timeout(&mtx->sem, usec, flags); |
return _semaphore_down_timeout(&mtx->sem, usec, trylock); |
} |
/** Release mutex |
75,4 → 75,3 |
{ |
semaphore_up(&mtx->sem); |
} |
/kernel/trunk/generic/src/synch/semaphore.c |
---|
67,16 → 67,16 |
* |
* @param s Semaphore. |
* @param usec Timeout in microseconds. |
* @param flags Select mode of operation. |
* @param trydown Switches between blocking and non-blocking mode. |
* |
* For exact description of possible combinations of |
* usec and flags, see comment for waitq_sleep_timeout(). |
* usec and trydown, see comment for waitq_sleep_timeout(). |
* |
* @return See comment for waitq_sleep_timeout(). |
*/ |
int _semaphore_down_timeout(semaphore_t *s, __u32 usec, int flags) |
int _semaphore_down_timeout(semaphore_t *s, __u32 usec, int trydown) |
{ |
return waitq_sleep_timeout(&s->wq, usec, flags); |
return waitq_sleep_timeout(&s->wq, usec, trydown); |
} |
/** Semaphore up |
/kernel/trunk/generic/src/synch/rwlock.c |
---|
89,14 → 89,14 |
* |
* @param rwl Reader/Writer lock. |
* @param usec Timeout in microseconds. |
* @param flags Specify mode of operation. |
* @param trylock Switches between blocking and non-blocking mode. |
* |
* For exact description of possible combinations of |
* usec and flags, see comment for waitq_sleep_timeout(). |
* @usec and @trylock, see comment for waitq_sleep_timeout(). |
* |
* @return See comment for waitq_sleep_timeout(). |
*/ |
int _rwlock_write_lock_timeout(rwlock_t *rwl, __u32 usec, int flags) |
int _rwlock_write_lock_timeout(rwlock_t *rwl, __u32 usec, int trylock) |
{ |
ipl_t ipl; |
int rc; |
111,11 → 111,11 |
* Writers take the easy part. |
* They just need to acquire the exclusive mutex. |
*/ |
rc = _mutex_lock_timeout(&rwl->exclusive, usec, flags); |
rc = _mutex_lock_timeout(&rwl->exclusive, usec, trylock); |
if (SYNCH_FAILED(rc)) { |
/* |
* Lock operation timed out or was interrupted. |
* Lock operation timed out. |
* The state of rwl is UNKNOWN at this point. |
* No claims about its holder can be made. |
*/ |
143,14 → 143,14 |
* |
* @param rwl Reader/Writer lock. |
* @param usec Timeout in microseconds. |
* @param flags Select mode of operation. |
* @param trylock Switches between blocking and non-blocking mode. |
* |
* For exact description of possible combinations of |
* usec and flags, see comment for waitq_sleep_timeout(). |
* usec and trylock, see comment for waitq_sleep_timeout(). |
* |
* @return See comment for waitq_sleep_timeout(). |
*/ |
int _rwlock_read_lock_timeout(rwlock_t *rwl, __u32 usec, int flags) |
int _rwlock_read_lock_timeout(rwlock_t *rwl, __u32 usec, int trylock) |
{ |
int rc; |
ipl_t ipl; |
199,7 → 199,7 |
thread_register_call_me(release_spinlock, NULL); |
#endif |
rc = _mutex_lock_timeout(&rwl->exclusive, usec, flags); |
rc = _mutex_lock_timeout(&rwl->exclusive, usec, trylock); |
switch (rc) { |
case ESYNCH_WOULD_BLOCK: |
/* |
208,9 → 208,8 |
thread_register_call_me(NULL, NULL); |
spinlock_unlock(&rwl->lock); |
case ESYNCH_TIMEOUT: |
case ESYNCH_INTERRUPTED: |
/* |
* The sleep timed out. |
* The sleep timeouted. |
* We just restore interrupt priority level. |
*/ |
case ESYNCH_OK_BLOCKED: |
/kernel/trunk/generic/src/ipc/sysipc.c |
---|
502,16 → 502,16 |
* |
* @param calldata Pointer to buffer where the call/answer data is stored |
* @param usec Timeout. See waitq_sleep_timeout() for explanation. |
* @param flags Select mode of sleep operation. See waitq_sleep_timeout() for explanation. |
* @param nonblocking See waitq_sleep_timeout() for explanation. |
* |
* @return Callid, if callid & 1, then the call is answer |
*/ |
__native sys_ipc_wait_for_call(ipc_data_t *calldata, __u32 usec, int flags) |
__native sys_ipc_wait_for_call(ipc_data_t *calldata, __u32 usec, int nonblocking) |
{ |
call_t *call; |
restart: |
call = ipc_wait_for_call(&TASK->answerbox, usec, flags | SYNCH_FLAGS_INTERRUPTIBLE); |
call = ipc_wait_for_call(&TASK->answerbox, usec, nonblocking); |
if (!call) |
return 0; |
/kernel/trunk/generic/src/ipc/ipc.c |
---|
142,7 → 142,7 |
request->callerbox = &sync_box; |
ipc_call(phone, request); |
ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE); |
ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, SYNCH_BLOCKING); |
} |
/** Answer message that was not dispatched and is not entered in |
305,12 → 305,12 |
* @param box Answerbox expecting the call. |
* @param usec Timeout in microseconds. See documentation for waitq_sleep_timeout() for |
* decription of its special meaning. |
* @param flags Select mode of sleep operation. See documentation for waitq_sleep_timeout()i |
* for description of its special meaning. |
* @param nonblocking Blocking vs. non-blocking operation mode switch. See documentation |
* for waitq_sleep_timeout() for description of its special meaning. |
* @return Recived message address |
* - to distinguish between call and answer, look at call->flags |
*/ |
call_t * ipc_wait_for_call(answerbox_t *box, __u32 usec, int flags) |
call_t * ipc_wait_for_call(answerbox_t *box, __u32 usec, int nonblocking) |
{ |
call_t *request; |
ipl_t ipl; |
317,7 → 317,7 |
int rc; |
restart: |
rc = waitq_sleep_timeout(&box->wq, usec, flags); |
rc = waitq_sleep_timeout(&box->wq, usec, nonblocking); |
if (SYNCH_FAILED(rc)) |
return NULL; |
412,7 → 412,7 |
/* Wait for all async answers to arrive */ |
while (atomic_get(&task->active_calls)) { |
call = ipc_wait_for_call(&task->answerbox, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE); |
call = ipc_wait_for_call(&task->answerbox, SYNCH_NO_TIMEOUT, SYNCH_BLOCKING); |
ASSERT((call->flags & IPC_CALL_ANSWERED) || (call->flags & IPC_CALL_NOTIF)); |
ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); |