xref: /freebsd/lib/libthr/thread/thr_exit.c (revision 37a6356bbed1e94fd2b0d9d02a29508465584c19)
1bb535300SJeff Roberson /*
2bb535300SJeff Roberson  * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
3bb535300SJeff Roberson  * All rights reserved.
4bb535300SJeff Roberson  *
5bb535300SJeff Roberson  * Redistribution and use in source and binary forms, with or without
6bb535300SJeff Roberson  * modification, are permitted provided that the following conditions
7bb535300SJeff Roberson  * are met:
8bb535300SJeff Roberson  * 1. Redistributions of source code must retain the above copyright
9bb535300SJeff Roberson  *    notice, this list of conditions and the following disclaimer.
10bb535300SJeff Roberson  * 2. Redistributions in binary form must reproduce the above copyright
11bb535300SJeff Roberson  *    notice, this list of conditions and the following disclaimer in the
12bb535300SJeff Roberson  *    documentation and/or other materials provided with the distribution.
13bb535300SJeff Roberson  * 3. All advertising materials mentioning features or use of this software
14bb535300SJeff Roberson  *    must display the following acknowledgement:
15bb535300SJeff Roberson  *	This product includes software developed by John Birrell.
16bb535300SJeff Roberson  * 4. Neither the name of the author nor the names of any co-contributors
17bb535300SJeff Roberson  *    may be used to endorse or promote products derived from this software
18bb535300SJeff Roberson  *    without specific prior written permission.
19bb535300SJeff Roberson  *
20bb535300SJeff Roberson  * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21bb535300SJeff Roberson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22bb535300SJeff Roberson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23bb535300SJeff Roberson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24bb535300SJeff Roberson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25bb535300SJeff Roberson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26bb535300SJeff Roberson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27bb535300SJeff Roberson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28bb535300SJeff Roberson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29bb535300SJeff Roberson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30bb535300SJeff Roberson  * SUCH DAMAGE.
31bb535300SJeff Roberson  *
32bb535300SJeff Roberson  * $FreeBSD$
33bb535300SJeff Roberson  */
34a091d823SDavid Xu 
35bb535300SJeff Roberson #include <errno.h>
36bb535300SJeff Roberson #include <stdio.h>
37bb535300SJeff Roberson #include <stdlib.h>
38bb535300SJeff Roberson #include <pthread.h>
39a091d823SDavid Xu 
40bb535300SJeff Roberson #include "thr_private.h"
41bb535300SJeff Roberson 
42a091d823SDavid Xu void	_pthread_exit(void *status);
43a091d823SDavid Xu 
44bb535300SJeff Roberson __weak_reference(_pthread_exit, pthread_exit);
45bb535300SJeff Roberson 
46bb535300SJeff Roberson void
4737a6356bSDavid Xu _thread_exit(const char *fname, int lineno, const char *msg)
48bb535300SJeff Roberson {
49bb535300SJeff Roberson 
50a091d823SDavid Xu 	/* Write an error message to the standard error file descriptor: */
51a091d823SDavid Xu 	_thread_printf(2,
52bb535300SJeff Roberson 	    "Fatal error '%s' at line %d in file %s (errno = %d)\n",
53a091d823SDavid Xu 	    msg, lineno, fname, errno);
54bb535300SJeff Roberson 
55bb535300SJeff Roberson 	abort();
56bb535300SJeff Roberson }
57bb535300SJeff Roberson 
58bb535300SJeff Roberson /*
59bb535300SJeff Roberson  * Only called when a thread is cancelled.  It may be more useful
60bb535300SJeff Roberson  * to call it from pthread_exit() if other ways of asynchronous or
61bb535300SJeff Roberson  * abnormal thread termination can be found.
62bb535300SJeff Roberson  */
63bb535300SJeff Roberson void
64a091d823SDavid Xu _thr_exit_cleanup(void)
65bb535300SJeff Roberson {
66a091d823SDavid Xu 	struct pthread	*curthread = _get_curthread();
67a091d823SDavid Xu 
68bb535300SJeff Roberson 	/*
69bb535300SJeff Roberson 	 * POSIX states that cancellation/termination of a thread should
70bb535300SJeff Roberson 	 * not release any visible resources (such as mutexes) and that
71bb535300SJeff Roberson 	 * it is the applications responsibility.  Resources that are
72bb535300SJeff Roberson 	 * internal to the threads library, including file and fd locks,
73bb535300SJeff Roberson 	 * are not visible to the application and need to be released.
74bb535300SJeff Roberson 	 */
75bb535300SJeff Roberson 	/* Unlock all private mutexes: */
76bb535300SJeff Roberson 	_mutex_unlock_private(curthread);
77bb535300SJeff Roberson 
78bb535300SJeff Roberson 	/*
79bb535300SJeff Roberson 	 * This still isn't quite correct because we don't account
80bb535300SJeff Roberson 	 * for held spinlocks (see libc/stdlib/malloc.c).
81bb535300SJeff Roberson 	 */
82bb535300SJeff Roberson }
83bb535300SJeff Roberson 
84bb535300SJeff Roberson void
85bb535300SJeff Roberson _pthread_exit(void *status)
86bb535300SJeff Roberson {
87a091d823SDavid Xu 	struct pthread *curthread = _get_curthread();
884cd18a22SMike Makonnen 
89bb535300SJeff Roberson 	/* Check if this thread is already in the process of exiting: */
90a091d823SDavid Xu 	if ((curthread->cancelflags & THR_CANCEL_EXITING) != 0) {
91bb535300SJeff Roberson 		char msg[128];
92a091d823SDavid Xu 		snprintf(msg, sizeof(msg), "Thread %p has called "
93a091d823SDavid Xu 		    "pthread_exit() from a destructor. POSIX 1003.1 "
94a091d823SDavid Xu 		    "1996 s16.2.5.2 does not allow this!", curthread);
95bb535300SJeff Roberson 		PANIC(msg);
96bb535300SJeff Roberson 	}
97bb535300SJeff Roberson 
98a091d823SDavid Xu 	/* Flag this thread as exiting. */
99a091d823SDavid Xu 	atomic_set_int(&curthread->cancelflags, THR_CANCEL_EXITING);
100a091d823SDavid Xu 
101a091d823SDavid Xu 	_thr_exit_cleanup();
102bb535300SJeff Roberson 
103bb535300SJeff Roberson 	/* Save the return value: */
104bb535300SJeff Roberson 	curthread->ret = status;
105bb535300SJeff Roberson 	while (curthread->cleanup != NULL) {
106bb535300SJeff Roberson 		pthread_cleanup_pop(1);
107bb535300SJeff Roberson 	}
10837a6356bSDavid Xu 
109bb535300SJeff Roberson 	/* Check if there is thread specific data: */
110bb535300SJeff Roberson 	if (curthread->specific != NULL) {
111bb535300SJeff Roberson 		/* Run the thread-specific data destructors: */
112bb535300SJeff Roberson 		_thread_cleanupspecific();
113bb535300SJeff Roberson 	}
114bb535300SJeff Roberson 
115a091d823SDavid Xu 	if (!_thr_isthreaded())
1164e3f7b6eSMike Makonnen 		exit(0);
117f97591bfSMike Makonnen 
118a091d823SDavid Xu 	THREAD_LIST_LOCK(curthread);
119a091d823SDavid Xu 	_thread_active_threads--;
120a091d823SDavid Xu 	if (_thread_active_threads == 0) {
121a091d823SDavid Xu 		THREAD_LIST_UNLOCK(curthread);
122a091d823SDavid Xu 		exit(0);
123a091d823SDavid Xu 		/* Never reach! */
124bb535300SJeff Roberson 	}
125bc414752SDavid Xu 	THR_LOCK(curthread);
126bc414752SDavid Xu 	curthread->state = PS_DEAD;
127bc414752SDavid Xu 	THR_UNLOCK(curthread);
128bc414752SDavid Xu 	/*
129bc414752SDavid Xu 	 * Thread was created with initial refcount 1, we drop the
130bc414752SDavid Xu 	 * reference count to allow it to be garbage collected.
131bc414752SDavid Xu 	 */
132bc414752SDavid Xu 	curthread->refcount--;
133a091d823SDavid Xu 	if (curthread->tlflags & TLFLAGS_DETACHED)
134a091d823SDavid Xu 		THR_GCLIST_ADD(curthread);
135a091d823SDavid Xu 	THREAD_LIST_UNLOCK(curthread);
136d245d9e1SDavid Xu 	if (SHOULD_REPORT_EVENT(curthread, TD_DEATH))
137d245d9e1SDavid Xu 		_thr_report_death(curthread);
138d7f119abSDavid Xu 
139d7f119abSDavid Xu 	/*
140d7f119abSDavid Xu 	 * Kernel will do wakeup at the address, so joiner thread
141d7f119abSDavid Xu 	 * will be resumed if it is sleeping at the address.
142d7f119abSDavid Xu 	 */
143d245d9e1SDavid Xu 	thr_exit(&curthread->tid);
144a091d823SDavid Xu 	PANIC("thr_exit() returned");
145a091d823SDavid Xu 	/* Never reach! */
1461c6f6301SMike Makonnen }
147