mirror of
https://github.com/fluencelabs/musl
synced 2025-05-21 11:41:29 +00:00
the new absolute-time-based wait kernelside was hard to get right and basically just code duplication. it could only improve "performance" when waiting, and even then, the improvement was just slight drop in cpu usage during a wait. actually, with vdso clock_gettime, the "old" way will be even faster than the "new" way if the time has already expired, since it will not invoke any syscalls. it can determine entirely in userspace that it needs to return ETIMEDOUT.
46 lines
1.0 KiB
C
46 lines
1.0 KiB
C
#include <pthread.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
#include "futex.h"
|
|
#include "syscall.h"
|
|
|
|
static int do_wait(volatile int *addr, int val,
|
|
clockid_t clk, const struct timespec *at, int priv)
|
|
{
|
|
int r;
|
|
struct timespec to, *top=0;
|
|
|
|
if (at) {
|
|
if (at->tv_nsec >= 1000000000UL) 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 += 1000000000;
|
|
}
|
|
if (to.tv_sec < 0) return ETIMEDOUT;
|
|
top = &to;
|
|
}
|
|
|
|
r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT, val, top);
|
|
if (r == EINTR || r == EINVAL || r == ETIMEDOUT) return r;
|
|
return 0;
|
|
}
|
|
|
|
int __timedwait(volatile int *addr, int val,
|
|
clockid_t clk, const struct timespec *at,
|
|
void (*cleanup)(void *), void *arg, int priv)
|
|
{
|
|
int r, cs;
|
|
|
|
if (!cleanup) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
|
|
pthread_cleanup_push(cleanup, arg);
|
|
|
|
r = do_wait(addr, val, clk, at, priv);
|
|
|
|
pthread_cleanup_pop(0);
|
|
if (!cleanup) pthread_setcancelstate(cs, 0);
|
|
|
|
return r;
|
|
}
|