X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fpthread-futex.c;h=cddcda9ec9e866617133a7870f8c3e822c039776;hb=f0cb0cf9c0fe1b6fce5d10dbd34a0b7b249c4ae8;hp=f010f9da9bfba92bd49c0f42cf712d5c8807088e;hpb=fe962ba01d267b92f638c8f0d19be41054219f04;p=sbcl.git diff --git a/src/runtime/pthread-futex.c b/src/runtime/pthread-futex.c index f010f9d..cddcda9 100644 --- a/src/runtime/pthread-futex.c +++ b/src/runtime/pthread-futex.c @@ -205,18 +205,44 @@ 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; - - sigemptyset(&newset); - sigaddset_deferrable(&newset); + sigset_t oldset; + struct timeval tv, *timeout; again: - pthread_sigmask(SIG_BLOCK, &newset, &oldset); + 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; + } + + block_deferrable_signals(0, &oldset); futex = futex_get(lock_word); @@ -245,7 +271,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 +297,9 @@ done: goto again; } + if (result == ETIMEDOUT) + return 1; + return result; } @@ -279,12 +308,9 @@ futex_wake(int *lock_word, int n) { int ret; struct futex *futex; - sigset_t newset, oldset; - - sigemptyset(&newset); - sigaddset_deferrable(&newset); + sigset_t oldset; - pthread_sigmask(SIG_BLOCK, &newset, &oldset); + block_deferrable_signals(0, &oldset); futex = futex_get(lock_word);