1 /* 2 * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the author nor the names of any co-contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: src/lib/libpthread/thread/thr_exit.c,v 1.39 2004/10/23 23:37:54 davidxu Exp $ 30 */ 31 32 #include "namespace.h" 33 #include <machine/tls.h> 34 #include <errno.h> 35 #include <unistd.h> 36 #include <fcntl.h> 37 #include <stdarg.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <pthread.h> 42 #include "un-namespace.h" 43 44 #include "libc_private.h" 45 #include "thr_private.h" 46 47 static void exit_thread(void) __dead2; 48 49 void 50 _thread_exitf(const char *fname, int lineno, const char *fmt, ...) 51 { 52 va_list ap; 53 54 /* Write an error message to the standard error file descriptor: */ 55 _thread_printf(STDERR_FILENO, "Fatal error '"); 56 57 va_start(ap, fmt); 58 _thread_vprintf(STDERR_FILENO, fmt, ap); 59 va_end(ap); 60 61 _thread_printf(STDERR_FILENO, "' at line %d in file %s (errno = %d)\n", 62 lineno, fname, errno); 63 64 abort(); 65 } 66 67 void 68 _thread_exit(const char *fname, int lineno, const char *msg) 69 { 70 _thread_exitf(fname, lineno, "%s", msg); 71 } 72 73 /* 74 * Only called when a thread is cancelled. It may be more useful 75 * to call it from pthread_exit() if other ways of asynchronous or 76 * abnormal thread termination can be found. 77 */ 78 void 79 _thr_exit_cleanup(void) 80 { 81 pthread_t curthread = tls_get_curthread(); 82 83 /* 84 * POSIX states that cancellation/termination of a thread should 85 * not release any visible resources (such as mutexes) and that 86 * it is the applications responsibility. Resources that are 87 * internal to the threads library, including file and fd locks, 88 * are not visible to the application and need to be released. 89 */ 90 /* Unlock all private mutexes: */ 91 _mutex_unlock_private(curthread); 92 93 /* 94 * This still isn't quite correct because we don't account 95 * for held spinlocks (see libc/stdlib/malloc.c). 96 */ 97 } 98 99 void 100 _pthread_exit(void *status) 101 { 102 pthread_t curthread = tls_get_curthread(); 103 104 /* Check if this thread is already in the process of exiting: */ 105 if ((curthread->cancelflags & THR_CANCEL_EXITING) != 0) { 106 PANIC("Thread %p has called " 107 "pthread_exit() from a destructor. POSIX 1003.1 " 108 "1996 s16.2.5.2 does not allow this!", curthread); 109 } 110 111 /* Flag this thread as exiting. */ 112 atomic_set_int(&curthread->cancelflags, THR_CANCEL_EXITING); 113 114 _thr_exit_cleanup(); 115 116 /* Save the return value: */ 117 curthread->ret = status; 118 while (curthread->cleanup != NULL) { 119 _pthread_cleanup_pop(1); 120 } 121 /* Call TLS destructors, if any. */ 122 _thread_finalize(); 123 124 exit_thread(); 125 } 126 127 __strong_reference(_pthread_exit, pthread_exit); 128 129 static void 130 exit_thread(void) 131 { 132 pthread_t curthread = tls_get_curthread(); 133 134 /* Check if there is thread specific data: */ 135 if (curthread->specific != NULL) { 136 /* Run the thread-specific data destructors: */ 137 _thread_cleanupspecific(); 138 } 139 140 if (!_thr_isthreaded()) 141 exit(0); 142 143 THREAD_LIST_LOCK(curthread); 144 _thread_active_threads--; 145 if (_thread_active_threads == 0) { 146 THREAD_LIST_UNLOCK(curthread); 147 exit(0); 148 /* Never reach! */ 149 } 150 THR_LOCK(curthread); 151 curthread->state = PS_DEAD; 152 THR_UNLOCK(curthread); 153 curthread->refcount--; 154 if (curthread->tlflags & TLFLAGS_DETACHED) 155 THR_GCLIST_ADD(curthread); 156 THREAD_LIST_UNLOCK(curthread); 157 if (curthread->joiner) 158 _thr_umtx_wake(&curthread->state, 0); 159 if (SHOULD_REPORT_EVENT(curthread, TD_DEATH)) 160 _thr_report_death(curthread); 161 /* Exit and set terminated to once we're really dead. */ 162 extexit(EXTEXIT_SETINT|EXTEXIT_LWP, 1, &curthread->terminated); 163 PANIC("thr_exit() returned"); 164 /* Never reach! */ 165 } 166