diff --git a/proc/cond.c b/proc/cond.c index 22b7b9818..1ddc8ede8 100644 --- a/proc/cond.c +++ b/proc/cond.c @@ -88,7 +88,8 @@ int proc_condWait(int c, int m, time_t timeout) { cond_t *cond; mutex_t *mutex; - int err; + int err = 0; + time_t offs, abstime = 0; cond = cond_get(c); if (cond == NULL) { @@ -101,7 +102,43 @@ int proc_condWait(int c, int m, time_t timeout) return -EINVAL; } - err = proc_lockWait(&cond->queue, &mutex->lock, timeout); + if (timeout != 0) { + switch (cond->attr.clock) { + case PH_CLOCK_REALTIME: + proc_gettime(&abstime, &offs); + if (abstime + offs > timeout) { + err = -ETIME; + break; + } + + abstime = timeout - offs; + break; + + case PH_CLOCK_MONOTONIC: + proc_gettime(&abstime, NULL); + if (abstime > timeout) { + err = -ETIME; + break; + } + + abstime = timeout; + break; + + case PH_CLOCK_RELATIVE: + proc_gettime(&abstime, NULL); + abstime += timeout; + break; + + default: + /* Wrong clock type, should never happen */ + err = -EINVAL; + break; + } + } + + if (err == 0) { + err = proc_lockWait(&cond->queue, &mutex->lock, abstime); + } mutex_put(mutex); cond_put(cond); diff --git a/proc/lock.h b/proc/lock.h index 72a1dfbaa..ac4c53f02 100644 --- a/proc/lock.h +++ b/proc/lock.h @@ -43,6 +43,7 @@ extern int proc_lockSet2(lock_t *lock1, lock_t *lock2); extern int proc_lockTry(lock_t *lock); +/* `timeout` - in microseconds, absolute time relative to monotonic clock */ extern int proc_lockWait(struct _thread_t **queue, lock_t *lock, time_t timeout); diff --git a/proc/threads.c b/proc/threads.c index 9052c7c7e..1b9280c9d 100644 --- a/proc/threads.c +++ b/proc/threads.c @@ -1072,7 +1072,6 @@ static void _proc_threadDequeue(thread_t *t) static void _proc_threadEnqueue(thread_t **queue, time_t timeout, int interruptible) { thread_t *current; - time_t now; if (*queue == wakeupPending) { (*queue) = NULL; @@ -1089,10 +1088,9 @@ static void _proc_threadEnqueue(thread_t **queue, time_t timeout, int interrupti current->interruptible = interruptible; if (timeout) { - now = _proc_gettimeRaw(); - current->wakeup = now + timeout; + current->wakeup = timeout; lib_rbInsert(&threads_common.sleeping, ¤t->sleeplinkage); - _threads_updateWakeup(now, NULL); + _threads_updateWakeup(_proc_gettimeRaw(), NULL); } _perf_enqueued(current); @@ -1271,9 +1269,11 @@ int proc_join(int tid, time_t timeout) process_t *process; thread_t *ghost, *firstGhost; spinlock_ctx_t sc; + time_t now, abstimeout; hal_spinlockSet(&threads_common.spinlock, &sc); + now = _proc_gettimeRaw(); current = _proc_current(); if (proc_getTid(current) == tid) { hal_spinlockClear(&threads_common.spinlock, &sc); @@ -1284,6 +1284,8 @@ int proc_join(int tid, time_t timeout) ghost = process->ghosts; firstGhost = process->ghosts; + abstimeout = (timeout == 0) ? 0 : now + timeout; + if (tid >= 0) { do { if (firstGhost != NULL) { @@ -1301,7 +1303,7 @@ int proc_join(int tid, time_t timeout) break; } else { - err = _proc_threadWait(&process->reaper, timeout, &sc); + err = _proc_threadWait(&process->reaper, abstimeout, &sc); firstGhost = process->ghosts; ghost = firstGhost; } @@ -1310,7 +1312,7 @@ int proc_join(int tid, time_t timeout) else { /* compatibility with existing code */ while ((ghost = process->ghosts) == NULL) { - err = _proc_threadWait(&process->reaper, timeout, &sc); + err = _proc_threadWait(&process->reaper, abstimeout, &sc); if (err == -EINTR || err == -ETIME) { break; }