diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/thread/__timedwait.c | 59 | 
1 files changed, 28 insertions, 31 deletions
| diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c index e15e2d0a..302273ae 100644 --- a/src/thread/__timedwait.c +++ b/src/thread/__timedwait.c @@ -4,45 +4,42 @@  #include "futex.h"  #include "syscall.h" -static int do_wait(volatile int *addr, int val, clockid_t clk, const struct timespec *at, int cp, int priv) +static int do_wait(volatile int *addr, int val, +	clockid_t clk, const struct timespec *at, int priv)  { -	int r, flag = 0; +	int r;  	struct timespec to, *top=0; -	if (!at) goto notimeout; -	if (at->tv_nsec >= 1000000000UL) -		return EINVAL; -	if (clk == CLOCK_REALTIME || clk == CLOCK_MONOTONIC) { -		if (clk == CLOCK_REALTIME) flag = FUTEX_CLOCK_REALTIME; -		if (cp) r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT_BITSET|flag, val, at, 0, -1); -		else r = -__syscall(SYS_futex, addr, FUTEX_WAIT_BITSET|flag, val, at, 0, -1); -		if (r != EINVAL && r != ENOSYS) goto done; -	} -	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 (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;  	} -	if (to.tv_sec < 0) return ETIMEDOUT; -	top = &to; -notimeout: -	if (cp) r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT, val, top); -	else r = -__syscall(SYS_futex, addr, FUTEX_WAIT, val, top); -done: + +	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 __timedwait(volatile int *addr, int val, +	clockid_t clk, const struct timespec *at, +	void (*cleanup)(void *), void *arg, int priv)  { -	int r; -	if (cleanup) { -		pthread_cleanup_push(cleanup, arg); -		r = do_wait(addr, val, clk, at, 1, priv); -		pthread_cleanup_pop(0); -	} else { -		r = do_wait(addr, val, clk, at, 0, 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;  } | 
