thr_exit.c revision 35509
1/*
2 * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by John Birrell.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 */
33#include <errno.h>
34#include <unistd.h>
35#include <fcntl.h>
36#include <string.h>
37#ifdef _THREAD_SAFE
38#include <pthread.h>
39#include "pthread_private.h"
40
41void _exit(int status)
42{
43	int		flags;
44	int             i;
45	struct itimerval itimer;
46
47	/* Disable the interval timer: */
48	itimer.it_interval.tv_sec  = 0;
49	itimer.it_interval.tv_usec = 0;
50	itimer.it_value.tv_sec     = 0;
51	itimer.it_value.tv_usec    = 0;
52	setitimer(ITIMER_VIRTUAL, &itimer, NULL);
53
54	/* Close the pthread kernel pipe: */
55	_thread_sys_close(_thread_kern_pipe[0]);
56	_thread_sys_close(_thread_kern_pipe[1]);
57
58	/*
59	 * Enter a loop to set all file descriptors to blocking
60	 * if they were not created as non-blocking:
61	 */
62	for (i = 0; i < _thread_dtablesize; i++) {
63		/* Check if this file descriptor is in use: */
64		if (_thread_fd_table[i] != NULL &&
65			!(_thread_fd_table[i]->flags & O_NONBLOCK)) {
66			/* Get the current flags: */
67			flags = _thread_sys_fcntl(i, F_GETFL, NULL);
68			/* Clear the nonblocking file descriptor flag: */
69			_thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK);
70		}
71	}
72
73	/* Call the _exit syscall: */
74	_thread_sys__exit(status);
75}
76
77void
78_thread_exit(char *fname, int lineno, char *string)
79{
80	char            s[256];
81
82	/* Prepare an error message string: */
83	strcpy(s, "Fatal error '");
84	strcat(s, string);
85	strcat(s, "' at line ? ");
86	strcat(s, "in file ");
87	strcat(s, fname);
88	strcat(s, " (errno = ?");
89	strcat(s, ")\n");
90
91	/* Write the string to the standard error file descriptor: */
92	_thread_sys_write(2, s, strlen(s));
93
94	/* Force this process to exit: */
95	_exit(1);
96}
97
98void
99pthread_exit(void *status)
100{
101	int             sig;
102	long            l;
103	pthread_t       pthread;
104
105	/* Save the return value: */
106	_thread_run->ret = status;
107
108	while (_thread_run->cleanup != NULL) {
109		pthread_cleanup_pop(1);
110	}
111
112	if (_thread_run->attr.cleanup_attr != NULL) {
113		_thread_run->attr.cleanup_attr(_thread_run->attr.arg_attr);
114	}
115	/* Check if there is thread specific data: */
116	if (_thread_run->specific_data != NULL) {
117		/* Run the thread-specific data destructors: */
118		_thread_cleanupspecific();
119	}
120	/* Check if there are any threads joined to this one: */
121	while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) {
122		/* Wake the joined thread and let it detach this thread: */
123		PTHREAD_NEW_STATE(pthread,PS_RUNNING);
124	}
125
126	/* Lock the thread list: */
127	_lock_thread_list();
128
129	/* Check if the running thread is at the head of the linked list: */
130	if (_thread_link_list == _thread_run) {
131		/* There is no previous thread: */
132		_thread_link_list = _thread_run->nxt;
133	} else {
134		/* Point to the first thread in the list: */
135		pthread = _thread_link_list;
136
137		/*
138		 * Enter a loop to find the thread in the linked list before
139		 * the running thread:
140		 */
141		while (pthread != NULL && pthread->nxt != _thread_run) {
142			/* Point to the next thread: */
143			pthread = pthread->nxt;
144		}
145
146		/* Check that a previous thread was found: */
147		if (pthread != NULL) {
148			/*
149			 * Point the previous thread to the one after the
150			 * running thread:
151			 */
152			pthread->nxt = _thread_run->nxt;
153		}
154	}
155
156	/* Unlock the thread list: */
157	_unlock_thread_list();
158
159	/* Lock the dead thread list: */
160	_lock_dead_thread_list();
161
162	/*
163	 * This thread will never run again. Add it to the list of dead
164	 * threads:
165	 */
166	_thread_run->nxt = _thread_dead;
167	_thread_dead = _thread_run;
168
169	/* Unlock the dead thread list: */
170	_unlock_dead_thread_list();
171
172	/*
173	 * The running thread is no longer in the thread link list so it will
174	 * now die:
175	 */
176	_thread_kern_sched_state(PS_DEAD, __FILE__, __LINE__);
177
178	/* This point should not be reached. */
179	PANIC("Dead thread has resumed");
180}
181#endif
182