diff options
| author | Rich Felker <dalias@aerifal.cx> | 2011-02-13 19:58:30 -0500 | 
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2011-02-13 19:58:30 -0500 | 
| commit | 1a9a2ff7b0daf99100db53440a0b18b2801566ca (patch) | |
| tree | 2dba96173c946fc846059f65e4651bc648353ff5 /src | |
| parent | 50e26f09eb13f6568113a05dbcfe94a6b1010da0 (diff) | |
| download | musl-1a9a2ff7b0daf99100db53440a0b18b2801566ca.tar.gz | |
reorganize thread exit code, make pthread_exit call cancellation handlers (pt2)
Diffstat (limited to 'src')
| -rw-r--r-- | src/thread/cancellation.c | 10 | ||||
| -rw-r--r-- | src/thread/pthread_create.c | 63 | 
2 files changed, 51 insertions, 22 deletions
| diff --git a/src/thread/cancellation.c b/src/thread/cancellation.c index e35ba824..ac1af30a 100644 --- a/src/thread/cancellation.c +++ b/src/thread/cancellation.c @@ -7,16 +7,8 @@ void __pthread_register_cancel(struct __ptcb *cb)  	self->cancelbuf = cb;  } -#define pthread_self __pthread_self -  void __pthread_unregister_cancel(struct __ptcb *cb)  { -	struct pthread *self = pthread_self(); +	struct pthread *self = __pthread_self();  	self->cancelbuf = self->cancelbuf->__next;  } - -void __pthread_unwind_next(struct __ptcb *cb) -{ -	if (cb->__next) longjmp((void *)cb->__next->__jb, 1); -	pthread_exit(PTHREAD_CANCELLED); -} diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index 6fa484c7..72d7acbc 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -1,6 +1,38 @@  #include "pthread_impl.h" -#define pthread_self __pthread_self +void __pthread_unwind_next(struct __ptcb *cb) +{ +	int i, j, not_finished; +	pthread_t self; + +	if (cb->__next) longjmp((void *)cb->__next->__jb, 1); + +	self = pthread_self(); +	if (self->cancel) self->result = PTHREAD_CANCELLED; + +	if (!a_fetch_add(&libc.threads_minus_1, -1)) +		exit(0); + +	LOCK(&self->exitlock); + +	not_finished = self->tsd_used; +	for (j=0; not_finished && j<PTHREAD_DESTRUCTOR_ITERATIONS; j++) { +		not_finished = 0; +		for (i=0; i<PTHREAD_KEYS_MAX; i++) { +			if (self->tsd[i] && libc.tsd_keys[i]) { +				void *tmp = self->tsd[i]; +				self->tsd[i] = 0; +				libc.tsd_keys[i](tmp); +				not_finished = 1; +			} +		} +	} + +	if (self->detached && self->map_base) +		__unmapself(self->map_base, self->map_size); + +	__syscall_exit(0); +}  static void docancel(struct pthread *self)  { @@ -10,13 +42,21 @@ static void docancel(struct pthread *self)  static void cancel_handler(int sig, siginfo_t *si, void *ctx)  { -	struct pthread *self = pthread_self(); +	struct pthread *self = __pthread_self();  	self->cancel = 1;  	if (self->canceldisable || (!self->cancelasync && !self->cancelpoint))  		return;  	docancel(self);  } +static void cancelpt(int x) +{ +	struct pthread *self = __pthread_self(); +	if (self->canceldisable) return; +	self->cancelpoint = x; +	if (self->cancel) docancel(self); +} +  /* "rsyscall" is a mechanism by which a thread can synchronously force all   * other threads to perform an arbitrary syscall. It is necessary to work   * around the non-conformant implementation of setuid() et al on Linux, @@ -50,7 +90,7 @@ static int rsyscall(int nr, long a, long b, long c, long d, long e, long f)  {  	int i, ret;  	sigset_t set = { 0 }; -	struct pthread *self = pthread_self(); +	struct pthread *self = __pthread_self();  	sigaddset(&set, SIGSYSCALL);  	LOCK(&rs.lock); @@ -90,14 +130,6 @@ static int rsyscall(int nr, long a, long b, long c, long d, long e, long f)  	return ret;  } -static void cancelpt(int x) -{ -	struct pthread *self = pthread_self(); -	if (self->canceldisable) return; -	self->cancelpoint = x; -	if (self->cancel) docancel(self); -} -  static void init_threads()  {  	struct sigaction sa = { .sa_flags = SA_SIGINFO | SA_RESTART }; @@ -120,8 +152,6 @@ static int start(void *p)  	return 0;  } -#undef pthread_self -  #define CLONE_MAGIC 0x7d0f00  int __clone(int (*)(void *), void *, int, void *, pid_t *, void *, pid_t *); @@ -187,3 +217,10 @@ int pthread_create(pthread_t *res, const pthread_attr_t *attr, void *(*entry)(vo  	*res = new;  	return 0;  } + +void pthread_exit(void *result) +{ +	struct pthread *self = pthread_self(); +	self->result = result; +	docancel(self); +} | 
