diff options
Diffstat (limited to 'src')
45 files changed, 235 insertions, 218 deletions
| diff --git a/src/fcntl/fcntl.c b/src/fcntl/fcntl.c index ab0ebecf..2c9fb6f3 100644 --- a/src/fcntl/fcntl.c +++ b/src/fcntl/fcntl.c @@ -6,17 +6,14 @@  int fcntl(int fd, int cmd, ...)  { -	int r;  	long arg;  	va_list ap;  	va_start(ap, cmd);  	arg = va_arg(ap, long);  	va_end(ap);  	if (cmd == F_SETFL) arg |= O_LARGEFILE; -	if (cmd == F_SETLKW) CANCELPT_BEGIN; -	r = syscall(SYS_fcntl, fd, cmd, arg); -	if (cmd == F_SETLKW) CANCELPT_END; -	return r; +	if (cmd == F_SETLKW) return syscall_cp(SYS_fcntl, fd, cmd, arg); +	return syscall(SYS_fcntl, fd, cmd, arg);  }  LFS64(fcntl); diff --git a/src/fcntl/open.c b/src/fcntl/open.c index 064d298c..31d6744c 100644 --- a/src/fcntl/open.c +++ b/src/fcntl/open.c @@ -6,16 +6,12 @@  int open(const char *filename, int flags, ...)  { -	int r;  	mode_t mode;  	va_list ap;  	va_start(ap, flags);  	mode = va_arg(ap, mode_t);  	va_end(ap); -	CANCELPT_BEGIN; -	r = syscall(SYS_open, filename, flags|O_LARGEFILE, mode); -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_open, filename, flags|O_LARGEFILE, mode);  }  LFS64(open); diff --git a/src/fcntl/openat.c b/src/fcntl/openat.c index 1a2d9535..bdecb8c8 100644 --- a/src/fcntl/openat.c +++ b/src/fcntl/openat.c @@ -6,16 +6,12 @@  int openat(int fd, const char *filename, int flags, ...)  { -	int r;  	mode_t mode;  	va_list ap;  	va_start(ap, flags);  	mode = va_arg(ap, mode_t);  	va_end(ap); -	CANCELPT_BEGIN; -	r = syscall(SYS_openat, fd, filename, flags|O_LARGEFILE, mode); -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_openat, fd, filename, flags|O_LARGEFILE, mode);  }  LFS64(openat); diff --git a/src/internal/libc.h b/src/internal/libc.h index c0039e77..3f1e55e5 100644 --- a/src/internal/libc.h +++ b/src/internal/libc.h @@ -6,7 +6,7 @@  struct __libc {  	int *(*errno_location)(void); -	void (*cancelpt)(int); +	void (*testcancel)(void);  	void (*lock)(volatile int *);  	void (*lockfile)(FILE *);  	void (*fork_handler)(int); @@ -40,12 +40,6 @@ void __lock(volatile int *);  void __lockfile(FILE *);  #define LOCK(x) (libc.threads_minus_1 ? (__lock(x),1) : ((void)(x),1))  #define UNLOCK(x) (*(x)=0) -#define CANCELPT(x) (libc.cancelpt ? libc.cancelpt((x)),0 : (void)(x),0) -#define CANCELPT_BEGIN CANCELPT(1) -#define CANCELPT_TRY CANCELPT(0) -#define CANCELPT_END CANCELPT(-1) -#define CANCELPT_INHIBIT CANCELPT(2) -#define CANCELPT_RESUME CANCELPT(-2)  int __rsyscall(int, long, long, long, long, long, long); diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index a6d90e9b..304bf98d 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -24,7 +24,8 @@ struct pthread {  	unsigned long tlsdesc[4];  	pid_t tid, pid;  	int tsd_used, errno_val, *errno_ptr; -	volatile int canceldisable, cancelasync, cancelpoint, cancel; +	volatile uintptr_t cp_sp, cp_ip; +	volatile int cancel, canceldisable, cancelasync;  	unsigned char *map_base;  	size_t map_size;  	void *start_arg; @@ -85,6 +86,7 @@ void __lock(volatile int *);  void __unmapself(void *, size_t);  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);  void __wake(volatile int *, int, int); diff --git a/src/internal/syscall.h b/src/internal/syscall.h index 39efc42d..0c71eca6 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -6,5 +6,19 @@  #include <sys/syscall.h>  #define socketcall __socketcall +#define socketcall_cp __socketcall_cp + +#define __syscall_cp0(n) __syscall_cp(n,0,0,0,0,0,0) +#define __syscall_cp1(n,a) __syscall_cp(n,(long)(a),0,0,0,0,0) +#define __syscall_cp2(n,a,b) __syscall_cp(n,(long)(a),(long)(b),0,0,0,0) +#define __syscall_cp3(n,a,b,c) __syscall_cp(n,(long)(a),(long)(b),(long)(c),0,0,0) +#define __syscall_cp4(n,a,b,c,d) __syscall_cp(n,(long)(a),(long)(b),(long)(c),(long)(d),0,0) +#define __syscall_cp5(n,a,b,c,d,e) __syscall_cp(n,(long)(a),(long)(b),(long)(c),(long)(d),(long)(e),0) +#define __syscall_cp6(n,a,b,c,d,e,f) __syscall_cp(n,(long)(a),(long)(b),(long)(c),(long)(d),(long)(e),(long)(f)) + +long (__syscall_cp)(long, long, long, long, long, long, long); + +#define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__) +#define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__))  #endif diff --git a/src/ipc/msgrcv.c b/src/ipc/msgrcv.c index 13c282ee..ed4a448a 100644 --- a/src/ipc/msgrcv.c +++ b/src/ipc/msgrcv.c @@ -5,13 +5,9 @@  ssize_t msgrcv(int q, void *m, size_t len, long type, int flag)  { -	ssize_t r; -	CANCELPT_BEGIN;  #ifdef SYS_msgrcv -	r = syscall(SYS_msgrcv, q, m, len, type, flag); +	return syscall_cp(SYS_msgrcv, q, m, len, type, flag);  #else -	r = syscall(SYS_ipc, IPCOP_msgrcv, q, len, flag, ((long[]){ (long)m, type })); +	return syscall_cp(SYS_ipc, IPCOP_msgrcv, q, len, flag, ((long[]){ (long)m, type }));  #endif -	CANCELPT_END; -	return r;  } diff --git a/src/ipc/msgsnd.c b/src/ipc/msgsnd.c index 1e0b2fa5..23f4a4cb 100644 --- a/src/ipc/msgsnd.c +++ b/src/ipc/msgsnd.c @@ -5,13 +5,9 @@  int msgsnd(int q, const void *m, size_t len, int flag)  { -	ssize_t r; -	CANCELPT_BEGIN;  #ifdef SYS_msgsnd -	r = syscall(SYS_msgsnd, q, m, len, flag); +	return syscall_cp(SYS_msgsnd, q, m, len, flag);  #else -	r = syscall(SYS_ipc, IPCOP_msgsnd, q, len, flag, m); +	return syscall_cp(SYS_ipc, IPCOP_msgsnd, q, len, flag, m);  #endif -	CANCELPT_END; -	return r;  } diff --git a/src/network/accept.c b/src/network/accept.c index 46adff5c..f6b75ba4 100644 --- a/src/network/accept.c +++ b/src/network/accept.c @@ -4,9 +4,5 @@  int accept(int fd, struct sockaddr *addr, socklen_t *len)  { -	int ret; -	CANCELPT_BEGIN; -	ret = socketcall(accept, fd, addr, len, 0, 0, 0); -	CANCELPT_END; -	return ret; +	return socketcall_cp(accept, fd, addr, len, 0, 0, 0);  } diff --git a/src/network/connect.c b/src/network/connect.c index 29bffbcb..57f01a1e 100644 --- a/src/network/connect.c +++ b/src/network/connect.c @@ -4,9 +4,5 @@  int connect(int fd, const struct sockaddr *addr, socklen_t len)  { -	int ret; -	CANCELPT_BEGIN; -	ret = socketcall(connect, fd, addr, len, 0, 0, 0); -	CANCELPT_END; -	return ret; +	return socketcall_cp(connect, fd, addr, len, 0, 0, 0);  } diff --git a/src/network/recvfrom.c b/src/network/recvfrom.c index d5222932..035a15f8 100644 --- a/src/network/recvfrom.c +++ b/src/network/recvfrom.c @@ -4,9 +4,5 @@  ssize_t recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *alen)  { -	ssize_t r; -	CANCELPT_BEGIN; -	r = socketcall(recvfrom, fd, buf, len, flags, addr, alen); -	CANCELPT_END; -	return r; +	return socketcall_cp(recvfrom, fd, buf, len, flags, addr, alen);  } diff --git a/src/network/recvmsg.c b/src/network/recvmsg.c index 65094fc8..4f526659 100644 --- a/src/network/recvmsg.c +++ b/src/network/recvmsg.c @@ -14,9 +14,7 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags)  		msg = &h;  	}  #endif -	CANCELPT_BEGIN; -	r = socketcall(recvmsg, fd, msg, flags, 0, 0, 0); -	CANCELPT_END; +	r = socketcall_cp(recvmsg, fd, msg, flags, 0, 0, 0);  #if LONG_MAX > INT_MAX  	if (orig) *orig = h;  #endif diff --git a/src/network/sendmsg.c b/src/network/sendmsg.c index 047c0eff..164c28d7 100644 --- a/src/network/sendmsg.c +++ b/src/network/sendmsg.c @@ -5,7 +5,6 @@  ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)  { -	ssize_t r;  #if LONG_MAX > INT_MAX  	struct msghdr h;  	if (msg) { @@ -14,8 +13,5 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)  		msg = &h;  	}  #endif -	CANCELPT_BEGIN; -	r = socketcall(sendmsg, fd, msg, flags, 0, 0, 0); -	CANCELPT_END; -	return r; +	return socketcall_cp(sendmsg, fd, msg, flags, 0, 0, 0);  } diff --git a/src/network/sendto.c b/src/network/sendto.c index 1cfc621d..899eecff 100644 --- a/src/network/sendto.c +++ b/src/network/sendto.c @@ -4,9 +4,5 @@  ssize_t sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t alen)  { -	ssize_t r; -	CANCELPT_BEGIN; -	r = socketcall(sendto, fd, buf, len, flags, addr, alen); -	CANCELPT_END; -	return r; +	return socketcall_cp(sendto, fd, buf, len, flags, addr, alen);  } diff --git a/src/process/waitid.c b/src/process/waitid.c index 4fa7c024..c67feac3 100644 --- a/src/process/waitid.c +++ b/src/process/waitid.c @@ -4,10 +4,5 @@  int waitid(idtype_t type, id_t id, siginfo_t *info, int options)  { -	int r; -	CANCELPT_BEGIN; -	r = syscall(SYS_waitid, type, id, info, options, 0); -	if (r<0) CANCELPT_TRY; -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_waitid, type, id, info, options, 0);  } diff --git a/src/process/waitpid.c b/src/process/waitpid.c index 5e0320f7..f75e31ef 100644 --- a/src/process/waitpid.c +++ b/src/process/waitpid.c @@ -4,10 +4,5 @@  pid_t waitpid(pid_t pid, int *status, int options)  { -	int r; -	CANCELPT_BEGIN; -	r = syscall(SYS_wait4, pid, status, options, 0); -	if (r<0) CANCELPT_TRY; -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_wait4, pid, status, options, 0);  } diff --git a/src/select/poll.c b/src/select/poll.c index caceebaf..f1e73e82 100644 --- a/src/select/poll.c +++ b/src/select/poll.c @@ -4,9 +4,5 @@  int poll(struct pollfd *fds, nfds_t n, int timeout)  { -	int r; -	CANCELPT_BEGIN; -	r = syscall(SYS_poll, fds, n, timeout); -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_poll, fds, n, timeout);  } diff --git a/src/select/pselect.c b/src/select/pselect.c index 155a6eb0..f28887ff 100644 --- a/src/select/pselect.c +++ b/src/select/pselect.c @@ -4,13 +4,8 @@  int pselect(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, const struct timespec *ts, const sigset_t *mask)  { -	int r;  	long data[2] = { (long)mask, 8 };  	struct timespec ts_tmp;  	if (ts) ts_tmp = *ts; -	CANCELPT_BEGIN; -	r = syscall(SYS_pselect6, n, rfds, wfds, efds, ts ? &ts_tmp : 0, data); -	CANCELPT_TRY; -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_pselect6, n, rfds, wfds, efds, ts ? &ts_tmp : 0, data);  } diff --git a/src/select/select.c b/src/select/select.c index b38e7fd2..696cb288 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -4,10 +4,5 @@  int select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)  { -	int r; -	CANCELPT_BEGIN; -	r = syscall(SYS_select, n, rfds, wfds, efds, tv); -	CANCELPT_TRY; -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_select, n, rfds, wfds, efds, tv);  } diff --git a/src/signal/sigsuspend.c b/src/signal/sigsuspend.c index cec5ddce..cd3a7b59 100644 --- a/src/signal/sigsuspend.c +++ b/src/signal/sigsuspend.c @@ -4,10 +4,5 @@  int sigsuspend(const sigset_t *mask)  { -	int ret; -	CANCELPT_BEGIN; -	ret = syscall(SYS_rt_sigsuspend, mask, 8); -	if (ret<0) CANCELPT_TRY; -	CANCELPT_END; -	return ret; +	return syscall_cp(SYS_rt_sigsuspend, mask, 8);  } diff --git a/src/signal/sigtimedwait.c b/src/signal/sigtimedwait.c index 1694cbe1..7eea58ab 100644 --- a/src/signal/sigtimedwait.c +++ b/src/signal/sigtimedwait.c @@ -6,11 +6,7 @@  int sigtimedwait(const sigset_t *mask, siginfo_t *si, const struct timespec *timeout)  {  	int ret; -	CANCELPT_BEGIN; -	do { -		ret = syscall(SYS_rt_sigtimedwait, mask, si, timeout, 8); -		if (ret<0) CANCELPT_TRY; -	} while (ret<0 && errno==EINTR); -	CANCELPT_END; +	do ret = syscall_cp(SYS_rt_sigtimedwait, mask, si, timeout, 8); +	while (ret<0 && errno==EINTR);  	return ret;  } diff --git a/src/termios/tcdrain.c b/src/termios/tcdrain.c index 9ff1ecd5..6e43afb7 100644 --- a/src/termios/tcdrain.c +++ b/src/termios/tcdrain.c @@ -1,13 +1,9 @@  #include <termios.h>  #include <sys/ioctl.h>  #include "libc.h" +#include "syscall.h"  int tcdrain(int fd)  { -	int ret; -	CANCELPT_BEGIN; -	ret = ioctl(fd, TCSBRK, 1); -	CANCELPT_TRY; -	CANCELPT_END; -	return ret; +	return syscall_cp(SYS_ioctl, fd, TCSBRK, 1);  } diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c index 5c84e80c..b1d3af23 100644 --- a/src/thread/__timedwait.c +++ b/src/thread/__timedwait.c @@ -2,7 +2,7 @@  #include <errno.h>  #include "futex.h"  #include "syscall.h" -#include <stdio.h> +  int __timedwait(volatile int *addr, int val, clockid_t clk, const struct timespec *at, int priv)  {  	int r; diff --git a/src/thread/__timedwait_cp.c b/src/thread/__timedwait_cp.c new file mode 100644 index 00000000..c2890985 --- /dev/null +++ b/src/thread/__timedwait_cp.c @@ -0,0 +1,23 @@ +#include <time.h> +#include <errno.h> +#include "futex.h" +#include "syscall.h" + +int __timedwait_cp(volatile int *addr, int val, clockid_t clk, const struct timespec *at, int priv) +{ +	int r; +	struct timespec to; +	if (at) { +		clock_gettime(clk, &to); +		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; +	} +	if (priv) priv = 128; priv=0; +	r = -__syscall_cp(SYS_futex, (long)addr, FUTEX_WAIT | priv, val, at ? (long)&to : 0); +	if (r == ETIMEDOUT || r == EINTR) return r; +	return 0; +} diff --git a/src/thread/cancel_dummy.c b/src/thread/cancel_dummy.c new file mode 100644 index 00000000..a39117e7 --- /dev/null +++ b/src/thread/cancel_dummy.c @@ -0,0 +1,8 @@ +#include "pthread_impl.h" + +static long sccp(long nr, long u, long v, long w, long x, long y, long z) +{ +	return (__syscall)(nr, u, v, w, x, y, z); +} + +weak_alias(sccp, __syscall_cp); diff --git a/src/thread/cancel_impl.c b/src/thread/cancel_impl.c new file mode 100644 index 00000000..5ce545d7 --- /dev/null +++ b/src/thread/cancel_impl.c @@ -0,0 +1,70 @@ +#include "pthread_impl.h" + +long __syscall_cp_asm(volatile void *, long, long, long, long, long, long, long); + +long (__syscall_cp)(long nr, long u, long v, long w, long x, long y, long z) +{ +	pthread_t self; +	uintptr_t old_sp, old_ip; +	long r; + +	if (!libc.lock || (self = __pthread_self())->canceldisable) +		return __syscall(nr, u, v, w, x, y, z); + +	old_sp = self->cp_sp; +	old_ip = self->cp_ip; +	self->cp_sp = 0; +	self->cp_ip = 0; +	r = __syscall_cp_asm(&self->cp_sp, nr, u, v, w, x, y, z); +	self->cp_sp = old_sp; +	self->cp_ip = old_ip; +	if (r == -EINTR && self->cancel) pthread_exit(PTHREAD_CANCELED); +	return r; +} + +static void cancel_handler(int sig, siginfo_t *si, void *ctx) +{ +	pthread_t self = __pthread_self(); +	ucontext_t *uc = ctx; +	uintptr_t sp = ((uintptr_t *)&uc->uc_mcontext)[CANCEL_REG_SP]; +	uintptr_t ip = ((uintptr_t *)&uc->uc_mcontext)[CANCEL_REG_IP]; + +	if (!self->cancel || self->canceldisable) return; + +	if (self->cancelasync) pthread_exit(PTHREAD_CANCELED); + +	if (sp != self->cp_sp) { +		if (!sp) return; +		sigaddset(&uc->uc_sigmask, SIGCANCEL); +		__syscall(SYS_tgkill, self->pid, self->tid, SIGCANCEL); +		return; +	} + +	if (ip <= self->cp_ip) pthread_exit(PTHREAD_CANCELED); +} + +static void testcancel() +{ +	pthread_t self = __pthread_self(); +	if (self->cancel && !self->canceldisable) +		pthread_exit(PTHREAD_CANCELED); +} + +static void init_cancellation() +{ +	struct sigaction sa = { +		.sa_flags = SA_SIGINFO | SA_RESTART, +		.sa_sigaction = cancel_handler +	}; +	sigfillset(&sa.sa_mask); +	__libc_sigaction(SIGCANCEL, &sa, 0); +	libc.testcancel = testcancel; +} + +int pthread_cancel(pthread_t t) +{ +	static pthread_once_t once; +	pthread_once(&once, init_cancellation); +	a_store(&t->cancel, 1); +	return pthread_kill(t, SIGCANCEL); +} diff --git a/src/thread/i386/syscall_cp.s b/src/thread/i386/syscall_cp.s new file mode 100644 index 00000000..6f98a779 --- /dev/null +++ b/src/thread/i386/syscall_cp.s @@ -0,0 +1,36 @@ +.text +.global __syscall_cp_asm +.type   __syscall_cp_asm,%function +__syscall_cp_asm: +	pushl %ebx +	pushl %esi +	pushl %edi +	pushl %ebp +	leal 20(%esp),%ebp +	call 1f +1:	popl %eax +	movl (%ebp),%ecx +	addl $[1f-1b],%eax +	movl %eax,4(%ecx) +	movl %esp,(%ecx) +	movl 8(%ecx),%eax +	testl %eax,%eax +	jnz 2f +	movl 4(%ebp),%eax +	movl 8(%ebp),%ebx +	movl 12(%ebp),%ecx +	movl 16(%ebp),%edx +	movl 20(%ebp),%esi +	movl 24(%ebp),%edi +	movl 28(%ebp),%ebp +1:	int $128 +	popl %ebp +	popl %edi +	popl %esi +	popl %ebx +	ret +2:	xorl %eax,%eax +	movl %eax,4(%ecx) +	movl %eax,(%ecx) +	pushl $-1 +	call pthread_exit diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c deleted file mode 100644 index c497dbe6..00000000 --- a/src/thread/pthread_cancel.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "pthread_impl.h" - -int pthread_cancel(pthread_t t) -{ -	a_store(&t->cancel, 1); -	return pthread_kill(t, SIGCANCEL); -} diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c index 7a19fc55..13728282 100644 --- a/src/thread/pthread_cond_timedwait.c +++ b/src/thread/pthread_cond_timedwait.c @@ -8,22 +8,19 @@ static void relock(void *m)  int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, const struct timespec *ts)  {  	int r, e=0; -	CANCELPT_BEGIN; -	CANCELPT_END; + +	pthread_testcancel();  	pthread_cleanup_push(relock, m);  	c->_c_block = 1;  	if ((r=pthread_mutex_unlock(m))) return r; -	CANCELPT_BEGIN; -	do e = __timedwait(&c->_c_block, 1, c->_c_clock, ts, 0); +	do e = __timedwait_cp(&c->_c_block, 1, c->_c_clock, ts, 0);  	while (e == EINTR); -	CANCELPT_END;  	pthread_cleanup_pop(0);  	if ((r=pthread_mutex_lock(m))) return r; -	CANCELPT_BEGIN; -	CANCELPT_END; +	pthread_testcancel();  	return e;  } diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index a722a2d6..844d7bf9 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -19,6 +19,7 @@ weak_alias(dummy_1, __pthread_tsd_run_dtors);  void __pthread_unwind_next(struct __ptcb *cb)  {  	pthread_t self; +	int n;  	if (cb->__next) longjmp((void *)cb->__next->__jb, 1); @@ -31,8 +32,9 @@ void __pthread_unwind_next(struct __ptcb *cb)  	/* Mark this thread dead before decrementing count */  	self->dead = 1; -	if (!a_fetch_add(&libc.threads_minus_1, -1)) -		exit(0); +	do n = libc.threads_minus_1; +	while (n && a_cas(&libc.threads_minus_1, n, n-1)!=n); +	if (!n) exit(0);  	if (self->detached && self->map_base) {  		__syscall(SYS_rt_sigprocmask, SIG_BLOCK, (long)(uint64_t[1]){-1},0,8); @@ -42,43 +44,16 @@ void __pthread_unwind_next(struct __ptcb *cb)  	__syscall(SYS_exit, 0);  } -static void docancel(struct pthread *self) -{ -	struct __ptcb cb = { .__next = self->cancelbuf }; -	self->canceldisable = 1; -	self->cancelasync = 0; -	__pthread_unwind_next(&cb); -} - -static void cancel_handler(int sig, siginfo_t *si, void *ctx) -{ -	struct pthread *self = __pthread_self(); -	if (self->cancel && !self->canceldisable && -	    (self->cancelasync || (self->cancelpoint==1 && PC_AT_SYS(ctx)))) -		docancel(self); -} - -static void cancelpt(int x) -{ -	struct pthread *self = __pthread_self(); -	if ((self->cancelpoint+=x)==1 && self->cancel -		&& x<2U && !self->canceldisable) docancel(self); -} -  static void init_threads()  { -	struct sigaction sa = { .sa_flags = SA_SIGINFO | SA_RESTART }; +	sigset_t set;  	libc.lock = __lock;  	libc.lockfile = __lockfile; -	libc.cancelpt = cancelpt; - -	sigemptyset(&sa.sa_mask); -	sa.sa_sigaction = cancel_handler; -	__libc_sigaction(SIGCANCEL, &sa, 0); -	sigaddset(&sa.sa_mask, SIGSYSCALL); -	sigaddset(&sa.sa_mask, SIGCANCEL); -	__libc_sigprocmask(SIG_UNBLOCK, &sa.sa_mask, 0); +	sigemptyset(&set); +	sigaddset(&set, SIGSYSCALL); +	sigaddset(&set, SIGCANCEL); +	__libc_sigprocmask(SIG_UNBLOCK, &set, 0);  }  static int start(void *p) @@ -159,6 +134,9 @@ int pthread_create(pthread_t *res, const pthread_attr_t *attr, void *(*entry)(vo  void pthread_exit(void *result)  {  	struct pthread *self = pthread_self(); +	struct __ptcb cb = { .__next = self->cancelbuf };  	self->result = result; -	docancel(self); +	self->canceldisable = 1; +	self->cancelasync = 0; +	__pthread_unwind_next(&cb);  } diff --git a/src/thread/pthread_join.c b/src/thread/pthread_join.c index 5210ed48..ba7bb7d5 100644 --- a/src/thread/pthread_join.c +++ b/src/thread/pthread_join.c @@ -3,9 +3,7 @@  int pthread_join(pthread_t t, void **res)  {  	int tmp = t->tid; -	CANCELPT_BEGIN; -	if (tmp) __wait(&t->tid, 0, tmp, 1); -	CANCELPT_END; +	if (tmp) __timedwait_cp(&t->tid, tmp, 0, 0, 1);  	if (res) *res = t->result;  	if (t->map_base) munmap(t->map_base, t->map_size);  	return 0; diff --git a/src/thread/pthread_testcancel.c b/src/thread/pthread_testcancel.c index 774b7068..c6b250b2 100644 --- a/src/thread/pthread_testcancel.c +++ b/src/thread/pthread_testcancel.c @@ -2,6 +2,5 @@  void pthread_testcancel()  { -	CANCELPT_BEGIN; -	CANCELPT_END; +	if (libc.testcancel) libc.testcancel();  } diff --git a/src/thread/sem_timedwait.c b/src/thread/sem_timedwait.c index 4f45c172..db05b417 100644 --- a/src/thread/sem_timedwait.c +++ b/src/thread/sem_timedwait.c @@ -21,19 +21,16 @@ int sem_timedwait(sem_t *sem, const struct timespec *at)  	a_inc(sem->__val+1);  	pthread_cleanup_push(cleanup, sem->__val+1) -	CANCELPT_BEGIN;  	for (;;) {  		r = 0;  		if (!sem_trywait(sem)) break; -		r = __timedwait(sem->__val, 0, CLOCK_REALTIME, at, 0); +		r = __timedwait_cp(sem->__val, 0, CLOCK_REALTIME, at, 0);  		if (r) {  			errno = r;  			r = -1;  			break;  		} -		CANCELPT_TRY;  	} -	CANCELPT_END;  	pthread_cleanup_pop(1); diff --git a/src/thread/syscall_cp.c b/src/thread/syscall_cp.c new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/thread/syscall_cp.c diff --git a/src/thread/x86_64/syscall_cp.s b/src/thread/x86_64/syscall_cp.s new file mode 100644 index 00000000..1894ce19 --- /dev/null +++ b/src/thread/x86_64/syscall_cp.s @@ -0,0 +1,24 @@ +.text +.global __syscall_cp_asm +.type   __syscall_cp_asm,%function +__syscall_cp_asm: +	lea 1f(%rip),%rax +	mov %rax,8(%rdi) +	mov %rsp,(%rdi) +	mov 16(%rdi),%eax +	test %eax,%eax +	jnz 2f +	mov %rsi,%rax +	mov %rdx,%rdi +	mov %rcx,%rsi +	mov %r8,%rdx +	mov %r9,%r10 +	mov 8(%rsp),%r8 +	mov 16(%rsp),%r9 +1:	syscall +	ret +2:	xor %edi,%edi +	mov %rdi,8(%r10) +	mov %rdi,(%r10) +	dec %rdi +	jmp pthread_exit diff --git a/src/time/clock_nanosleep.c b/src/time/clock_nanosleep.c index 4667725b..ec87b9e3 100644 --- a/src/time/clock_nanosleep.c +++ b/src/time/clock_nanosleep.c @@ -4,9 +4,5 @@  int clock_nanosleep(clockid_t clk, int flags, const struct timespec *req, struct timespec *rem)  { -	int ret; -	CANCELPT_BEGIN; -	ret = -__syscall(SYS_clock_nanosleep, clk, flags, req, rem); -	CANCELPT_END; -	return ret; +	return -__syscall_cp(SYS_clock_nanosleep, clk, flags, req, rem);  } diff --git a/src/time/nanosleep.c b/src/time/nanosleep.c index 0e0753f3..c8878b11 100644 --- a/src/time/nanosleep.c +++ b/src/time/nanosleep.c @@ -5,10 +5,5 @@  int nanosleep(const struct timespec *req, struct timespec *rem)  { -	int ret; -	CANCELPT_BEGIN; -	ret = syscall(SYS_nanosleep, req, rem); -	CANCELPT_TRY; -	CANCELPT_END; -	return ret; +	return syscall_cp(SYS_nanosleep, req, rem);  } diff --git a/src/unistd/close.c b/src/unistd/close.c index f52c0ef3..231f79ef 100644 --- a/src/unistd/close.c +++ b/src/unistd/close.c @@ -4,8 +4,7 @@  int close(int fd)  { -	int ret = syscall(SYS_close, fd); -	CANCELPT_BEGIN; -	CANCELPT_END; +	int ret = syscall_cp(SYS_close, fd); +	if (libc.testcancel) libc.testcancel();  	return ret;  } diff --git a/src/unistd/pause.c b/src/unistd/pause.c index 57ed25e5..f7ed17d1 100644 --- a/src/unistd/pause.c +++ b/src/unistd/pause.c @@ -4,9 +4,5 @@  int pause(void)  { -	int r; -	CANCELPT_BEGIN; -	r = syscall(SYS_pause); -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_pause);  } diff --git a/src/unistd/pread.c b/src/unistd/pread.c index 0a045013..1bf0c754 100644 --- a/src/unistd/pread.c +++ b/src/unistd/pread.c @@ -4,11 +4,7 @@  ssize_t pread(int fd, void *buf, size_t size, off_t ofs)  { -	ssize_t r; -	CANCELPT_BEGIN; -	r = syscall(SYS_pread, fd, buf, size, __SYSCALL_LL(ofs)); -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_pread, fd, buf, size, __SYSCALL_LL(ofs));  }  LFS64(pread); diff --git a/src/unistd/pwrite.c b/src/unistd/pwrite.c index f878bb63..224eacdd 100644 --- a/src/unistd/pwrite.c +++ b/src/unistd/pwrite.c @@ -4,11 +4,7 @@  ssize_t pwrite(int fd, const void *buf, size_t size, off_t ofs)  { -	ssize_t r; -	CANCELPT_BEGIN; -	r = syscall(SYS_pwrite, fd, buf, size, __SYSCALL_LL(ofs)); -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_pwrite, fd, buf, size, __SYSCALL_LL(ofs));  }  LFS64(pwrite); diff --git a/src/unistd/read.c b/src/unistd/read.c index 194b389e..eb882fcc 100644 --- a/src/unistd/read.c +++ b/src/unistd/read.c @@ -4,9 +4,5 @@  ssize_t read(int fd, void *buf, size_t count)  { -	ssize_t r; -	CANCELPT_BEGIN; -	r = syscall(SYS_read, fd, buf, count); -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_read, fd, buf, count);  } diff --git a/src/unistd/readv.c b/src/unistd/readv.c index 9b87728e..e45cb484 100644 --- a/src/unistd/readv.c +++ b/src/unistd/readv.c @@ -4,9 +4,5 @@  ssize_t readv(int fd, const struct iovec *iov, int count)  { -	ssize_t r; -	CANCELPT_BEGIN; -	r = syscall(SYS_readv, fd, iov, count); -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_readv, fd, iov, count);  } diff --git a/src/unistd/write.c b/src/unistd/write.c index a8284b32..e2f7e1f2 100644 --- a/src/unistd/write.c +++ b/src/unistd/write.c @@ -4,9 +4,5 @@  ssize_t write(int fd, const void *buf, size_t count)  { -	int r; -	CANCELPT_BEGIN; -	r = syscall(SYS_write, fd, buf, count); -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_write, fd, buf, count);  } diff --git a/src/unistd/writev.c b/src/unistd/writev.c index a45afeb7..ef300ddf 100644 --- a/src/unistd/writev.c +++ b/src/unistd/writev.c @@ -4,9 +4,5 @@  ssize_t writev(int fd, const struct iovec *iov, int count)  { -	ssize_t r; -	CANCELPT_BEGIN; -	r = syscall(SYS_writev, fd, iov, count); -	CANCELPT_END; -	return r; +	return syscall_cp(SYS_writev, fd, iov, count);  } | 
