1.0.26.15: interrupt.c refactoring
[sbcl.git] / src / runtime / pthread-futex.c
index 8a3da46..cddcda9 100644 (file)
@@ -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)
+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);