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);
&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
goto again;
}
+ if (result == ETIMEDOUT)
+ return 1;
+
return result;
}
{
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);