diff options
Diffstat (limited to 'src/thread')
| -rw-r--r-- | src/thread/__timedwait.c | 2 | ||||
| -rw-r--r-- | src/thread/pthread_cond_timedwait.c | 3 | ||||
| -rw-r--r-- | src/thread/sem_post.c | 3 | ||||
| -rw-r--r-- | src/thread/sem_timedwait.c | 45 | ||||
| -rw-r--r-- | src/thread/sem_trywait.c | 5 | 
5 files changed, 37 insertions, 21 deletions
| diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c index 28b777bc..a673099b 100644 --- a/src/thread/__timedwait.c +++ b/src/thread/__timedwait.c @@ -18,6 +18,6 @@ int __timedwait(volatile int *addr, int val, clockid_t clk, const struct timespe  	}  	if (priv) priv = 128; priv=0;  	r = -__syscall(__NR_futex, (long)addr, FUTEX_WAIT | priv, val, at ? (long)&to : 0); -	if (r == ETIMEDOUT) return r; +	if (r == ETIMEDOUT || r == EINTR) return r;  	return 0;  } diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c index 1439aace..7a19fc55 100644 --- a/src/thread/pthread_cond_timedwait.c +++ b/src/thread/pthread_cond_timedwait.c @@ -16,7 +16,8 @@ int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, const struct t  	if ((r=pthread_mutex_unlock(m))) return r;  	CANCELPT_BEGIN; -	e = __timedwait(&c->_c_block, 1, c->_c_clock, ts, 0); +	do e = __timedwait(&c->_c_block, 1, c->_c_clock, ts, 0); +	while (e == EINTR);  	CANCELPT_END;  	pthread_cleanup_pop(0); diff --git a/src/thread/sem_post.c b/src/thread/sem_post.c index 0bd8a462..8f4700c3 100644 --- a/src/thread/sem_post.c +++ b/src/thread/sem_post.c @@ -3,7 +3,8 @@  int sem_post(sem_t *sem)  { -	if (!a_fetch_add(sem->__val, 1)) +	a_inc(sem->__val); +	if (sem->__val[1])  		__wake(sem->__val, 1, 0);  	return 0;  } diff --git a/src/thread/sem_timedwait.c b/src/thread/sem_timedwait.c index 11a01700..4f45c172 100644 --- a/src/thread/sem_timedwait.c +++ b/src/thread/sem_timedwait.c @@ -1,26 +1,41 @@  #include <semaphore.h>  #include "pthread_impl.h" +static void cleanup(void *p) +{ +	a_dec(p); +} +  int sem_timedwait(sem_t *sem, const struct timespec *at)  { -	int val; +	int r; + +	if (a_fetch_add(sem->__val, -1) > 0) return 0; +	a_inc(sem->__val); + +	if (at && at->tv_nsec >= 1000000000UL) { +		errno = EINVAL; +		return -1; +	} + +	a_inc(sem->__val+1); +	pthread_cleanup_push(cleanup, sem->__val+1) +	CANCELPT_BEGIN;  	for (;;) { -		if (a_fetch_add(sem->__val, -1) > 0) return 0; -		val = a_fetch_add(sem->__val, 1)+1; -		if (val==1) __wake(sem->__val, 1, 0); -		if (at && at->tv_nsec >= 1000000000UL) { -			errno = EINVAL; -			return -1; -		} -		CANCELPT_BEGIN; -		if (val <= 0 && __timedwait(sem->__val, val, CLOCK_REALTIME, at, 0) == ETIMEDOUT) { -			errno = ETIMEDOUT; -			CANCELPT_TRY; -			CANCELPT_END; -			return -1; +		r = 0; +		if (!sem_trywait(sem)) break; +		r = __timedwait(sem->__val, 0, CLOCK_REALTIME, at, 0); +		if (r) { +			errno = r; +			r = -1; +			break;  		}  		CANCELPT_TRY; -		CANCELPT_END;  	} +	CANCELPT_END; + +	pthread_cleanup_pop(1); + +	return r;  } diff --git a/src/thread/sem_trywait.c b/src/thread/sem_trywait.c index c5370c70..beb7aa5d 100644 --- a/src/thread/sem_trywait.c +++ b/src/thread/sem_trywait.c @@ -3,9 +3,8 @@  int sem_trywait(sem_t *sem)  { -	int val = a_fetch_add(sem->__val, -1); -	if (val > 0) return 0; -	if (!a_fetch_add(sem->__val, 1)) +	if (a_fetch_add(sem->__val, -1) > 0) return 0; +	if (!a_fetch_add(sem->__val, 1) && sem->__val[1])  		__wake(sem->__val, 1, 0);  	errno = EAGAIN;  	return -1; | 
