thr_exit.c revision 36827
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
2313546Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS 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 *
3213546Sjulian */
3313546Sjulian#include <errno.h>
3417706Sjulian#include <unistd.h>
3517706Sjulian#include <fcntl.h>
3613546Sjulian#include <string.h>
3713546Sjulian#ifdef _THREAD_SAFE
3813546Sjulian#include <pthread.h>
3913546Sjulian#include "pthread_private.h"
4013546Sjulian
4117706Sjulianvoid _exit(int status)
4217706Sjulian{
4317706Sjulian	int		flags;
4417706Sjulian	int             i;
4517706Sjulian	struct itimerval itimer;
4617706Sjulian
4717706Sjulian	/* Disable the interval timer: */
4817706Sjulian	itimer.it_interval.tv_sec  = 0;
4917706Sjulian	itimer.it_interval.tv_usec = 0;
5017706Sjulian	itimer.it_value.tv_sec     = 0;
5117706Sjulian	itimer.it_value.tv_usec    = 0;
5217706Sjulian	setitimer(ITIMER_VIRTUAL, &itimer, NULL);
5317706Sjulian
5417706Sjulian	/* Close the pthread kernel pipe: */
5517706Sjulian	_thread_sys_close(_thread_kern_pipe[0]);
5617706Sjulian	_thread_sys_close(_thread_kern_pipe[1]);
5717706Sjulian
5817706Sjulian	/*
5917706Sjulian	 * Enter a loop to set all file descriptors to blocking
6017706Sjulian	 * if they were not created as non-blocking:
6117706Sjulian	 */
6217706Sjulian	for (i = 0; i < _thread_dtablesize; i++) {
6317706Sjulian		/* Check if this file descriptor is in use: */
6417706Sjulian		if (_thread_fd_table[i] != NULL &&
6517706Sjulian			!(_thread_fd_table[i]->flags & O_NONBLOCK)) {
6617706Sjulian			/* Get the current flags: */
6717706Sjulian			flags = _thread_sys_fcntl(i, F_GETFL, NULL);
6817706Sjulian			/* Clear the nonblocking file descriptor flag: */
6917706Sjulian			_thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK);
7017706Sjulian		}
7117706Sjulian	}
7217706Sjulian
7317706Sjulian	/* Call the _exit syscall: */
7417706Sjulian	_thread_sys__exit(status);
7517706Sjulian}
7617706Sjulian
7713546Sjulianvoid
7813546Sjulian_thread_exit(char *fname, int lineno, char *string)
7913546Sjulian{
8013546Sjulian	char            s[256];
8113546Sjulian
8213546Sjulian	/* Prepare an error message string: */
8313546Sjulian	strcpy(s, "Fatal error '");
8413546Sjulian	strcat(s, string);
8513546Sjulian	strcat(s, "' at line ? ");
8613546Sjulian	strcat(s, "in file ");
8713546Sjulian	strcat(s, fname);
8813546Sjulian	strcat(s, " (errno = ?");
8913546Sjulian	strcat(s, ")\n");
9013546Sjulian
9113546Sjulian	/* Write the string to the standard error file descriptor: */
9213546Sjulian	_thread_sys_write(2, s, strlen(s));
9313546Sjulian
9413546Sjulian	/* Force this process to exit: */
9513546Sjulian	_exit(1);
9613546Sjulian}
9713546Sjulian
9813546Sjulianvoid
9913546Sjulianpthread_exit(void *status)
10013546Sjulian{
10113546Sjulian	int             sig;
10213546Sjulian	long            l;
10313546Sjulian	pthread_t       pthread;
10413546Sjulian
10536827Sjb	/* Check if this thread is already in the process of exiting: */
10636827Sjb	if ((_thread_run->flags & PTHREAD_EXITING) != 0) {
10736827Sjb		char msg[128];
10836827Sjb		snprintf(msg,"Thread %p has called pthread_exit() from a destructor. POSIX 1003.1 1996 s16.2.5.2 does not allow this!",_thread_run);
10936827Sjb		PANIC(msg);
11036827Sjb	}
11136827Sjb
11236827Sjb	/* Flag this thread as exiting: */
11336827Sjb	_thread_run->flags |= PTHREAD_EXITING;
11436827Sjb
11513546Sjulian	/* Save the return value: */
11613546Sjulian	_thread_run->ret = status;
11713546Sjulian
11813546Sjulian	while (_thread_run->cleanup != NULL) {
11922315Sjulian		pthread_cleanup_pop(1);
12013546Sjulian	}
12113546Sjulian
12213546Sjulian	if (_thread_run->attr.cleanup_attr != NULL) {
12313546Sjulian		_thread_run->attr.cleanup_attr(_thread_run->attr.arg_attr);
12413546Sjulian	}
12513546Sjulian	/* Check if there is thread specific data: */
12613546Sjulian	if (_thread_run->specific_data != NULL) {
12713546Sjulian		/* Run the thread-specific data destructors: */
12813546Sjulian		_thread_cleanupspecific();
12913546Sjulian	}
13013546Sjulian	/* Check if there are any threads joined to this one: */
13113546Sjulian	while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) {
13213546Sjulian		/* Wake the joined thread and let it detach this thread: */
13322315Sjulian		PTHREAD_NEW_STATE(pthread,PS_RUNNING);
13413546Sjulian	}
13513546Sjulian
13635509Sjb	/* Lock the thread list: */
13735509Sjb	_lock_thread_list();
13835509Sjb
13913546Sjulian	/* Check if the running thread is at the head of the linked list: */
14013546Sjulian	if (_thread_link_list == _thread_run) {
14113546Sjulian		/* There is no previous thread: */
14213546Sjulian		_thread_link_list = _thread_run->nxt;
14313546Sjulian	} else {
14413546Sjulian		/* Point to the first thread in the list: */
14513546Sjulian		pthread = _thread_link_list;
14613546Sjulian
14713546Sjulian		/*
14813546Sjulian		 * Enter a loop to find the thread in the linked list before
14913546Sjulian		 * the running thread:
15013546Sjulian		 */
15113546Sjulian		while (pthread != NULL && pthread->nxt != _thread_run) {
15213546Sjulian			/* Point to the next thread: */
15313546Sjulian			pthread = pthread->nxt;
15413546Sjulian		}
15513546Sjulian
15613546Sjulian		/* Check that a previous thread was found: */
15713546Sjulian		if (pthread != NULL) {
15813546Sjulian			/*
15913546Sjulian			 * Point the previous thread to the one after the
16013546Sjulian			 * running thread:
16113546Sjulian			 */
16213546Sjulian			pthread->nxt = _thread_run->nxt;
16313546Sjulian		}
16413546Sjulian	}
16513546Sjulian
16635509Sjb	/* Unlock the thread list: */
16735509Sjb	_unlock_thread_list();
16813546Sjulian
16935509Sjb	/* Lock the dead thread list: */
17035509Sjb	_lock_dead_thread_list();
17113546Sjulian
17213546Sjulian	/*
17313546Sjulian	 * This thread will never run again. Add it to the list of dead
17413546Sjulian	 * threads:
17513546Sjulian	 */
17613546Sjulian	_thread_run->nxt = _thread_dead;
17713546Sjulian	_thread_dead = _thread_run;
17813546Sjulian
17935509Sjb	/* Unlock the dead thread list: */
18035509Sjb	_unlock_dead_thread_list();
18135509Sjb
18213546Sjulian	/*
18313546Sjulian	 * The running thread is no longer in the thread link list so it will
18413546Sjulian	 * now die:
18513546Sjulian	 */
18613546Sjulian	_thread_kern_sched_state(PS_DEAD, __FILE__, __LINE__);
18713546Sjulian
18813546Sjulian	/* This point should not be reached. */
18913546Sjulian	PANIC("Dead thread has resumed");
19013546Sjulian}
19113546Sjulian#endif
192