thr_exit.c revision 115399
113546Sjulian/*
235509Sjb * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
313546Sjulian * All rights reserved.
413546Sjulian *
513546Sjulian * Redistribution and use in source and binary forms, with or without
613546Sjulian * modification, are permitted provided that the following conditions
713546Sjulian * are met:
813546Sjulian * 1. Redistributions of source code must retain the above copyright
913546Sjulian *    notice, this list of conditions and the following disclaimer.
1013546Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1113546Sjulian *    notice, this list of conditions and the following disclaimer in the
1213546Sjulian *    documentation and/or other materials provided with the distribution.
1313546Sjulian * 3. All advertising materials mentioning features or use of this software
1413546Sjulian *    must display the following acknowledgement:
1513546Sjulian *	This product includes software developed by John Birrell.
1613546Sjulian * 4. Neither the name of the author nor the names of any co-contributors
1713546Sjulian *    may be used to endorse or promote products derived from this software
1813546Sjulian *    without specific prior written permission.
1913546Sjulian *
2013546Sjulian * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
2113546Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2213546Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2349439Sdeischen * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2413546Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2513546Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2613546Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2713546Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2813546Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2913546Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3013546Sjulian * SUCH DAMAGE.
3113546Sjulian *
3250476Speter * $FreeBSD: head/lib/libkse/thread/thr_exit.c 115399 2003-05-30 00:21:52Z kan $
3313546Sjulian */
3413546Sjulian#include <errno.h>
3517706Sjulian#include <unistd.h>
3617706Sjulian#include <fcntl.h>
3753812Salfred#include <stdio.h>
3853812Salfred#include <stdlib.h>
3913546Sjulian#include <string.h>
4013546Sjulian#include <pthread.h>
41103388Smini#include "thr_private.h"
4213546Sjulian
43113658Sdeischenvoid	_pthread_exit(void *status);
4467097Sdeischen
4575369Sdeischen__weak_reference(_pthread_exit, pthread_exit);
4671581Sdeischen
4713546Sjulianvoid
48113658Sdeischen_thr_exit(char *fname, int lineno, char *msg)
4913546Sjulian{
5013546Sjulian
51115399Skan	/* Write an error message to the standard error file descriptor: */
52115399Skan	_thread_printf(2,
5372374Sdeischen	    "Fatal error '%s' at line %d in file %s (errno = %d)\n",
54113658Sdeischen	    msg, lineno, fname, errno);
5513546Sjulian
5648046Sjb	abort();
5713546Sjulian}
5813546Sjulian
5953812Salfred/*
6053812Salfred * Only called when a thread is cancelled.  It may be more useful
6153812Salfred * to call it from pthread_exit() if other ways of asynchronous or
6253812Salfred * abnormal thread termination can be found.
6353812Salfred */
6413546Sjulianvoid
65113658Sdeischen_thr_exit_cleanup(void)
6653812Salfred{
6771581Sdeischen	struct pthread	*curthread = _get_curthread();
6871581Sdeischen
6953812Salfred	/*
7053812Salfred	 * POSIX states that cancellation/termination of a thread should
7153812Salfred	 * not release any visible resources (such as mutexes) and that
7253812Salfred	 * it is the applications responsibility.  Resources that are
7353812Salfred	 * internal to the threads library, including file and fd locks,
7453812Salfred	 * are not visible to the application and need to be released.
7553812Salfred	 */
7653812Salfred	/* Unlock all private mutexes: */
7771581Sdeischen	_mutex_unlock_private(curthread);
7853812Salfred
7953812Salfred	/*
8053812Salfred	 * This still isn't quite correct because we don't account
8153812Salfred	 * for held spinlocks (see libc/stdlib/malloc.c).
8253812Salfred	 */
8353812Salfred}
8453812Salfred
8553812Salfredvoid
8671581Sdeischen_pthread_exit(void *status)
8713546Sjulian{
88113658Sdeischen	struct pthread *curthread = _get_curthread();
8913546Sjulian
9036827Sjb	/* Check if this thread is already in the process of exiting: */
91113658Sdeischen	if ((curthread->flags & THR_FLAGS_EXITING) != 0) {
9236827Sjb		char msg[128];
93113658Sdeischen		snprintf(msg, sizeof(msg), "Thread %p has called "
94113658Sdeischen		    "pthread_exit() from a destructor. POSIX 1003.1 "
95113658Sdeischen		    "1996 s16.2.5.2 does not allow this!", curthread);
9636827Sjb		PANIC(msg);
9736827Sjb	}
9836827Sjb
99113658Sdeischen	/*
100113658Sdeischen	 * Flag this thread as exiting.  Threads should now be prevented
101113658Sdeischen	 * from joining to this thread.
102113658Sdeischen	 */
103114187Sdeischen	THR_SCHED_LOCK(curthread, curthread);
104113658Sdeischen	curthread->flags |= THR_FLAGS_EXITING;
105114187Sdeischen	THR_SCHED_UNLOCK(curthread, curthread);
10636827Sjb
10713546Sjulian	/* Save the return value: */
10871581Sdeischen	curthread->ret = status;
10971581Sdeischen	while (curthread->cleanup != NULL) {
11022315Sjulian		pthread_cleanup_pop(1);
11113546Sjulian	}
11271581Sdeischen	if (curthread->attr.cleanup_attr != NULL) {
11371581Sdeischen		curthread->attr.cleanup_attr(curthread->attr.arg_attr);
11413546Sjulian	}
11513546Sjulian	/* Check if there is thread specific data: */
11692730Sdeischen	if (curthread->specific != NULL) {
11713546Sjulian		/* Run the thread-specific data destructors: */
11813546Sjulian		_thread_cleanupspecific();
11913546Sjulian	}
12044963Sjb
12167097Sdeischen	/* This thread will never be re-scheduled. */
122114187Sdeischen	THR_LOCK_SWITCH(curthread);
123113658Sdeischen	THR_SET_STATE(curthread, PS_DEAD);
124115080Sdeischen	_thr_sched_switch_unlocked(curthread);
125114187Sdeischen	/* Never reach! */
12668516Sdeischen
12768516Sdeischen	/* This point should not be reached. */
12868516Sdeischen	PANIC("Dead thread has resumed");
12913546Sjulian}
130