X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fpthread-futex.c;h=a08eb80e0abd962c042f31c993f329cfa22b1aa2;hb=4bf2de6a2adff75459cf218c8bff67f6cdb91211;hp=f010f9da9bfba92bd49c0f42cf712d5c8807088e;hpb=fe962ba01d267b92f638c8f0d19be41054219f04;p=sbcl.git diff --git a/src/runtime/pthread-futex.c b/src/runtime/pthread-futex.c index f010f9d..a08eb80 100644 --- a/src/runtime/pthread-futex.c +++ b/src/runtime/pthread-futex.c @@ -205,17 +205,46 @@ futex_relative_to_abs(struct timespec *tp, int relative) return 0; } +static int +futex_istimeout(struct timeval *timeout) +{ + int ret; + struct timeval tv; + + if (timeout == NULL) + return 0; + + ret = gettimeofday(&tv, NULL); + if (ret != 0) + return ret; + + return (tv.tv_sec > timeout->tv_sec) || + ((tv.tv_sec == timeout->tv_sec) && tv.tv_usec > timeout->tv_usec); +} + int futex_wait(int *lock_word, int oldval, long sec, unsigned long usec) { int ret, result; struct futex *futex; sigset_t oldset, newset; + struct timeval tv, *timeout; sigemptyset(&newset); sigaddset_deferrable(&newset); again: + if (sec < 0) + timeout = NULL; + else { + ret = gettimeofday(&tv, NULL); + if (ret != 0) + return ret; + tv.tv_sec = tv.tv_sec + sec + (tv.tv_usec + usec) / 1000000; + tv.tv_usec = (tv.tv_usec + usec) % 1000000; + timeout = &tv; + } + pthread_sigmask(SIG_BLOCK, &newset, &oldset); futex = futex_get(lock_word); @@ -245,7 +274,7 @@ again: &abstime); futex_assert(result == 0 || result == ETIMEDOUT); - if (result != ETIMEDOUT) + if (result != ETIMEDOUT || futex_istimeout(timeout)) break; /* futex system call of Linux returns with EINTR errno when @@ -271,6 +300,9 @@ done: goto again; } + if (result == ETIMEDOUT) + return 1; + return result; }