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> 374a9b8501Szrj #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 46*90306d38Szrj static void exit_thread(void) __dead2; 47*90306d38Szrj 4871b3fa15SDavid Xu void 494a9b8501Szrj _thread_exitf(const char *fname, int lineno, const char *fmt, ...) 5071b3fa15SDavid Xu { 514a9b8501Szrj va_list ap; 5271b3fa15SDavid Xu 5371b3fa15SDavid Xu /* Write an error message to the standard error file descriptor: */ 544a9b8501Szrj _thread_printf(STDERR_FILENO, "Fatal error '"); 554a9b8501Szrj 564a9b8501Szrj va_start(ap, fmt); 574a9b8501Szrj _thread_vprintf(STDERR_FILENO, fmt, ap); 584a9b8501Szrj va_end(ap); 594a9b8501Szrj 604a9b8501Szrj _thread_printf(STDERR_FILENO, "' at line %d in file %s (errno = %d)\n", 614a9b8501Szrj lineno, fname, errno); 6271b3fa15SDavid Xu 6371b3fa15SDavid Xu abort(); 6471b3fa15SDavid Xu } 6571b3fa15SDavid Xu 664a9b8501Szrj void 674a9b8501Szrj _thread_exit(const char *fname, int lineno, const char *msg) 684a9b8501Szrj { 694a9b8501Szrj _thread_exitf(fname, lineno, "%s", msg); 704a9b8501Szrj } 714a9b8501Szrj 7271b3fa15SDavid Xu /* 7371b3fa15SDavid Xu * Only called when a thread is cancelled. It may be more useful 7471b3fa15SDavid Xu * to call it from pthread_exit() if other ways of asynchronous or 7571b3fa15SDavid Xu * abnormal thread termination can be found. 7671b3fa15SDavid Xu */ 7771b3fa15SDavid Xu void 7871b3fa15SDavid Xu _thr_exit_cleanup(void) 7971b3fa15SDavid Xu { 809e2ee207SJoerg Sonnenberger struct pthread *curthread = tls_get_curthread(); 8171b3fa15SDavid Xu 8271b3fa15SDavid Xu /* 8371b3fa15SDavid Xu * POSIX states that cancellation/termination of a thread should 8471b3fa15SDavid Xu * not release any visible resources (such as mutexes) and that 8571b3fa15SDavid Xu * it is the applications responsibility. Resources that are 8671b3fa15SDavid Xu * internal to the threads library, including file and fd locks, 8771b3fa15SDavid Xu * are not visible to the application and need to be released. 8871b3fa15SDavid Xu */ 8971b3fa15SDavid Xu /* Unlock all private mutexes: */ 9071b3fa15SDavid Xu _mutex_unlock_private(curthread); 9171b3fa15SDavid Xu 9271b3fa15SDavid Xu /* 9371b3fa15SDavid Xu * This still isn't quite correct because we don't account 9471b3fa15SDavid Xu * for held spinlocks (see libc/stdlib/malloc.c). 9571b3fa15SDavid Xu */ 9671b3fa15SDavid Xu } 9771b3fa15SDavid Xu 9871b3fa15SDavid Xu void 9971b3fa15SDavid Xu _pthread_exit(void *status) 10071b3fa15SDavid Xu { 1019e2ee207SJoerg Sonnenberger struct pthread *curthread = tls_get_curthread(); 10271b3fa15SDavid Xu 10371b3fa15SDavid Xu /* Check if this thread is already in the process of exiting: */ 10471b3fa15SDavid Xu if ((curthread->cancelflags & THR_CANCEL_EXITING) != 0) { 1054a9b8501Szrj PANIC("Thread %p has called " 10671b3fa15SDavid Xu "pthread_exit() from a destructor. POSIX 1003.1 " 10771b3fa15SDavid Xu "1996 s16.2.5.2 does not allow this!", curthread); 10871b3fa15SDavid Xu } 10971b3fa15SDavid Xu 11071b3fa15SDavid Xu /* Flag this thread as exiting. */ 11171b3fa15SDavid Xu atomic_set_int(&curthread->cancelflags, THR_CANCEL_EXITING); 11271b3fa15SDavid Xu 11371b3fa15SDavid Xu _thr_exit_cleanup(); 11471b3fa15SDavid Xu 11571b3fa15SDavid Xu /* Save the return value: */ 11671b3fa15SDavid Xu curthread->ret = status; 11771b3fa15SDavid Xu while (curthread->cleanup != NULL) { 118557d26c7SDavid Xu _pthread_cleanup_pop(1); 11971b3fa15SDavid Xu } 120e8382b15SDavid Xu 121*90306d38Szrj exit_thread(); 122*90306d38Szrj } 123*90306d38Szrj 124*90306d38Szrj __strong_reference(_pthread_exit, pthread_exit); 125*90306d38Szrj 126*90306d38Szrj static void 127*90306d38Szrj exit_thread(void) 128*90306d38Szrj { 129*90306d38Szrj struct pthread *curthread = tls_get_curthread(); 130*90306d38Szrj 13171b3fa15SDavid Xu /* Check if there is thread specific data: */ 13271b3fa15SDavid Xu if (curthread->specific != NULL) { 13371b3fa15SDavid Xu /* Run the thread-specific data destructors: */ 13471b3fa15SDavid Xu _thread_cleanupspecific(); 13571b3fa15SDavid Xu } 13671b3fa15SDavid Xu 13771b3fa15SDavid Xu if (!_thr_isthreaded()) 13871b3fa15SDavid Xu exit(0); 13971b3fa15SDavid Xu 14071b3fa15SDavid Xu THREAD_LIST_LOCK(curthread); 14171b3fa15SDavid Xu _thread_active_threads--; 14271b3fa15SDavid Xu if (_thread_active_threads == 0) { 14371b3fa15SDavid Xu THREAD_LIST_UNLOCK(curthread); 14471b3fa15SDavid Xu exit(0); 14571b3fa15SDavid Xu /* Never reach! */ 14671b3fa15SDavid Xu } 147c9ad2203SDavid Xu THR_LOCK(curthread); 148c9ad2203SDavid Xu curthread->state = PS_DEAD; 149c9ad2203SDavid Xu THR_UNLOCK(curthread); 150c9ad2203SDavid Xu curthread->refcount--; 15171b3fa15SDavid Xu if (curthread->tlflags & TLFLAGS_DETACHED) 15271b3fa15SDavid Xu THR_GCLIST_ADD(curthread); 15371b3fa15SDavid Xu THREAD_LIST_UNLOCK(curthread); 15471b3fa15SDavid Xu if (curthread->joiner) 15571b3fa15SDavid Xu _thr_umtx_wake(&curthread->state, INT_MAX); 1563cd47da3SDavid Xu if (SHOULD_REPORT_EVENT(curthread, TD_DEATH)) 1573cd47da3SDavid Xu _thr_report_death(curthread); 158fbf2ef09SSimon Schubert /* Exit and set terminated to once we're really dead. */ 159fbf2ef09SSimon Schubert extexit(EXTEXIT_SETINT|EXTEXIT_LWP, 1, &curthread->terminated); 16071b3fa15SDavid Xu PANIC("thr_exit() returned"); 16171b3fa15SDavid Xu /* Never reach! */ 16271b3fa15SDavid Xu } 163