171b3fa15SDavid Xu /* 271b3fa15SDavid Xu * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> 371b3fa15SDavid Xu * All rights reserved. 471b3fa15SDavid Xu * 571b3fa15SDavid Xu * Redistribution and use in source and binary forms, with or without 671b3fa15SDavid Xu * modification, are permitted provided that the following conditions 771b3fa15SDavid Xu * are met: 871b3fa15SDavid Xu * 1. Redistributions of source code must retain the above copyright 971b3fa15SDavid Xu * notice, this list of conditions and the following disclaimer. 1071b3fa15SDavid Xu * 2. Redistributions in binary form must reproduce the above copyright 1171b3fa15SDavid Xu * notice, this list of conditions and the following disclaimer in the 1271b3fa15SDavid Xu * documentation and/or other materials provided with the distribution. 13d3b15642Szrj * 3. Neither the name of the author nor the names of any co-contributors 1471b3fa15SDavid Xu * may be used to endorse or promote products derived from this software 1571b3fa15SDavid Xu * without specific prior written permission. 1671b3fa15SDavid Xu * 1771b3fa15SDavid Xu * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 1871b3fa15SDavid Xu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1971b3fa15SDavid Xu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2071b3fa15SDavid Xu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2171b3fa15SDavid Xu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2271b3fa15SDavid Xu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2371b3fa15SDavid Xu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2471b3fa15SDavid Xu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2571b3fa15SDavid Xu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2671b3fa15SDavid Xu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2771b3fa15SDavid Xu * SUCH DAMAGE. 2871b3fa15SDavid Xu * 2971b3fa15SDavid Xu * $FreeBSD: src/lib/libpthread/thread/thr_exit.c,v 1.39 2004/10/23 23:37:54 davidxu Exp $ 3071b3fa15SDavid Xu */ 319e2ee207SJoerg Sonnenberger 32557d26c7SDavid Xu #include "namespace.h" 339e2ee207SJoerg Sonnenberger #include <machine/tls.h> 3471b3fa15SDavid Xu #include <errno.h> 3571b3fa15SDavid Xu #include <unistd.h> 3671b3fa15SDavid Xu #include <fcntl.h> 37*4a9b8501Szrj #include <stdarg.h> 3871b3fa15SDavid Xu #include <stdio.h> 3971b3fa15SDavid Xu #include <stdlib.h> 4071b3fa15SDavid Xu #include <string.h> 4171b3fa15SDavid Xu #include <pthread.h> 42557d26c7SDavid Xu #include "un-namespace.h" 4371b3fa15SDavid Xu 44557d26c7SDavid Xu #include "thr_private.h" 4571b3fa15SDavid Xu 4671b3fa15SDavid Xu void 47*4a9b8501Szrj _thread_exitf(const char *fname, int lineno, const char *fmt, ...) 4871b3fa15SDavid Xu { 49*4a9b8501Szrj va_list ap; 5071b3fa15SDavid Xu 5171b3fa15SDavid Xu /* Write an error message to the standard error file descriptor: */ 52*4a9b8501Szrj _thread_printf(STDERR_FILENO, "Fatal error '"); 53*4a9b8501Szrj 54*4a9b8501Szrj va_start(ap, fmt); 55*4a9b8501Szrj _thread_vprintf(STDERR_FILENO, fmt, ap); 56*4a9b8501Szrj va_end(ap); 57*4a9b8501Szrj 58*4a9b8501Szrj _thread_printf(STDERR_FILENO, "' at line %d in file %s (errno = %d)\n", 59*4a9b8501Szrj lineno, fname, errno); 6071b3fa15SDavid Xu 6171b3fa15SDavid Xu abort(); 6271b3fa15SDavid Xu } 6371b3fa15SDavid Xu 64*4a9b8501Szrj void 65*4a9b8501Szrj _thread_exit(const char *fname, int lineno, const char *msg) 66*4a9b8501Szrj { 67*4a9b8501Szrj _thread_exitf(fname, lineno, "%s", msg); 68*4a9b8501Szrj } 69*4a9b8501Szrj 7071b3fa15SDavid Xu /* 7171b3fa15SDavid Xu * Only called when a thread is cancelled. It may be more useful 7271b3fa15SDavid Xu * to call it from pthread_exit() if other ways of asynchronous or 7371b3fa15SDavid Xu * abnormal thread termination can be found. 7471b3fa15SDavid Xu */ 7571b3fa15SDavid Xu void 7671b3fa15SDavid Xu _thr_exit_cleanup(void) 7771b3fa15SDavid Xu { 789e2ee207SJoerg Sonnenberger struct pthread *curthread = tls_get_curthread(); 7971b3fa15SDavid Xu 8071b3fa15SDavid Xu /* 8171b3fa15SDavid Xu * POSIX states that cancellation/termination of a thread should 8271b3fa15SDavid Xu * not release any visible resources (such as mutexes) and that 8371b3fa15SDavid Xu * it is the applications responsibility. Resources that are 8471b3fa15SDavid Xu * internal to the threads library, including file and fd locks, 8571b3fa15SDavid Xu * are not visible to the application and need to be released. 8671b3fa15SDavid Xu */ 8771b3fa15SDavid Xu /* Unlock all private mutexes: */ 8871b3fa15SDavid Xu _mutex_unlock_private(curthread); 8971b3fa15SDavid Xu 9071b3fa15SDavid Xu /* 9171b3fa15SDavid Xu * This still isn't quite correct because we don't account 9271b3fa15SDavid Xu * for held spinlocks (see libc/stdlib/malloc.c). 9371b3fa15SDavid Xu */ 9471b3fa15SDavid Xu } 9571b3fa15SDavid Xu 9671b3fa15SDavid Xu void 9771b3fa15SDavid Xu _pthread_exit(void *status) 9871b3fa15SDavid Xu { 999e2ee207SJoerg Sonnenberger struct pthread *curthread = tls_get_curthread(); 10071b3fa15SDavid Xu 10171b3fa15SDavid Xu /* Check if this thread is already in the process of exiting: */ 10271b3fa15SDavid Xu if ((curthread->cancelflags & THR_CANCEL_EXITING) != 0) { 103*4a9b8501Szrj PANIC("Thread %p has called " 10471b3fa15SDavid Xu "pthread_exit() from a destructor. POSIX 1003.1 " 10571b3fa15SDavid Xu "1996 s16.2.5.2 does not allow this!", curthread); 10671b3fa15SDavid Xu } 10771b3fa15SDavid Xu 10871b3fa15SDavid Xu /* Flag this thread as exiting. */ 10971b3fa15SDavid Xu atomic_set_int(&curthread->cancelflags, THR_CANCEL_EXITING); 11071b3fa15SDavid Xu 11171b3fa15SDavid Xu _thr_exit_cleanup(); 11271b3fa15SDavid Xu 11371b3fa15SDavid Xu /* Save the return value: */ 11471b3fa15SDavid Xu curthread->ret = status; 11571b3fa15SDavid Xu while (curthread->cleanup != NULL) { 116557d26c7SDavid Xu _pthread_cleanup_pop(1); 11771b3fa15SDavid Xu } 118e8382b15SDavid Xu 11971b3fa15SDavid Xu /* Check if there is thread specific data: */ 12071b3fa15SDavid Xu if (curthread->specific != NULL) { 12171b3fa15SDavid Xu /* Run the thread-specific data destructors: */ 12271b3fa15SDavid Xu _thread_cleanupspecific(); 12371b3fa15SDavid Xu } 12471b3fa15SDavid Xu 12571b3fa15SDavid Xu if (!_thr_isthreaded()) 12671b3fa15SDavid Xu exit(0); 12771b3fa15SDavid Xu 12871b3fa15SDavid Xu THREAD_LIST_LOCK(curthread); 12971b3fa15SDavid Xu _thread_active_threads--; 13071b3fa15SDavid Xu if (_thread_active_threads == 0) { 13171b3fa15SDavid Xu THREAD_LIST_UNLOCK(curthread); 13271b3fa15SDavid Xu exit(0); 13371b3fa15SDavid Xu /* Never reach! */ 13471b3fa15SDavid Xu } 135c9ad2203SDavid Xu THR_LOCK(curthread); 136c9ad2203SDavid Xu curthread->state = PS_DEAD; 137c9ad2203SDavid Xu THR_UNLOCK(curthread); 138c9ad2203SDavid Xu curthread->refcount--; 13971b3fa15SDavid Xu if (curthread->tlflags & TLFLAGS_DETACHED) 14071b3fa15SDavid Xu THR_GCLIST_ADD(curthread); 14171b3fa15SDavid Xu THREAD_LIST_UNLOCK(curthread); 14271b3fa15SDavid Xu if (curthread->joiner) 14371b3fa15SDavid Xu _thr_umtx_wake(&curthread->state, INT_MAX); 1443cd47da3SDavid Xu if (SHOULD_REPORT_EVENT(curthread, TD_DEATH)) 1453cd47da3SDavid Xu _thr_report_death(curthread); 146fbf2ef09SSimon Schubert /* Exit and set terminated to once we're really dead. */ 147fbf2ef09SSimon Schubert extexit(EXTEXIT_SETINT|EXTEXIT_LWP, 1, &curthread->terminated); 14871b3fa15SDavid Xu PANIC("thr_exit() returned"); 14971b3fa15SDavid Xu /* Never reach! */ 15071b3fa15SDavid Xu } 1515a1048c8SDavid Xu 1525a1048c8SDavid Xu __strong_reference(_pthread_exit, pthread_exit); 153