فهرست منبع

factor cancellation cleanup push/pop out of futex __timedwait function

previously, the __timedwait function was optionally a cancellation
point depending on whether it was passed a pointer to a cleaup
function and context to register. as of now, only one caller actually
used such a cleanup function (and it may face removal soon); most
callers either passed a null pointer to disable cancellation or a
dummy cleanup function.

now, __timedwait is never a cancellation point, and __timedwait_cp is
the cancellable version. this makes the intent of the calling code
more obvious and avoids ugly dummy functions and long argument lists.
Rich Felker 10 سال پیش
والد
کامیت
0fc317d83c

+ 1 - 1
src/aio/aio_suspend.c

@@ -61,7 +61,7 @@ int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec
 			break;
 		}
 
-		ret = __timedwait(pfut, expect, CLOCK_MONOTONIC, ts?&at:0, 0, 0, 1);
+		ret = __timedwait(pfut, expect, CLOCK_MONOTONIC, ts?&at:0, 1);
 
 		if (ret) {
 			errno = ret==ETIMEDOUT ? EAGAIN : ret;

+ 2 - 1
src/internal/pthread_impl.h

@@ -107,7 +107,8 @@ int __libc_sigprocmask(int, const sigset_t *, sigset_t *);
 void __lock(volatile int *);
 void __unmapself(void *, size_t);
 
-int __timedwait(volatile int *, int, clockid_t, const struct timespec *, void (*)(void *), void *, int);
+int __timedwait(volatile int *, int, clockid_t, const struct timespec *, int);
+int __timedwait_cp(volatile int *, int, clockid_t, const struct timespec *, int);
 void __wait(volatile int *, volatile int *, int, int);
 static inline void __wake(volatile void *addr, int cnt, int priv)
 {

+ 13 - 9
src/thread/__timedwait.c

@@ -3,15 +3,15 @@
 #include <errno.h>
 #include "futex.h"
 #include "syscall.h"
+#include "pthread_impl.h"
 
 int __pthread_setcancelstate(int, int *);
 int __clock_gettime(clockid_t, struct timespec *);
 
-int __timedwait(volatile int *addr, int val,
-	clockid_t clk, const struct timespec *at,
-	void (*cleanup)(void *), void *arg, int priv)
+int __timedwait_cp(volatile int *addr, int val,
+	clockid_t clk, const struct timespec *at, int priv)
 {
-	int r, cs;
+	int r;
 	struct timespec to, *top=0;
 
 	if (priv) priv = 128;
@@ -28,15 +28,19 @@ int __timedwait(volatile int *addr, int val,
 		top = &to;
 	}
 
-	if (!cleanup) __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
-	pthread_cleanup_push(cleanup, arg);
-
 	r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT|priv, val, top);
 	if (r == ENOSYS) r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT, val, top);
 	if (r != EINTR && r != ETIMEDOUT && r != ECANCELED) r = 0;
 
-	pthread_cleanup_pop(0);
-	if (!cleanup) __pthread_setcancelstate(cs, 0);
+	return r;
+}
 
+int __timedwait(volatile int *addr, int val,
+	clockid_t clk, const struct timespec *at, int priv)
+{
+	int cs, r;
+	__pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+	r = __timedwait_cp(addr, val, clk, at, priv);
+	__pthread_setcancelstate(cs, 0);
 	return r;
 }

+ 1 - 5
src/thread/pthread_cond_timedwait.c

@@ -64,10 +64,6 @@ enum {
 	LEAVING,
 };
 
-static void dummy(void *arg)
-{
-}
-
 int __pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restrict m, const struct timespec *restrict ts)
 {
 	struct waiter node = { 0 };
@@ -104,7 +100,7 @@ int __pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restri
 
 	__pthread_setcancelstate(PTHREAD_CANCEL_MASKED, &cs);
 
-	do e = __timedwait(fut, seq, clock, ts, dummy, 0, !shared);
+	do e = __timedwait_cp(fut, seq, clock, ts, !shared);
 	while (*fut==seq && (!e || e==EINTR));
 	if (e == EINTR) e = 0;
 

+ 1 - 5
src/thread/pthread_join.c

@@ -3,15 +3,11 @@
 
 int __munmap(void *, size_t);
 
-static void dummy(void *p)
-{
-}
-
 int __pthread_join(pthread_t t, void **res)
 {
 	int tmp;
 	pthread_testcancel();
-	while ((tmp = t->tid)) __timedwait(&t->tid, tmp, 0, 0, dummy, 0, 0);
+	while ((tmp = t->tid)) __timedwait_cp(&t->tid, tmp, 0, 0, 0);
 	if (res) *res = t->result;
 	if (t->map_base) __munmap(t->map_base, t->map_size);
 	return 0;

+ 1 - 1
src/thread/pthread_mutex_timedlock.c

@@ -24,7 +24,7 @@ int __pthread_mutex_timedlock(pthread_mutex_t *restrict m, const struct timespec
 		a_inc(&m->_m_waiters);
 		t = r | 0x80000000;
 		a_cas(&m->_m_lock, r, t);
-		r = __timedwait(&m->_m_lock, t, CLOCK_REALTIME, at, 0, 0, priv);
+		r = __timedwait(&m->_m_lock, t, CLOCK_REALTIME, at, priv);
 		a_dec(&m->_m_waiters);
 		if (r && r != EINTR) break;
 	}

+ 1 - 1
src/thread/pthread_rwlock_timedrdlock.c

@@ -15,7 +15,7 @@ int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rw, const struct times
 		t = r | 0x80000000;
 		a_inc(&rw->_rw_waiters);
 		a_cas(&rw->_rw_lock, r, t);
-		r = __timedwait(&rw->_rw_lock, t, CLOCK_REALTIME, at, 0, 0, rw->_rw_shared^128);
+		r = __timedwait(&rw->_rw_lock, t, CLOCK_REALTIME, at, rw->_rw_shared^128);
 		a_dec(&rw->_rw_waiters);
 		if (r && r != EINTR) return r;
 	}

+ 1 - 1
src/thread/pthread_rwlock_timedwrlock.c

@@ -15,7 +15,7 @@ int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rw, const struct times
 		t = r | 0x80000000;
 		a_inc(&rw->_rw_waiters);
 		a_cas(&rw->_rw_lock, r, t);
-		r = __timedwait(&rw->_rw_lock, t, CLOCK_REALTIME, at, 0, 0, rw->_rw_shared^128);
+		r = __timedwait(&rw->_rw_lock, t, CLOCK_REALTIME, at, rw->_rw_shared^128);
 		a_dec(&rw->_rw_waiters);
 		if (r && r != EINTR) return r;
 	}

+ 3 - 2
src/thread/sem_timedwait.c

@@ -19,8 +19,9 @@ int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict at)
 		int r;
 		a_inc(sem->__val+1);
 		a_cas(sem->__val, 0, -1);
-		r = __timedwait(sem->__val, -1, CLOCK_REALTIME, at, cleanup, sem->__val+1, sem->__val[2]);
-		a_dec(sem->__val+1);
+		pthread_cleanup_push(cleanup, sem->__val+1);
+		r = __timedwait_cp(sem->__val, -1, CLOCK_REALTIME, at, sem->__val[2]);
+		pthread_cleanup_pop(1);
 		if (r && r != EINTR) {
 			errno = r;
 			return -1;