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