diff options
author | davidxu <davidxu@FreeBSD.org> | 2005-04-02 01:20:00 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2005-04-02 01:20:00 +0000 |
commit | f066519e91e2290cb79ef12fe7c958ee462cda6c (patch) | |
tree | 6aaef5f553a6539306bd6f5679d039ed3c2abcce /lib/libthr/thread/thr_exit.c | |
parent | 3cc412b7837a105c757df856c422eb5f497bad67 (diff) | |
download | FreeBSD-src-f066519e91e2290cb79ef12fe7c958ee462cda6c.zip FreeBSD-src-f066519e91e2290cb79ef12fe7c958ee462cda6c.tar.gz |
Import my recent 1:1 threading working. some features improved includes:
1. fast simple type mutex.
2. __thread tls works.
3. asynchronous cancellation works ( using signal ).
4. thread synchronization is fully based on umtx, mainly, condition
variable and other synchronization objects were rewritten by using
umtx directly. those objects can be shared between processes via
shared memory, it has to change ABI which does not happen yet.
5. default stack size is increased to 1M on 32 bits platform, 2M for
64 bits platform.
As the result, some mysql super-smack benchmarks show performance is
improved massivly.
Okayed by: jeff, mtm, rwatson, scottl
Diffstat (limited to 'lib/libthr/thread/thr_exit.c')
-rw-r--r-- | lib/libthr/thread/thr_exit.c | 154 |
1 files changed, 36 insertions, 118 deletions
diff --git a/lib/libthr/thread/thr_exit.c b/lib/libthr/thread/thr_exit.c index f74b5e1..554646b 100644 --- a/lib/libthr/thread/thr_exit.c +++ b/lib/libthr/thread/thr_exit.c @@ -31,39 +31,28 @@ * * $FreeBSD$ */ + #include <errno.h> -#include <unistd.h> -#include <fcntl.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <pthread.h> + #include "thr_private.h" -__weak_reference(_pthread_exit, pthread_exit); +void _pthread_exit(void *status); -static void deadlist_free_threads(); +__weak_reference(_pthread_exit, pthread_exit); void -_thread_exit(char *fname, int lineno, char *string) +_thread_exit(char *fname, int lineno, char *msg) { - char s[256]; - /* Prepare an error message string: */ - snprintf(s, sizeof(s), + /* Write an error message to the standard error file descriptor: */ + _thread_printf(2, "Fatal error '%s' at line %d in file %s (errno = %d)\n", - string, lineno, fname, errno); - - /* Write the string to the standard error file descriptor: */ - __sys_write(2, s, strlen(s)); + msg, lineno, fname, errno); - /* Force this process to exit: */ - /* XXX - Do we want abort to be conditional on _PTHREADS_INVARIANTS? */ -#if defined(_PTHREADS_INVARIANTS) abort(); -#else - __sys_exit(1); -#endif } /* @@ -72,8 +61,10 @@ _thread_exit(char *fname, int lineno, char *string) * abnormal thread termination can be found. */ void -_thread_exit_cleanup(void) +_thr_exit_cleanup(void) { + struct pthread *curthread = _get_curthread(); + /* * POSIX states that cancellation/termination of a thread should * not release any visible resources (such as mutexes) and that @@ -93,27 +84,24 @@ _thread_exit_cleanup(void) void _pthread_exit(void *status) { - struct pthread *pthread; - int exitNow = 0; - - /* - * This thread will no longer handle any signals. - */ - _thread_sigblock(); + struct pthread *curthread = _get_curthread(); /* Check if this thread is already in the process of exiting: */ - if (curthread->exiting) { + if ((curthread->cancelflags & THR_CANCEL_EXITING) != 0) { char msg[128]; - snprintf(msg, sizeof(msg), "Thread %p has called pthread_exit() from a destructor. POSIX 1003.1 1996 s16.2.5.2 does not allow this!",curthread); + snprintf(msg, sizeof(msg), "Thread %p has called " + "pthread_exit() from a destructor. POSIX 1003.1 " + "1996 s16.2.5.2 does not allow this!", curthread); PANIC(msg); } - /* Flag this thread as exiting: */ - curthread->exiting = 1; + /* Flag this thread as exiting. */ + atomic_set_int(&curthread->cancelflags, THR_CANCEL_EXITING); + + _thr_exit_cleanup(); /* Save the return value: */ curthread->ret = status; - while (curthread->cleanup != NULL) { pthread_cleanup_pop(1); } @@ -126,93 +114,23 @@ _pthread_exit(void *status) _thread_cleanupspecific(); } - /* - * Remove read-write lock list. It is allocated as-needed. - * Therefore, it must be checked for validity before freeing. - */ - if (curthread->rwlockList != NULL) - free(curthread->rwlockList); - - /* Lock the dead list first to maintain correct lock order */ - DEAD_LIST_LOCK; - THREAD_LIST_LOCK; - - /* Check if there is a thread joining this one: */ - if (curthread->joiner != NULL) { - pthread = curthread->joiner; - curthread->joiner = NULL; - - /* Set the return value for the joining thread: */ - pthread->join_status.ret = curthread->ret; - pthread->join_status.error = 0; - pthread->join_status.thread = NULL; - - /* Make the joining thread runnable: */ - PTHREAD_WAKE(pthread); - - curthread->attr.flags |= PTHREAD_DETACHED; - } - - /* - * Free any memory allocated for dead threads. - * Add this thread to the list of dead threads, and - * also remove it from the active threads list. - */ - deadlist_free_threads(); - TAILQ_INSERT_HEAD(&_dead_list, curthread, dle); - TAILQ_REMOVE(&_thread_list, curthread, tle); - - /* If we're the last thread, call it quits */ - if (TAILQ_EMPTY(&_thread_list)) - exitNow = 1; - - THREAD_LIST_UNLOCK; - DEAD_LIST_UNLOCK; - - if (exitNow) + if (!_thr_isthreaded()) exit(0); - /* - * This function will not return unless we are the last - * thread, which we can't be because we've already checked - * for that. - */ - thr_exit((long *)&curthread->isdead); - - /* This point should not be reached. */ - PANIC("Dead thread has resumed"); -} - -/* - * Note: this function must be called with the dead thread list - * locked. - */ -static void -deadlist_free_threads() -{ - struct pthread *ptd, *ptdTemp; - - TAILQ_FOREACH_SAFE(ptd, &_dead_list, dle, ptdTemp) { - /* Don't destroy the initial thread or non-detached threads. */ - if (ptd == _thread_initial || - (ptd->attr.flags & PTHREAD_DETACHED) == 0 || - !ptd->isdead) - continue; - TAILQ_REMOVE(&_dead_list, ptd, dle); - deadlist_free_onethread(ptd); - } -} - -void -deadlist_free_onethread(struct pthread *ptd) -{ - - if (ptd->attr.stackaddr_attr == NULL && ptd->stack != NULL) { - STACK_LOCK; - _thread_stack_free(ptd->stack, ptd->attr.stacksize_attr, - ptd->attr.guardsize_attr); - STACK_UNLOCK; + THREAD_LIST_LOCK(curthread); + _thread_active_threads--; + if (_thread_active_threads == 0) { + THREAD_LIST_UNLOCK(curthread); + exit(0); + /* Never reach! */ } - _retire_thread(ptd->arch_id); - free(ptd); + if (curthread->tlflags & TLFLAGS_DETACHED) + THR_GCLIST_ADD(curthread); + curthread->state = PS_DEAD; + THREAD_LIST_UNLOCK(curthread); + if (curthread->joiner) + _thr_umtx_wake(&curthread->state, INT_MAX); + thr_exit(&curthread->terminated); + PANIC("thr_exit() returned"); + /* Never reach! */ } |