xref: /freebsd/lib/libthr/thread/thr_init.c (revision f2c3dd08ec095110deaf22261ac49e08187db378)
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  */
34bb535300SJeff Roberson 
35bb535300SJeff Roberson /* Allocate space for global thread variables here: */
36bb535300SJeff Roberson #define GLOBAL_PTHREAD_PRIVATE
37bb535300SJeff Roberson 
38bb535300SJeff Roberson #include "namespace.h"
39bb535300SJeff Roberson #include <sys/param.h>
40bb535300SJeff Roberson #include <sys/types.h>
41bb535300SJeff Roberson #include <machine/reg.h>
42bb535300SJeff Roberson 
43bb535300SJeff Roberson #include <sys/ioctl.h>
44bb535300SJeff Roberson #include <sys/mount.h>
45bb535300SJeff Roberson #include <sys/uio.h>
46bb535300SJeff Roberson #include <sys/socket.h>
47bb535300SJeff Roberson #include <sys/event.h>
48bb535300SJeff Roberson #include <sys/stat.h>
49bb535300SJeff Roberson #include <sys/sysctl.h>
50bb535300SJeff Roberson #include <sys/time.h>
51bb535300SJeff Roberson #include <sys/ttycom.h>
52bb535300SJeff Roberson #include <sys/user.h>
53bb535300SJeff Roberson #include <sys/wait.h>
54bb535300SJeff Roberson #include <sys/mman.h>
55bb535300SJeff Roberson #include <dirent.h>
56bb535300SJeff Roberson #include <errno.h>
57bb535300SJeff Roberson #include <fcntl.h>
58bb535300SJeff Roberson #include <paths.h>
59bb535300SJeff Roberson #include <pthread.h>
60bb535300SJeff Roberson #include <signal.h>
61bb535300SJeff Roberson #include <stdio.h>
62bb535300SJeff Roberson #include <stdlib.h>
63bb535300SJeff Roberson #include <string.h>
64bb535300SJeff Roberson #include <unistd.h>
65bb535300SJeff Roberson #include "un-namespace.h"
66bb535300SJeff Roberson 
67bb535300SJeff Roberson #include "thr_private.h"
68bb535300SJeff Roberson 
697c916264SJohn Polstra /*
707c916264SJohn Polstra  * Early implementations of sigtimedwait interpreted the signal
717c916264SJohn Polstra  * set incorrectly.
727c916264SJohn Polstra  */
737c916264SJohn Polstra #define SIGTIMEDWAIT_SET_IS_INVERTED(osreldate) \
747c916264SJohn Polstra     ((500100 <= (osreldate) && (osreldate) <= 500113) || \
757c916264SJohn Polstra     (osreldate) == 501000 || (osreldate) == 501100)
767c916264SJohn Polstra 
774dee39feSMike Makonnen extern void _thread_init_hack(void);
784dee39feSMike Makonnen 
79bb535300SJeff Roberson /*
80bb535300SJeff Roberson  * All weak references used within libc should be in this table.
81bb535300SJeff Roberson  * This will is so that static libraries will work.
82bb535300SJeff Roberson  *
83bb535300SJeff Roberson  * XXXTHR - Check this list.
84bb535300SJeff Roberson  */
85bb535300SJeff Roberson static void *references[] = {
864dee39feSMike Makonnen 	&_thread_init_hack,
874dee39feSMike Makonnen 	&_thread_init,
88bb535300SJeff Roberson 	&_accept,
89bb535300SJeff Roberson 	&_bind,
90bb535300SJeff Roberson 	&_close,
91bb535300SJeff Roberson 	&_connect,
92bb535300SJeff Roberson 	&_dup,
93bb535300SJeff Roberson 	&_dup2,
94bb535300SJeff Roberson 	&_execve,
95bb535300SJeff Roberson 	&_fcntl,
96bb535300SJeff Roberson 	&_flock,
97bb535300SJeff Roberson 	&_flockfile,
98bb535300SJeff Roberson 	&_fstat,
99bb535300SJeff Roberson 	&_fstatfs,
100bb535300SJeff Roberson 	&_fsync,
101bb535300SJeff Roberson 	&_funlockfile,
102bb535300SJeff Roberson 	&_getdirentries,
103bb535300SJeff Roberson 	&_getlogin,
104bb535300SJeff Roberson 	&_getpeername,
105bb535300SJeff Roberson 	&_getsockname,
106bb535300SJeff Roberson 	&_getsockopt,
107bb535300SJeff Roberson 	&_ioctl,
108bb535300SJeff Roberson 	&_kevent,
109bb535300SJeff Roberson 	&_listen,
110bb535300SJeff Roberson 	&_nanosleep,
111bb535300SJeff Roberson 	&_open,
112bb535300SJeff Roberson 	&_pthread_getspecific,
113bb535300SJeff Roberson 	&_pthread_key_create,
114bb535300SJeff Roberson 	&_pthread_key_delete,
115bb535300SJeff Roberson 	&_pthread_mutex_destroy,
116bb535300SJeff Roberson 	&_pthread_mutex_init,
117bb535300SJeff Roberson 	&_pthread_mutex_lock,
118bb535300SJeff Roberson 	&_pthread_mutex_trylock,
119bb535300SJeff Roberson 	&_pthread_mutex_unlock,
120bb535300SJeff Roberson 	&_pthread_mutexattr_init,
121bb535300SJeff Roberson 	&_pthread_mutexattr_destroy,
122bb535300SJeff Roberson 	&_pthread_mutexattr_settype,
123bb535300SJeff Roberson 	&_pthread_once,
124bb535300SJeff Roberson 	&_pthread_setspecific,
125bb535300SJeff Roberson 	&_read,
126bb535300SJeff Roberson 	&_readv,
127bb535300SJeff Roberson 	&_recvfrom,
128bb535300SJeff Roberson 	&_recvmsg,
129bb535300SJeff Roberson 	&_select,
130bb535300SJeff Roberson 	&_sendmsg,
131bb535300SJeff Roberson 	&_sendto,
132bb535300SJeff Roberson 	&_setsockopt,
133bb535300SJeff Roberson 	&_sigaction,
134bb535300SJeff Roberson 	&_sigprocmask,
135bb535300SJeff Roberson 	&_sigsuspend,
136bb535300SJeff Roberson 	&_socket,
137bb535300SJeff Roberson 	&_socketpair,
138bb535300SJeff Roberson 	&_wait4,
139bb535300SJeff Roberson 	&_write,
140bb535300SJeff Roberson 	&_writev
141bb535300SJeff Roberson };
142bb535300SJeff Roberson 
143bb535300SJeff Roberson /*
144bb535300SJeff Roberson  * These are needed when linking statically.  All references within
145bb535300SJeff Roberson  * libgcc (and in the future libc) to these routines are weak, but
146bb535300SJeff Roberson  * if they are not (strongly) referenced by the application or other
147bb535300SJeff Roberson  * libraries, then the actual functions will not be loaded.
148bb535300SJeff Roberson  */
149bb535300SJeff Roberson static void *libgcc_references[] = {
1504dee39feSMike Makonnen 	&_thread_init_hack,
1514dee39feSMike Makonnen 	&_thread_init,
152bb535300SJeff Roberson 	&_pthread_once,
153bb535300SJeff Roberson 	&_pthread_key_create,
154bb535300SJeff Roberson 	&_pthread_key_delete,
155bb535300SJeff Roberson 	&_pthread_getspecific,
156bb535300SJeff Roberson 	&_pthread_setspecific,
157bb535300SJeff Roberson 	&_pthread_mutex_init,
158bb535300SJeff Roberson 	&_pthread_mutex_destroy,
159bb535300SJeff Roberson 	&_pthread_mutex_lock,
160bb535300SJeff Roberson 	&_pthread_mutex_trylock,
161bb535300SJeff Roberson 	&_pthread_mutex_unlock
162bb535300SJeff Roberson };
163bb535300SJeff Roberson 
164bb535300SJeff Roberson int _pthread_guard_default;
165bb535300SJeff Roberson int _pthread_page_size;
166bb535300SJeff Roberson 
167bb535300SJeff Roberson /*
168f2c3dd08SMike Makonnen  * Initialize the current thread.
169f2c3dd08SMike Makonnen  */
170f2c3dd08SMike Makonnen void
171f2c3dd08SMike Makonnen init_td_common(struct pthread *td, struct pthread_attr *attrp, int reinit)
172f2c3dd08SMike Makonnen {
173f2c3dd08SMike Makonnen 	/*
174f2c3dd08SMike Makonnen 	 * Some parts of a pthread are initialized only once.
175f2c3dd08SMike Makonnen 	 */
176f2c3dd08SMike Makonnen 	if (!reinit) {
177f2c3dd08SMike Makonnen 		memset(td, 0, sizeof(struct pthread));
178f2c3dd08SMike Makonnen 		td->cancelflags = PTHREAD_CANCEL_ENABLE |
179f2c3dd08SMike Makonnen 		    PTHREAD_CANCEL_DEFERRED;
180f2c3dd08SMike Makonnen 		memcpy(&td->attr, attrp, sizeof(struct pthread_attr));
181f2c3dd08SMike Makonnen 		td->magic = PTHREAD_MAGIC;
182f2c3dd08SMike Makonnen 		TAILQ_INIT(&td->mutexq);
183f2c3dd08SMike Makonnen 	} else {
184f2c3dd08SMike Makonnen 		memset(&td->join_status, 0, sizeof(struct join_status));
185f2c3dd08SMike Makonnen 	}
186f2c3dd08SMike Makonnen 	td->joiner = NULL;
187f2c3dd08SMike Makonnen 	td->error = 0;
188f2c3dd08SMike Makonnen 	td->flags = 0;
189f2c3dd08SMike Makonnen }
190f2c3dd08SMike Makonnen 
191f2c3dd08SMike Makonnen /*
192f2c3dd08SMike Makonnen  * Initialize the active and dead threads list. Any threads in the active
193f2c3dd08SMike Makonnen  * list will be removed and the thread td * will be marked as the
194f2c3dd08SMike Makonnen  * initial thread and inserted in the list as the only thread. Any threads
195f2c3dd08SMike Makonnen  * in the dead threads list will also be removed.
196f2c3dd08SMike Makonnen  */
197f2c3dd08SMike Makonnen void
198f2c3dd08SMike Makonnen init_tdlist(struct pthread *td, int reinit)
199f2c3dd08SMike Makonnen {
200f2c3dd08SMike Makonnen 	struct pthread *tdTemp, *tdTemp2;
201f2c3dd08SMike Makonnen 
202f2c3dd08SMike Makonnen 	_thread_initial = td;
203f2c3dd08SMike Makonnen 	td->name = strdup("_thread_initial");
204f2c3dd08SMike Makonnen 
205f2c3dd08SMike Makonnen 	/*
206f2c3dd08SMike Makonnen 	 * If this is not the first initialization, remove any entries
207f2c3dd08SMike Makonnen 	 * that may be in the list and deallocate their memory. Also
208f2c3dd08SMike Makonnen 	 * destroy any global pthread primitives (they will be recreated).
209f2c3dd08SMike Makonnen 	 */
210f2c3dd08SMike Makonnen 	if (reinit) {
211f2c3dd08SMike Makonnen 		TAILQ_FOREACH_SAFE(tdTemp, &_thread_list, tle, tdTemp2) {
212f2c3dd08SMike Makonnen 			if (tdTemp != NULL) {
213f2c3dd08SMike Makonnen 				TAILQ_REMOVE(&_thread_list, tdTemp, tle);
214f2c3dd08SMike Makonnen 				free(tdTemp);
215f2c3dd08SMike Makonnen 			}
216f2c3dd08SMike Makonnen 		}
217f2c3dd08SMike Makonnen 		TAILQ_FOREACH_SAFE(tdTemp, &_dead_list, dle, tdTemp2) {
218f2c3dd08SMike Makonnen 			if (tdTemp != NULL) {
219f2c3dd08SMike Makonnen 				TAILQ_REMOVE(&_dead_list, tdTemp, dle);
220f2c3dd08SMike Makonnen 				free(tdTemp);
221f2c3dd08SMike Makonnen 			}
222f2c3dd08SMike Makonnen 		}
223f2c3dd08SMike Makonnen 		_pthread_mutex_destroy(&dead_list_lock);
224f2c3dd08SMike Makonnen 		_pthread_cond_destroy(&_gc_cond);
225f2c3dd08SMike Makonnen 	} else {
226f2c3dd08SMike Makonnen 		TAILQ_INIT(&_thread_list);
227f2c3dd08SMike Makonnen 		TAILQ_INIT(&_dead_list);
228f2c3dd08SMike Makonnen 	}
229f2c3dd08SMike Makonnen 
230f2c3dd08SMike Makonnen 	/* Insert this thread as the first thread in the active list */
231f2c3dd08SMike Makonnen 	TAILQ_INSERT_HEAD(&_thread_list, td, tle);
232f2c3dd08SMike Makonnen 
233f2c3dd08SMike Makonnen 	/*
234f2c3dd08SMike Makonnen 	 * Initialize the active thread list lock and the
235f2c3dd08SMike Makonnen 	 * dead threads list lock & associated condition variable.
236f2c3dd08SMike Makonnen 	 */
237f2c3dd08SMike Makonnen 	memset(&thread_list_lock, 0, sizeof(spinlock_t));
238f2c3dd08SMike Makonnen 	if (_pthread_mutex_init(&dead_list_lock,NULL) != 0 ||
239f2c3dd08SMike Makonnen 	    _pthread_cond_init(&_gc_cond,NULL) != 0)
240f2c3dd08SMike Makonnen 		PANIC("Failed to initialize garbage collector primitives");
241f2c3dd08SMike Makonnen }
242f2c3dd08SMike Makonnen 
243f2c3dd08SMike Makonnen /*
244bb535300SJeff Roberson  * Threaded process initialization
245bb535300SJeff Roberson  */
246bb535300SJeff Roberson void
247bb535300SJeff Roberson _thread_init(void)
248bb535300SJeff Roberson {
249bb535300SJeff Roberson 	struct pthread	*pthread;
250bb535300SJeff Roberson 	int		fd;
251bb535300SJeff Roberson 	int             i;
252bb535300SJeff Roberson 	size_t		len;
253bb535300SJeff Roberson 	int		mib[2];
254bb535300SJeff Roberson 	sigset_t	set;
2557c916264SJohn Polstra 	int		osreldate;
25612c407a4SMike Makonnen 	int		error;
257bb535300SJeff Roberson 
258bb535300SJeff Roberson 	struct clockinfo clockinfo;
259bb535300SJeff Roberson 	struct sigaction act;
260bb535300SJeff Roberson 
261bb535300SJeff Roberson 	/* Check if this function has already been called: */
262bb535300SJeff Roberson 	if (_thread_initial)
263bb535300SJeff Roberson 		/* Only initialise the threaded application once. */
264bb535300SJeff Roberson 		return;
265bb535300SJeff Roberson 
266bb535300SJeff Roberson 	_pthread_page_size = getpagesize();
267bb535300SJeff Roberson 	_pthread_guard_default = getpagesize();
268bb535300SJeff Roberson 
269bb535300SJeff Roberson 	pthread_attr_default.guardsize_attr = _pthread_guard_default;
270bb535300SJeff Roberson 
271bb535300SJeff Roberson 
272bb535300SJeff Roberson 	/*
273bb535300SJeff Roberson 	 * Make gcc quiescent about {,libgcc_}references not being
274bb535300SJeff Roberson 	 * referenced:
275bb535300SJeff Roberson 	 */
276bb535300SJeff Roberson 	if ((references[0] == NULL) || (libgcc_references[0] == NULL))
277bb535300SJeff Roberson 		PANIC("Failed loading mandatory references in _thread_init");
278bb535300SJeff Roberson 
279bb535300SJeff Roberson 	/*
280bb535300SJeff Roberson 	 * Check for the special case of this process running as
281bb535300SJeff Roberson 	 * or in place of init as pid = 1:
282bb535300SJeff Roberson 	 */
283bb535300SJeff Roberson 	if (getpid() == 1) {
284bb535300SJeff Roberson 		/*
285bb535300SJeff Roberson 		 * Setup a new session for this process which is
286bb535300SJeff Roberson 		 * assumed to be running as root.
287bb535300SJeff Roberson 		 */
288bb535300SJeff Roberson 		if (setsid() == -1)
289bb535300SJeff Roberson 			PANIC("Can't set session ID");
290bb535300SJeff Roberson 		if (revoke(_PATH_CONSOLE) != 0)
291bb535300SJeff Roberson 			PANIC("Can't revoke console");
292bb535300SJeff Roberson 		if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0)
293bb535300SJeff Roberson 			PANIC("Can't open console");
294bb535300SJeff Roberson 		if (setlogin("root") == -1)
295bb535300SJeff Roberson 			PANIC("Can't set login to root");
296bb535300SJeff Roberson 		if (__sys_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1)
297bb535300SJeff Roberson 			PANIC("Can't set controlling terminal");
298bb535300SJeff Roberson 		if (__sys_dup2(fd, 0) == -1 ||
299bb535300SJeff Roberson 		    __sys_dup2(fd, 1) == -1 ||
300bb535300SJeff Roberson 		    __sys_dup2(fd, 2) == -1)
301bb535300SJeff Roberson 			PANIC("Can't dup2");
302bb535300SJeff Roberson 	}
303bb535300SJeff Roberson 
304bb535300SJeff Roberson 	/* Allocate memory for the thread structure of the initial thread: */
305bb535300SJeff Roberson 	if ((pthread = (pthread_t) malloc(sizeof(struct pthread))) == NULL) {
306bb535300SJeff Roberson 		/*
307bb535300SJeff Roberson 		 * Insufficient memory to initialise this application, so
308bb535300SJeff Roberson 		 * abort:
309bb535300SJeff Roberson 		 */
310bb535300SJeff Roberson 		PANIC("Cannot allocate memory for initial thread");
311bb535300SJeff Roberson 	}
3123f07b4bcSMike Makonnen 
313f2c3dd08SMike Makonnen 	init_tdlist(pthread, 0);
314f2c3dd08SMike Makonnen 	init_td_common(pthread, &pthread_attr_default, 0);
31512c407a4SMike Makonnen 	pthread->arch_id = _set_curthread(NULL, pthread, &error);
316bb535300SJeff Roberson 
317bb535300SJeff Roberson 	/* Get our thread id. */
318bb535300SJeff Roberson 	thr_self(&pthread->thr_id);
319bb535300SJeff Roberson 
320bb535300SJeff Roberson 	/* Find the stack top */
321bb535300SJeff Roberson 	mib[0] = CTL_KERN;
322bb535300SJeff Roberson 	mib[1] = KERN_USRSTACK;
323bb535300SJeff Roberson 	len = sizeof (_usrstack);
324bb535300SJeff Roberson 	if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) == -1)
325bb535300SJeff Roberson 		_usrstack = (void *)USRSTACK;
326bb535300SJeff Roberson 	/*
327bb535300SJeff Roberson 	 * Create a red zone below the main stack.  All other stacks are
328bb535300SJeff Roberson 	 * constrained to a maximum size by the paramters passed to
329bb535300SJeff Roberson 	 * mmap(), but this stack is only limited by resource limits, so
330bb535300SJeff Roberson 	 * this stack needs an explicitly mapped red zone to protect the
331bb535300SJeff Roberson 	 * thread stack that is just beyond.
332bb535300SJeff Roberson 	 */
333bb535300SJeff Roberson 	if (mmap(_usrstack - PTHREAD_STACK_INITIAL -
334bb535300SJeff Roberson 	    _pthread_guard_default, _pthread_guard_default, 0,
335bb535300SJeff Roberson 	    MAP_ANON, -1, 0) == MAP_FAILED)
336bb535300SJeff Roberson 		PANIC("Cannot allocate red zone for initial thread");
337bb535300SJeff Roberson 
338bb535300SJeff Roberson 	/* Set the main thread stack pointer. */
339bb535300SJeff Roberson 	pthread->stack = _usrstack - PTHREAD_STACK_INITIAL;
340bb535300SJeff Roberson 
341bb535300SJeff Roberson 	/* Set the stack attributes. */
342bb535300SJeff Roberson 	pthread->attr.stackaddr_attr = pthread->stack;
343bb535300SJeff Roberson 	pthread->attr.stacksize_attr = PTHREAD_STACK_INITIAL;
344bb535300SJeff Roberson 
345bb535300SJeff Roberson 	/* Setup the context for initial thread. */
346bb535300SJeff Roberson 	getcontext(&pthread->ctx);
347bb535300SJeff Roberson 	pthread->ctx.uc_stack.ss_sp = pthread->stack;
348bb535300SJeff Roberson 	pthread->ctx.uc_stack.ss_size = PTHREAD_STACK_INITIAL;
349bb535300SJeff Roberson 
350bb535300SJeff Roberson 	/* Default the priority of the initial thread: */
351bb535300SJeff Roberson 	pthread->base_priority = PTHREAD_DEFAULT_PRIORITY;
352bb535300SJeff Roberson 	pthread->active_priority = PTHREAD_DEFAULT_PRIORITY;
353bb535300SJeff Roberson 	pthread->inherited_priority = 0;
354bb535300SJeff Roberson 
355bb535300SJeff Roberson 	/* Initialise the state of the initial thread: */
356bb535300SJeff Roberson 	pthread->state = PS_RUNNING;
357bb535300SJeff Roberson 
358bb535300SJeff Roberson 	/* Enter a loop to get the existing signal status: */
359bb535300SJeff Roberson 	for (i = 1; i < NSIG; i++) {
360bb535300SJeff Roberson 		/* Check for signals which cannot be trapped. */
361bb535300SJeff Roberson 		if (i == SIGKILL || i == SIGSTOP)
362bb535300SJeff Roberson 			continue;
363bb535300SJeff Roberson 
364bb535300SJeff Roberson 		/* Get the signal handler details. */
365bb535300SJeff Roberson 		if (__sys_sigaction(i, NULL,
366bb535300SJeff Roberson 		    &_thread_sigact[i - 1]) != 0)
367bb535300SJeff Roberson 			PANIC("Cannot read signal handler info");
368bb535300SJeff Roberson 	}
369bb535300SJeff Roberson 	act.sa_sigaction = _thread_sig_wrapper;
370bb535300SJeff Roberson 	act.sa_flags = SA_SIGINFO;
371bb535300SJeff Roberson 	SIGFILLSET(act.sa_mask);
372bb535300SJeff Roberson 
373bb535300SJeff Roberson 	if (__sys_sigaction(SIGTHR, &act, NULL))
374bb535300SJeff Roberson 		PANIC("Cannot set SIGTHR handler.\n");
375bb535300SJeff Roberson 
376bb535300SJeff Roberson 	SIGEMPTYSET(set);
377bb535300SJeff Roberson 	SIGADDSET(set, SIGTHR);
378bb535300SJeff Roberson 	__sys_sigprocmask(SIG_BLOCK, &set, 0);
379bb535300SJeff Roberson 
3807c916264SJohn Polstra 	/*
3817c916264SJohn Polstra 	 * Precompute the signal set used by _thread_suspend to wait
3827c916264SJohn Polstra 	 * for SIGTHR.
3837c916264SJohn Polstra 	 */
3847c916264SJohn Polstra 	mib[0] = CTL_KERN;
3857c916264SJohn Polstra 	mib[1] = KERN_OSRELDATE;
3867c916264SJohn Polstra 	len = sizeof(osreldate);
3877c916264SJohn Polstra 	if (sysctl(mib, 2, &osreldate, &len, NULL, 0) == 0 &&
3887c916264SJohn Polstra 	    SIGTIMEDWAIT_SET_IS_INVERTED(osreldate)) {
3897c916264SJohn Polstra 		/* Kernel bug requires an inverted signal set. */
3907c916264SJohn Polstra 		SIGFILLSET(_thread_suspend_sigset);
3917c916264SJohn Polstra 		SIGDELSET(_thread_suspend_sigset, SIGTHR);
3927c916264SJohn Polstra 	} else {
3937c916264SJohn Polstra 		SIGEMPTYSET(_thread_suspend_sigset);
3947c916264SJohn Polstra 		SIGADDSET(_thread_suspend_sigset, SIGTHR);
3957c916264SJohn Polstra 	}
396393441d4SMike Makonnen #ifdef _PTHREADS_INVARIANTS
397393441d4SMike Makonnen 	SIGADDSET(_thread_suspend_sigset, SIGALRM);
398393441d4SMike Makonnen #endif
3997c916264SJohn Polstra 
400bb535300SJeff Roberson 	/* Get the kernel clockrate: */
401bb535300SJeff Roberson 	mib[0] = CTL_KERN;
402bb535300SJeff Roberson 	mib[1] = KERN_CLOCKRATE;
403bb535300SJeff Roberson 	len = sizeof (struct clockinfo);
404bb535300SJeff Roberson 	if (sysctl(mib, 2, &clockinfo, &len, NULL, 0) == 0)
405bb535300SJeff Roberson 		_clock_res_usec = clockinfo.tick > CLOCK_RES_USEC_MIN ?
406bb535300SJeff Roberson 		    clockinfo.tick : CLOCK_RES_USEC_MIN;
407bb535300SJeff Roberson }
408bb535300SJeff Roberson 
409bb535300SJeff Roberson /*
410bb535300SJeff Roberson  * Special start up code for NetBSD/Alpha
411bb535300SJeff Roberson  */
412bb535300SJeff Roberson #if	defined(__NetBSD__) && defined(__alpha__)
413bb535300SJeff Roberson int
414bb535300SJeff Roberson main(int argc, char *argv[], char *env);
415bb535300SJeff Roberson 
416bb535300SJeff Roberson int
417bb535300SJeff Roberson _thread_main(int argc, char *argv[], char *env)
418bb535300SJeff Roberson {
419bb535300SJeff Roberson 	_thread_init();
420bb535300SJeff Roberson 	return (main(argc, argv, env));
421bb535300SJeff Roberson }
422bb535300SJeff Roberson #endif
423