blob: a58ca22cba4fec92adaaa78c053617fe7ba54c15 [file] [log] [blame]
#include "pthread_impl.h"
#include <errno.h>
#include <magenta/syscalls.h>
#include <time.h>
#include "clock_impl.h"
int __timedwait(atomic_int* futex, int val, clockid_t clk, const struct timespec* at) {
struct timespec to;
mx_time_t deadline = MX_TIME_INFINITE;
if (at) {
if (at->tv_nsec >= MX_SEC(1))
return EINVAL;
if (__clock_gettime(clk, &to))
return EINVAL;
to.tv_sec = at->tv_sec - to.tv_sec;
if ((to.tv_nsec = at->tv_nsec - to.tv_nsec) < 0) {
to.tv_sec--;
to.tv_nsec += MX_SEC(1);
}
if (to.tv_sec < 0)
return ETIMEDOUT;
deadline = _mx_deadline_after(MX_SEC(to.tv_sec) + to.tv_nsec);
}
// mx_futex_wait will return MX_ERR_BAD_STATE if someone modifying *addr
// races with this call. But this is indistinguishable from
// otherwise being woken up just before someone else changes the
// value. Therefore this functions returns 0 in that case.
switch (_mx_futex_wait(futex, val, deadline)) {
case MX_OK:
case MX_ERR_BAD_STATE:
return 0;
case MX_ERR_TIMED_OUT:
return ETIMEDOUT;
case MX_ERR_INVALID_ARGS:
default:
__builtin_trap();
}
}