提交 feee9890 编写于 作者: R Rich Felker

overhaul pthread cancellation

this patch improves the correctness, simplicity, and size of
cancellation-related code. modulo any small errors, it should now be
completely conformant, safe, and resource-leak free.

the notion of entering and exiting cancellation-point context has been
completely eliminated and replaced with alternative syscall assembly
code for cancellable syscalls. the assembly is responsible for setting
up execution context information (stack pointer and address of the
syscall instruction) which the cancellation signal handler can use to
determine whether the interrupted code was in a cancellable state.

these changes eliminate race conditions in the previous generation of
cancellation handling code (whereby a cancellation request received
just prior to the syscall would not be processed, leaving the syscall
to block, potentially indefinitely), and remedy an issue where
non-cancellable syscalls made from signal handlers became cancellable
if the signal handler interrupted a cancellation point.

x86_64 asm is untested and may need a second try to get it right.
上级 90f09a0d
......@@ -7,17 +7,17 @@ struct __ptcb {
static inline void __pthread_register_cancel_2(struct __ptcb *__cb)
{
__asm__ __volatile__( "call __pthread_register_cancel" : : "a"(__cb) );
__asm__ __volatile__( "call __pthread_register_cancel" : : "a"(__cb) : "ecx", "edx", "memory" );
}
static inline void __pthread_unregister_cancel_2(struct __ptcb *__cb)
{
__asm__ __volatile__( "call __pthread_unregister_cancel" : : "a"(__cb) );
__asm__ __volatile__( "call __pthread_unregister_cancel" : : "a"(__cb) : "ecx", "edx", "memory" );
}
static inline void __pthread_unwind_next_2(struct __ptcb *__cb)
{
__asm__ __volatile__( "call __pthread_unwind_next" : : "a"(__cb) );
__asm__ __volatile__( "call __pthread_unwind_next" : : "a"(__cb) : "ecx", "edx", "memory" );
}
#define __pthread_register_cancel __pthread_register_cancel_2
......
......@@ -122,7 +122,9 @@ static inline long __syscall6(long __n, long __a1, long __a2, long __a3, long __
#define __SC_sendmsg 16
#define __SC_recvmsg 17
#define __socketcall(nm, a, b, c, d, e, f) syscall(SYS_socketcall, __SC_##nm, \
#define __socketcall(nm,a,b,c,d,e,f) syscall(SYS_socketcall, __SC_##nm, \
((long [6]){ (long)a, (long)b, (long)c, (long)d, (long)e, (long)f }))
#define __socketcall_cp(nm,a,b,c,d,e,f) syscall_cp(SYS_socketcall, __SC_##nm, \
((long [6]){ (long)a, (long)b, (long)c, (long)d, (long)e, (long)f }))
#define __NR_restart_syscall 0
......
......@@ -5,5 +5,5 @@ static inline struct pthread *__pthread_self()
return self;
}
#define PC_AT_SYS(c) \
(*(uint16_t *)(((ucontext_t *)(c))->uc_mcontext.__gregs[14])==0x80cd)
#define CANCEL_REG_SP 7
#define CANCEL_REG_IP 14
......@@ -60,7 +60,8 @@ static inline long __syscall6(long __n, long __a1, long __a2, long __a3, long __
return __ret;
}
#define __socketcall(nm, a, b, c, d, e, f) syscall(__NR_##nm, a, b, c, d, e, f)
#define __socketcall(nm,a,b,c,d,e,f) syscall(__NR_##nm, a, b, c, d, e, f)
#define __socketcall_cp(nm,a,b,c,d,e,f) syscall_cp(__NR_##nm, a, b, c, d, e, f)
#define __NR_read 0
#define __NR_write 1
......
......@@ -5,5 +5,5 @@ static inline struct pthread *__pthread_self()
return self;
}
#define PC_AT_SYS(c) \
(*(uint16_t *)(((ucontext_t *)(c))->uc_mcontext.__gregs[16])==0x050f)
#define CANCEL_REG_SP 15
#define CANCEL_REG_IP 16
......@@ -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);
......@@ -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);
......@@ -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);
......@@ -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);
......
......@@ -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);
......
......@@ -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
......@@ -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;
}
......@@ -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;
}
......@@ -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);
}
......@@ -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);
}
......@@ -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);
}
......@@ -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
......
......@@ -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);
}
......@@ -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);
}
......@@ -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);
}
......@@ -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);
}
......@@ -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);
}
......@@ -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);
}
......@@ -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);
}
......@@ -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);
}
......@@ -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;
}
#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);
}
......@@ -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;
......
#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;
}
#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);
#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);
}
.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
#include "pthread_impl.h"
int pthread_cancel(pthread_t t)
{
a_store(&t->cancel, 1);
return pthread_kill(t, SIGCANCEL);
}
......@@ -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;
}
......@@ -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);
}
......@@ -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;
......
......@@ -2,6 +2,5 @@
void pthread_testcancel()
{
CANCELPT_BEGIN;
CANCELPT_END;
if (libc.testcancel) libc.testcancel();
}
......@@ -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);
......
.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
......@@ -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);
}
......@@ -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);
}
......@@ -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;
}
......@@ -4,9 +4,5 @@
int pause(void)
{
int r;
CANCELPT_BEGIN;
r = syscall(SYS_pause);
CANCELPT_END;
return r;
return syscall_cp(SYS_pause);
}
......@@ -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);
......@@ -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);
......@@ -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);
}
......@@ -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);
}
......@@ -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);
}
......@@ -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);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册