thr_exit.c revision 144518
1250003Sadrian/* 2250003Sadrian * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> 3250003Sadrian * All rights reserved. 4250003Sadrian * 5250003Sadrian * Redistribution and use in source and binary forms, with or without 6250003Sadrian * modification, are permitted provided that the following conditions 7250003Sadrian * are met: 8250003Sadrian * 1. Redistributions of source code must retain the above copyright 9250003Sadrian * notice, this list of conditions and the following disclaimer. 10250003Sadrian * 2. Redistributions in binary form must reproduce the above copyright 11250003Sadrian * notice, this list of conditions and the following disclaimer in the 12250003Sadrian * documentation and/or other materials provided with the distribution. 13250003Sadrian * 3. All advertising materials mentioning features or use of this software 14250003Sadrian * must display the following acknowledgement: 15250003Sadrian * This product includes software developed by John Birrell. 16250003Sadrian * 4. Neither the name of the author nor the names of any co-contributors 17250003Sadrian * may be used to endorse or promote products derived from this software 18250003Sadrian * without specific prior written permission. 19250003Sadrian * 20250003Sadrian * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 21250003Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22250003Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23250003Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24250003Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25250003Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26250003Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27250003Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28250003Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29250003Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30250003Sadrian * SUCH DAMAGE. 31250003Sadrian * 32250003Sadrian * $FreeBSD: head/lib/libthr/thread/thr_exit.c 144518 2005-04-02 01:20:00Z davidxu $ 33250003Sadrian */ 34250003Sadrian 35250003Sadrian#include <errno.h> 36250003Sadrian#include <stdio.h> 37250008Sadrian#include <stdlib.h> 38250008Sadrian#include <pthread.h> 39250008Sadrian 40250008Sadrian#include "thr_private.h" 41250008Sadrian 42250008Sadrianvoid _pthread_exit(void *status); 43250008Sadrian 44250008Sadrian__weak_reference(_pthread_exit, pthread_exit); 45250008Sadrian 46250008Sadrianvoid 47250008Sadrian_thread_exit(char *fname, int lineno, char *msg) 48250008Sadrian{ 49250008Sadrian 50250003Sadrian /* Write an error message to the standard error file descriptor: */ 51250003Sadrian _thread_printf(2, 52250003Sadrian "Fatal error '%s' at line %d in file %s (errno = %d)\n", 53250003Sadrian msg, lineno, fname, errno); 54250003Sadrian 55250008Sadrian abort(); 56250003Sadrian} 57250003Sadrian 58250003Sadrian/* 59250003Sadrian * Only called when a thread is cancelled. It may be more useful 60250003Sadrian * to call it from pthread_exit() if other ways of asynchronous or 61250003Sadrian * abnormal thread termination can be found. 62250003Sadrian */ 63250003Sadrianvoid 64250008Sadrian_thr_exit_cleanup(void) 65250003Sadrian{ 66250003Sadrian struct pthread *curthread = _get_curthread(); 67250003Sadrian 68250003Sadrian /* 69250003Sadrian * POSIX states that cancellation/termination of a thread should 70250003Sadrian * not release any visible resources (such as mutexes) and that 71250003Sadrian * it is the applications responsibility. Resources that are 72250003Sadrian * internal to the threads library, including file and fd locks, 73250003Sadrian * are not visible to the application and need to be released. 74250003Sadrian */ 75250003Sadrian /* Unlock all private mutexes: */ 76250003Sadrian _mutex_unlock_private(curthread); 77250003Sadrian 78250003Sadrian /* 79250003Sadrian * This still isn't quite correct because we don't account 80250003Sadrian * for held spinlocks (see libc/stdlib/malloc.c). 81250003Sadrian */ 82250008Sadrian} 83250003Sadrian 84250003Sadrianvoid 85250003Sadrian_pthread_exit(void *status) 86250003Sadrian{ 87250008Sadrian struct pthread *curthread = _get_curthread(); 88250008Sadrian 89250008Sadrian /* Check if this thread is already in the process of exiting: */ 90250003Sadrian if ((curthread->cancelflags & THR_CANCEL_EXITING) != 0) { 91250003Sadrian char msg[128]; 92250003Sadrian snprintf(msg, sizeof(msg), "Thread %p has called " 93250003Sadrian "pthread_exit() from a destructor. POSIX 1003.1 " 94250003Sadrian "1996 s16.2.5.2 does not allow this!", curthread); 95250003Sadrian PANIC(msg); 96250003Sadrian } 97250003Sadrian 98250003Sadrian /* Flag this thread as exiting. */ 99250003Sadrian atomic_set_int(&curthread->cancelflags, THR_CANCEL_EXITING); 100250003Sadrian 101250003Sadrian _thr_exit_cleanup(); 102250003Sadrian 103250003Sadrian /* Save the return value: */ 104250008Sadrian curthread->ret = status; 105250003Sadrian while (curthread->cleanup != NULL) { 106250003Sadrian pthread_cleanup_pop(1); 107250003Sadrian } 108250003Sadrian if (curthread->attr.cleanup_attr != NULL) { 109250003Sadrian curthread->attr.cleanup_attr(curthread->attr.arg_attr); 110250003Sadrian } 111250003Sadrian /* Check if there is thread specific data: */ 112250003Sadrian if (curthread->specific != NULL) { 113250003Sadrian /* Run the thread-specific data destructors: */ 114250003Sadrian _thread_cleanupspecific(); 115250003Sadrian } 116250003Sadrian 117250003Sadrian if (!_thr_isthreaded()) 118250003Sadrian exit(0); 119250003Sadrian 120250003Sadrian THREAD_LIST_LOCK(curthread); 121250003Sadrian _thread_active_threads--; 122250003Sadrian if (_thread_active_threads == 0) { 123250003Sadrian THREAD_LIST_UNLOCK(curthread); 124250003Sadrian exit(0); 125250003Sadrian /* Never reach! */ 126250003Sadrian } 127250003Sadrian if (curthread->tlflags & TLFLAGS_DETACHED) 128250003Sadrian THR_GCLIST_ADD(curthread); 129250003Sadrian curthread->state = PS_DEAD; 130250003Sadrian THREAD_LIST_UNLOCK(curthread); 131250003Sadrian if (curthread->joiner) 132250003Sadrian _thr_umtx_wake(&curthread->state, INT_MAX); 133250003Sadrian thr_exit(&curthread->terminated); 134250003Sadrian PANIC("thr_exit() returned"); 135250003Sadrian /* Never reach! */ 136250003Sadrian} 137250003Sadrian