thr_exit.c revision 174806
166458Sdfr/* 266458Sdfr * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> 396912Smarcel * All rights reserved. 496912Smarcel * 566458Sdfr * Redistribution and use in source and binary forms, with or without 666458Sdfr * modification, are permitted provided that the following conditions 766458Sdfr * are met: 866458Sdfr * 1. Redistributions of source code must retain the above copyright 966458Sdfr * notice, this list of conditions and the following disclaimer. 1066458Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1166458Sdfr * notice, this list of conditions and the following disclaimer in the 1266458Sdfr * documentation and/or other materials provided with the distribution. 1366458Sdfr * 3. Neither the name of the author nor the names of any co-contributors 1466458Sdfr * may be used to endorse or promote products derived from this software 1566458Sdfr * without specific prior written permission. 1666458Sdfr * 1766458Sdfr * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 1866458Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1966458Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2066458Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2166458Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2266458Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2366458Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2466458Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2566458Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2666458Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2766458Sdfr * SUCH DAMAGE. 2866458Sdfr * 2966458Sdfr * $FreeBSD: head/lib/libthr/thread/thr_exit.c 174806 2007-12-20 04:40:12Z davidxu $ 3066458Sdfr */ 3166458Sdfr 3266458Sdfr#include <errno.h> 3366458Sdfr#include <stdio.h> 3466458Sdfr#include <stdlib.h> 3566458Sdfr#include <pthread.h> 3666458Sdfr 3766458Sdfr#include "thr_private.h" 3866458Sdfr 3966458Sdfrvoid _pthread_exit(void *status); 4066458Sdfr 4166458Sdfr__weak_reference(_pthread_exit, pthread_exit); 4266458Sdfr 4366458Sdfrvoid 4466458Sdfr_thread_exit(const char *fname, int lineno, const char *msg) 4566458Sdfr{ 4666458Sdfr 4766458Sdfr /* Write an error message to the standard error file descriptor: */ 4896912Smarcel _thread_printf(2, 4966458Sdfr "Fatal error '%s' at line %d in file %s (errno = %d)\n", 5066458Sdfr msg, lineno, fname, errno); 5166458Sdfr 5266458Sdfr abort(); 5366458Sdfr} 5466458Sdfr 5566458Sdfr/* 5666458Sdfr * Only called when a thread is cancelled. It may be more useful 5766633Sdfr * to call it from pthread_exit() if other ways of asynchronous or 5866458Sdfr * abnormal thread termination can be found. 5966458Sdfr */ 6066458Sdfrvoid 6166458Sdfr_thr_exit_cleanup(void) 6266458Sdfr{ 6366458Sdfr struct pthread *curthread = _get_curthread(); 6466458Sdfr 6566458Sdfr /* 6666458Sdfr * POSIX states that cancellation/termination of a thread should 6766458Sdfr * not release any visible resources (such as mutexes) and that 6866458Sdfr * it is the applications responsibility. Resources that are 6966458Sdfr * internal to the threads library, including file and fd locks, 7066458Sdfr * are not visible to the application and need to be released. 7166458Sdfr */ 7266458Sdfr /* Unlock all private mutexes: */ 7366458Sdfr _mutex_unlock_private(curthread); 7466458Sdfr 7592670Speter /* 7666458Sdfr * This still isn't quite correct because we don't account 7766458Sdfr * for held spinlocks (see libc/stdlib/malloc.c). 7866458Sdfr */ 7966458Sdfr} 8066458Sdfr 8166458Sdfrvoid 8266458Sdfr_pthread_exit(void *status) 8366458Sdfr{ 8466458Sdfr struct pthread *curthread = _get_curthread(); 8566458Sdfr 8666458Sdfr /* Check if this thread is already in the process of exiting: */ 8766458Sdfr if (curthread->cancelling) { 8866458Sdfr char msg[128]; 8966458Sdfr snprintf(msg, sizeof(msg), "Thread %p has called " 9066458Sdfr "pthread_exit() from a destructor. POSIX 1003.1 " 9166458Sdfr "1996 s16.2.5.2 does not allow this!", curthread); 9266458Sdfr PANIC(msg); 9366458Sdfr } 9466458Sdfr 9566458Sdfr /* Flag this thread as exiting. */ 9666458Sdfr curthread->cancelling = 1; 9766458Sdfr 9866458Sdfr _thr_exit_cleanup(); 9966458Sdfr 10066458Sdfr /* Save the return value: */ 10166458Sdfr curthread->ret = status; 10266458Sdfr while (curthread->cleanup != NULL) { 10366458Sdfr _pthread_cleanup_pop(1); 10466458Sdfr } 10566458Sdfr 10666458Sdfr /* Check if there is thread specific data: */ 10766458Sdfr if (curthread->specific != NULL) { 10866458Sdfr /* Run the thread-specific data destructors: */ 10966458Sdfr _thread_cleanupspecific(); 11066458Sdfr } 11166458Sdfr 11266458Sdfr if (!_thr_isthreaded()) 11366458Sdfr exit(0); 11466458Sdfr 11566458Sdfr THREAD_LIST_LOCK(curthread); 11666458Sdfr _thread_active_threads--; 11766458Sdfr if (_thread_active_threads == 0) { 11866458Sdfr THREAD_LIST_UNLOCK(curthread); 11966458Sdfr exit(0); 12066458Sdfr /* Never reach! */ 12166458Sdfr } 12266458Sdfr THR_LOCK(curthread); 12366458Sdfr curthread->state = PS_DEAD; 12496912Smarcel THR_UNLOCK(curthread); 12596912Smarcel /* 12696912Smarcel * Thread was created with initial refcount 1, we drop the 12796912Smarcel * reference count to allow it to be garbage collected. 12896912Smarcel */ 12996912Smarcel curthread->refcount--; 13096912Smarcel if (curthread->tlflags & TLFLAGS_DETACHED) 13196912Smarcel THR_GCLIST_ADD(curthread); 13296912Smarcel THREAD_LIST_UNLOCK(curthread); 13366458Sdfr if (SHOULD_REPORT_EVENT(curthread, TD_DEATH)) 13466458Sdfr _thr_report_death(curthread); 13566458Sdfr 13666458Sdfr /* 13766458Sdfr * Kernel will do wakeup at the address, so joiner thread 13866458Sdfr * will be resumed if it is sleeping at the address. 13966458Sdfr */ 14066458Sdfr thr_exit(&curthread->tid); 14166458Sdfr PANIC("thr_exit() returned"); 14266458Sdfr /* Never reach! */ 14396912Smarcel} 14496912Smarcel