thr_init.c revision 139023
17857Sgibbs/*
27857Sgibbs * Copyright (c) 2003 Daniel M. Eischen <deischen@freebsd.org>
34568Sgibbs * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
47857Sgibbs * All rights reserved.
57857Sgibbs *
67857Sgibbs * Redistribution and use in source and binary forms, with or without
77857Sgibbs * modification, are permitted provided that the following conditions
87857Sgibbs * are met:
97857Sgibbs * 1. Redistributions of source code must retain the above copyright
107857Sgibbs *    notice, this list of conditions and the following disclaimer.
117857Sgibbs * 2. Redistributions in binary form must reproduce the above copyright
127857Sgibbs *    notice, this list of conditions and the following disclaimer in the
137857Sgibbs *    documentation and/or other materials provided with the distribution.
147857Sgibbs * 3. All advertising materials mentioning features or use of this software
157857Sgibbs *    must display the following acknowledgement:
167857Sgibbs *	This product includes software developed by John Birrell.
177857Sgibbs * 4. Neither the name of the author nor the names of any co-contributors
187857Sgibbs *    may be used to endorse or promote products derived from this software
197857Sgibbs *    without specific prior written permission.
207857Sgibbs *
217857Sgibbs * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
227857Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
237857Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
247857Sgibbs * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
257857Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
267857Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
277857Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
287857Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
297857Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
307857Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
317857Sgibbs * SUCH DAMAGE.
327857Sgibbs *
337857Sgibbs * $FreeBSD: head/lib/libkse/thread/thr_init.c 139023 2004-12-18 18:07:37Z deischen $
347857Sgibbs */
357857Sgibbs
367857Sgibbs/* Allocate space for global thread variables here: */
377857Sgibbs#define GLOBAL_PTHREAD_PRIVATE
384568Sgibbs
396608Sgibbs#include "namespace.h"
406608Sgibbs#include <sys/param.h>
415647Sgibbs#include <sys/types.h>
427857Sgibbs#include <sys/signalvar.h>
434568Sgibbs#include <machine/reg.h>
449917Sgibbs
455647Sgibbs#include <sys/ioctl.h>
469928Sgibbs#include <sys/mount.h>
474568Sgibbs#include <sys/uio.h>
484568Sgibbs#include <sys/socket.h>
498104Sgibbs#include <sys/event.h>
504568Sgibbs#include <sys/stat.h>
514568Sgibbs#include <sys/sysctl.h>
524568Sgibbs#include <sys/time.h>
534568Sgibbs#include <sys/ttycom.h>
544568Sgibbs#include <sys/wait.h>
554568Sgibbs#include <sys/mman.h>
564568Sgibbs#include <dirent.h>
574568Sgibbs#include <errno.h>
584568Sgibbs#include <fcntl.h>
594568Sgibbs#include <paths.h>
604568Sgibbs#include <pthread.h>
618104Sgibbs#include <pthread_np.h>
624568Sgibbs#include <signal.h>
638104Sgibbs#include <stdio.h>
648104Sgibbs#include <stdlib.h>
654568Sgibbs#include <string.h>
664568Sgibbs#include <unistd.h>
679928Sgibbs#include "un-namespace.h"
684568Sgibbs
694568Sgibbs#include "libc_private.h"
704568Sgibbs#include "thr_private.h"
714568Sgibbs
724568Sgibbsint	__pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
734568Sgibbsint	__pthread_mutex_lock(pthread_mutex_t *);
744568Sgibbsint	__pthread_mutex_trylock(pthread_mutex_t *);
754568Sgibbsvoid	_thread_init_hack(void);
764568Sgibbsextern int _thread_state_running;
774568Sgibbs
784568Sgibbsstatic void init_private(void);
794568Sgibbsstatic void init_main_thread(struct pthread *thread);
804568Sgibbs
814568Sgibbs/*
824568Sgibbs * All weak references used within libc should be in this table.
837532Sgibbs * This is so that static libraries will work.
847532Sgibbs */
857532Sgibbsstatic void *references[] = {
864568Sgibbs	&_accept,
874568Sgibbs	&_bind,
884568Sgibbs	&_close,
894568Sgibbs	&_connect,
904568Sgibbs	&_dup,
914568Sgibbs	&_dup2,
924568Sgibbs	&_execve,
934568Sgibbs	&_fcntl,
944568Sgibbs	&_flock,
954568Sgibbs	&_flockfile,
964568Sgibbs	&_fstat,
974568Sgibbs	&_fstatfs,
984568Sgibbs	&_fsync,
995326Sgibbs	&_funlockfile,
1005326Sgibbs	&_getdirentries,
1014568Sgibbs	&_getlogin,
1024568Sgibbs	&_getpeername,
1039928Sgibbs	&_getsockname,
1049928Sgibbs	&_getsockopt,
1059928Sgibbs	&_ioctl,
1069928Sgibbs	&_kevent,
1079928Sgibbs	&_listen,
1084568Sgibbs	&_nanosleep,
1094568Sgibbs	&_open,
1105647Sgibbs	&_pthread_getspecific,
1115647Sgibbs	&_pthread_key_create,
1125647Sgibbs	&_pthread_key_delete,
1139928Sgibbs	&_pthread_mutex_destroy,
1146608Sgibbs	&_pthread_mutex_init,
1159928Sgibbs	&_pthread_mutex_lock,
1165647Sgibbs	&_pthread_mutex_trylock,
1175647Sgibbs	&_pthread_mutex_unlock,
1184568Sgibbs	&_pthread_mutexattr_init,
1194568Sgibbs	&_pthread_mutexattr_destroy,
1204568Sgibbs	&_pthread_mutexattr_settype,
1215647Sgibbs	&_pthread_once,
1225647Sgibbs	&_pthread_setspecific,
1235647Sgibbs	&_read,
1244568Sgibbs	&_readv,
1255647Sgibbs	&_recvfrom,
1265647Sgibbs	&_recvmsg,
1275647Sgibbs	&_select,
1284568Sgibbs	&_sendmsg,
1295647Sgibbs	&_sendto,
1305647Sgibbs	&_setsockopt,
1314568Sgibbs	&_sigaction,
1324568Sgibbs	&_sigprocmask,
1334568Sgibbs	&_sigsuspend,
1344568Sgibbs	&_socket,
1354568Sgibbs	&_socketpair,
1364568Sgibbs	&_thread_init_hack,
1374568Sgibbs	&_wait4,
1384568Sgibbs	&_write,
1394568Sgibbs	&_writev
1404568Sgibbs};
1414568Sgibbs
1424568Sgibbs/*
1435647Sgibbs * These are needed when linking statically.  All references within
1447532Sgibbs * libgcc (and in the future libc) to these routines are weak, but
1457532Sgibbs * if they are not (strongly) referenced by the application or other
1467532Sgibbs * libraries, then the actual functions will not be loaded.
1478104Sgibbs */
1484568Sgibbsstatic void *libgcc_references[] = {
1495647Sgibbs	&_pthread_once,
1508104Sgibbs	&_pthread_key_create,
1515647Sgibbs	&_pthread_key_delete,
1525647Sgibbs	&_pthread_getspecific,
1535647Sgibbs	&_pthread_setspecific,
1545647Sgibbs	&_pthread_mutex_init,
1555647Sgibbs	&_pthread_mutex_destroy,
1565647Sgibbs	&_pthread_mutex_lock,
1575647Sgibbs	&_pthread_mutex_trylock,
1587532Sgibbs	&_pthread_mutex_unlock
1597562Sgibbs};
1608567Sdg
1618567Sdg#define	DUAL_ENTRY(entry)	\
1628567Sdg	(pthread_func_t)entry, (pthread_func_t)entry
1638567Sdg
1648567Sdgstatic pthread_func_t jmp_table[][2] = {
1659810Sgibbs	{DUAL_ENTRY(_pthread_cond_broadcast)},	/* PJT_COND_BROADCAST */
1664568Sgibbs	{DUAL_ENTRY(_pthread_cond_destroy)},	/* PJT_COND_DESTROY */
1678567Sdg	{DUAL_ENTRY(_pthread_cond_init)},	/* PJT_COND_INIT */
1684568Sgibbs	{DUAL_ENTRY(_pthread_cond_signal)},	/* PJT_COND_SIGNAL */
1695326Sgibbs	{(pthread_func_t)__pthread_cond_wait,
1705326Sgibbs	 (pthread_func_t)_pthread_cond_wait},	/* PJT_COND_WAIT */
1714568Sgibbs	{DUAL_ENTRY(_pthread_getspecific)},	/* PJT_GETSPECIFIC */
1724568Sgibbs	{DUAL_ENTRY(_pthread_key_create)},	/* PJT_KEY_CREATE */
1735326Sgibbs	{DUAL_ENTRY(_pthread_key_delete)},	/* PJT_KEY_DELETE*/
1745326Sgibbs	{DUAL_ENTRY(_pthread_main_np)},		/* PJT_MAIN_NP */
1759928Sgibbs	{DUAL_ENTRY(_pthread_mutex_destroy)},	/* PJT_MUTEX_DESTROY */
1769928Sgibbs	{DUAL_ENTRY(_pthread_mutex_init)},	/* PJT_MUTEX_INIT */
1779928Sgibbs	{(pthread_func_t)__pthread_mutex_lock,
1789928Sgibbs	 (pthread_func_t)_pthread_mutex_lock},	/* PJT_MUTEX_LOCK */
1799928Sgibbs	{(pthread_func_t)__pthread_mutex_trylock,
1804568Sgibbs	 (pthread_func_t)_pthread_mutex_trylock},/* PJT_MUTEX_TRYLOCK */
1818104Sgibbs	{DUAL_ENTRY(_pthread_mutex_unlock)},	/* PJT_MUTEX_UNLOCK */
1828104Sgibbs	{DUAL_ENTRY(_pthread_mutexattr_destroy)}, /* PJT_MUTEXATTR_DESTROY */
1834568Sgibbs	{DUAL_ENTRY(_pthread_mutexattr_init)},	/* PJT_MUTEXATTR_INIT */
1845562Sgibbs	{DUAL_ENTRY(_pthread_mutexattr_settype)}, /* PJT_MUTEXATTR_SETTYPE */
1854568Sgibbs	{DUAL_ENTRY(_pthread_once)},		/* PJT_ONCE */
1864568Sgibbs	{DUAL_ENTRY(_pthread_rwlock_destroy)},	/* PJT_RWLOCK_DESTROY */
1874568Sgibbs	{DUAL_ENTRY(_pthread_rwlock_init)},	/* PJT_RWLOCK_INIT */
1884568Sgibbs	{DUAL_ENTRY(_pthread_rwlock_rdlock)},	/* PJT_RWLOCK_RDLOCK */
1898104Sgibbs	{DUAL_ENTRY(_pthread_rwlock_tryrdlock)},/* PJT_RWLOCK_TRYRDLOCK */
1909928Sgibbs	{DUAL_ENTRY(_pthread_rwlock_trywrlock)},/* PJT_RWLOCK_TRYWRLOCK */
1919928Sgibbs	{DUAL_ENTRY(_pthread_rwlock_unlock)},	/* PJT_RWLOCK_UNLOCK */
1929928Sgibbs	{DUAL_ENTRY(_pthread_rwlock_wrlock)},	/* PJT_RWLOCK_WRLOCK */
1934568Sgibbs	{DUAL_ENTRY(_pthread_self)},		/* PJT_SELF */
1944568Sgibbs	{DUAL_ENTRY(_pthread_setspecific)},	/* PJT_SETSPECIFIC */
1954568Sgibbs	{DUAL_ENTRY(_pthread_sigmask)}		/* PJT_SIGMASK */
1964568Sgibbs};
1974568Sgibbs
1984568Sgibbsstatic int	init_once = 0;
1995326Sgibbs
2005326Sgibbs/*
2014568Sgibbs * Threaded process initialization.
2026608Sgibbs *
2036608Sgibbs * This is only called under two conditions:
2046608Sgibbs *
2056608Sgibbs *   1) Some thread routines have detected that the library hasn't yet
2066608Sgibbs *      been initialized (_thr_initial == NULL && curthread == NULL), or
2076608Sgibbs *
2086608Sgibbs *   2) An explicit call to reinitialize after a fork (indicated
2097562Sgibbs *      by curthread != NULL)
2104568Sgibbs */
2116608Sgibbsvoid
2125647Sgibbs_libpthread_init(struct pthread *curthread)
2136608Sgibbs{
2144568Sgibbs	int fd;
2156608Sgibbs
2164568Sgibbs	/* Check if this function has already been called: */
2175647Sgibbs	if ((_thr_initial != NULL) && (curthread == NULL))
2185647Sgibbs		/* Only initialize the threaded application once. */
2195647Sgibbs		return;
2209928Sgibbs
2215647Sgibbs	/*
2229928Sgibbs	 * Make gcc quiescent about {,libgcc_}references not being
2236608Sgibbs	 * referenced:
2246608Sgibbs	 */
2256608Sgibbs	if ((references[0] == NULL) || (libgcc_references[0] == NULL))
2266608Sgibbs		PANIC("Failed loading mandatory references in _thread_init");
2276608Sgibbs
2286608Sgibbs	/* Pull debug symbols in for static binary */
2294568Sgibbs	_thread_state_running = PS_RUNNING;
2306608Sgibbs
2316608Sgibbs	/*
2325326Sgibbs	 * Check the size of the jump table to make sure it is preset
2335326Sgibbs	 * with the correct number of entries.
2349928Sgibbs	 */
2358567Sdg	if (sizeof(jmp_table) != (sizeof(pthread_func_t) * PJT_MAX * 2))
2365562Sgibbs		PANIC("Thread jump table not properly initialized");
2375562Sgibbs	memcpy(__thr_jtable, jmp_table, sizeof(jmp_table));
2385562Sgibbs
2394568Sgibbs	/*
2408567Sdg	 * Check for the special case of this process running as
2418567Sdg	 * or in place of init as pid = 1:
2428567Sdg	 */
2436608Sgibbs	if ((_thr_pid = getpid()) == 1) {
2446608Sgibbs		/*
2458104Sgibbs		 * Setup a new session for this process which is
2468104Sgibbs		 * assumed to be running as root.
2478104Sgibbs		 */
2488104Sgibbs		if (setsid() == -1)
2498104Sgibbs			PANIC("Can't set session ID");
2508104Sgibbs		if (revoke(_PATH_CONSOLE) != 0)
2518104Sgibbs			PANIC("Can't revoke console");
2528104Sgibbs		if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0)
2538104Sgibbs			PANIC("Can't open console");
2548104Sgibbs		if (setlogin("root") == -1)
2558104Sgibbs			PANIC("Can't set login to root");
2568104Sgibbs		if (__sys_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1)
2578104Sgibbs			PANIC("Can't set controlling terminal");
2589395Sgibbs	}
2599395Sgibbs
2608104Sgibbs	/* Initialize pthread private data. */
2618104Sgibbs	init_private();
2628104Sgibbs	_kse_init();
2638104Sgibbs
2648104Sgibbs	/* Initialize the initial kse and kseg. */
2658104Sgibbs	_kse_initial = _kse_alloc(NULL, _thread_scope_system > 0);
2668104Sgibbs	if (_kse_initial == NULL)
2679395Sgibbs		PANIC("Can't allocate initial kse.");
2688104Sgibbs	_kse_initial->k_kseg = _kseg_alloc(NULL);
2698104Sgibbs	if (_kse_initial->k_kseg == NULL)
2704866Sgibbs		PANIC("Can't allocate initial kseg.");
2714568Sgibbs	_kse_initial->k_kseg->kg_flags |= KGF_SINGLE_THREAD;
2724568Sgibbs	_kse_initial->k_schedq = &_kse_initial->k_kseg->kg_schedq;
2738104Sgibbs
2745326Sgibbs	TAILQ_INSERT_TAIL(&_kse_initial->k_kseg->kg_kseq, _kse_initial, k_kgqe);
2755326Sgibbs	_kse_initial->k_kseg->kg_ksecount = 1;
2765326Sgibbs
2775326Sgibbs	/* Set the initial thread. */
2788104Sgibbs	if (curthread == NULL) {
2795326Sgibbs		/* Create and initialize the initial thread. */
2805326Sgibbs		curthread = _thr_alloc(NULL);
2818104Sgibbs		if (curthread == NULL)
2829395Sgibbs			PANIC("Can't allocate initial thread");
2838104Sgibbs		_thr_initial = curthread;
2844568Sgibbs		init_main_thread(curthread);
2858104Sgibbs	} else {
2868104Sgibbs		/*
2878104Sgibbs		 * The initial thread is the current thread.  It is
2888104Sgibbs		 * assumed that the current thread is already initialized
2898104Sgibbs		 * because it is left over from a fork().
2904568Sgibbs		 */
2914568Sgibbs		_thr_initial = curthread;
2924568Sgibbs	}
2935647Sgibbs	_kse_initial->k_kseg->kg_threadcount = 0;
2945647Sgibbs	_thr_initial->kse = _kse_initial;
2955647Sgibbs	_thr_initial->kseg = _kse_initial->k_kseg;
2968104Sgibbs	_thr_initial->active = 1;
2975647Sgibbs
2985647Sgibbs	/*
2995647Sgibbs	 * Add the thread to the thread list and to the KSEG's thread
3005647Sgibbs         * queue.
3018104Sgibbs	 */
3028104Sgibbs	THR_LIST_ADD(_thr_initial);
3038104Sgibbs	KSEG_THRQ_ADD(_kse_initial->k_kseg, _thr_initial);
3048104Sgibbs
3055647Sgibbs	/* Setup the KSE/thread specific data for the current KSE/thread. */
3065647Sgibbs	_thr_initial->kse->k_curthread = _thr_initial;
3075647Sgibbs	_kcb_set(_thr_initial->kse->k_kcb);
3085647Sgibbs	_tcb_set(_thr_initial->kse->k_kcb, _thr_initial->tcb);
3097532Sgibbs	_thr_initial->kse->k_flags |= KF_INITIALIZED;
3105647Sgibbs
3115647Sgibbs	_thr_signal_init();
3125647Sgibbs	_kse_critical_leave(&_thr_initial->tcb->tcb_tmbx);
3137532Sgibbs	/*
3149928Sgibbs	 * activate threaded mode as soon as possible if we are
3159928Sgibbs	 * being debugged
3169928Sgibbs	 */
3179928Sgibbs	if (_libkse_debug)
3188104Sgibbs		_kse_setthreaded(1);
3194568Sgibbs}
3205326Sgibbs
3215326Sgibbs/*
3225326Sgibbs * This function and pthread_create() do a lot of the same things.
3235326Sgibbs * It'd be nice to consolidate the common stuff in one place.
3245326Sgibbs */
3255326Sgibbsstatic void
3265326Sgibbsinit_main_thread(struct pthread *thread)
3274568Sgibbs{
3285647Sgibbs	/* Setup the thread attributes. */
3294568Sgibbs	thread->attr = _pthread_attr_default;
3304568Sgibbs	thread->attr.flags |= PTHREAD_SCOPE_SYSTEM;
3315326Sgibbs	/*
3325326Sgibbs	 * Set up the thread stack.
3335326Sgibbs	 *
3349928Sgibbs	 * Create a red zone below the main stack.  All other stacks
3355326Sgibbs	 * are constrained to a maximum size by the parameters
3365326Sgibbs	 * passed to mmap(), but this stack is only limited by
3375326Sgibbs	 * resource limits, so this stack needs an explicitly mapped
3384568Sgibbs	 * red zone to protect the thread stack that is just beyond.
3395326Sgibbs	 */
3404568Sgibbs	if (mmap((void *)_usrstack - THR_STACK_INITIAL -
3418104Sgibbs	    _thr_guard_default, _thr_guard_default, 0, MAP_ANON,
3424568Sgibbs	    -1, 0) == MAP_FAILED)
3438104Sgibbs		PANIC("Cannot allocate red zone for initial thread");
3448104Sgibbs
3458104Sgibbs	/*
3468104Sgibbs	 * Mark the stack as an application supplied stack so that it
3478104Sgibbs	 * isn't deallocated.
3485326Sgibbs	 *
3495326Sgibbs	 * XXX - I'm not sure it would hurt anything to deallocate
3509928Sgibbs	 *       the main thread stack because deallocation doesn't
3515326Sgibbs	 *       actually free() it; it just puts it in the free
3525326Sgibbs	 *       stack queue for later reuse.
3535326Sgibbs	 */
3546940Sgibbs	thread->attr.stackaddr_attr = (void *)_usrstack - THR_STACK_INITIAL;
3556940Sgibbs	thread->attr.stacksize_attr = THR_STACK_INITIAL;
3566940Sgibbs	thread->attr.guardsize_attr = _thr_guard_default;
3576940Sgibbs	thread->attr.flags |= THR_STACK_USER;
3588104Sgibbs
3598104Sgibbs	/*
3608104Sgibbs	 * Write a magic value to the thread structure
3618104Sgibbs	 * to help identify valid ones:
3628104Sgibbs	 */
3638104Sgibbs	thread->magic = THR_MAGIC;
3648104Sgibbs
3658104Sgibbs	thread->slice_usec = -1;
3668104Sgibbs	thread->cancelflags = PTHREAD_CANCEL_ENABLE | PTHREAD_CANCEL_DEFERRED;
3678104Sgibbs	thread->name = strdup("initial thread");
3689928Sgibbs
3694568Sgibbs	/* Initialize the thread for signals: */
3704568Sgibbs	SIGEMPTYSET(thread->sigmask);
3714568Sgibbs
3724568Sgibbs	/*
3734568Sgibbs	 * Set up the thread mailbox.  The threads saved context
3744866Sgibbs	 * is also in the mailbox.
3754568Sgibbs	 */
3764568Sgibbs	thread->tcb->tcb_tmbx.tm_udata = thread;
3774568Sgibbs	thread->tcb->tcb_tmbx.tm_context.uc_stack.ss_size =
3784568Sgibbs	    thread->attr.stacksize_attr;
3798567Sdg	thread->tcb->tcb_tmbx.tm_context.uc_stack.ss_sp =
3808567Sdg	    thread->attr.stackaddr_attr;
3818567Sdg
3828567Sdg	/* Default the priority of the initial thread: */
3838567Sdg	thread->base_priority = THR_DEFAULT_PRIORITY;
3848567Sdg	thread->active_priority = THR_DEFAULT_PRIORITY;
3858567Sdg	thread->inherited_priority = 0;
3868567Sdg
3879917Sgibbs	/* Initialize the mutex queue: */
3888567Sdg	TAILQ_INIT(&thread->mutexq);
3898567Sdg
3909928Sgibbs	/* Initialize hooks in the thread structure: */
3914568Sgibbs	thread->specific = NULL;
3924568Sgibbs	thread->cleanup = NULL;
3939928Sgibbs	thread->flags = 0;
3944568Sgibbs	thread->sigbackout = NULL;
3954568Sgibbs	thread->continuation = NULL;
3964568Sgibbs
3979928Sgibbs	thread->state = PS_RUNNING;
3984568Sgibbs	thread->uniqueid = 0;
3994568Sgibbs}
4006608Sgibbs
4016608Sgibbsstatic void
4026608Sgibbsinit_private(void)
4036608Sgibbs{
4046608Sgibbs	struct clockinfo clockinfo;
4056608Sgibbs	size_t len;
4066608Sgibbs	int mib[2];
4076608Sgibbs
4086608Sgibbs	/*
4096608Sgibbs	 * Avoid reinitializing some things if they don't need to be,
4106608Sgibbs	 * e.g. after a fork().
4116608Sgibbs	 */
4126608Sgibbs	if (init_once == 0) {
4136608Sgibbs		/* Find the stack top */
4146608Sgibbs		mib[0] = CTL_KERN;
4156608Sgibbs		mib[1] = KERN_USRSTACK;
4164568Sgibbs		len = sizeof (_usrstack);
4179917Sgibbs		if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) == -1)
4189917Sgibbs			PANIC("Cannot get kern.usrstack from sysctl");
4199917Sgibbs		/* Get the kernel clockrate: */
4209917Sgibbs		mib[0] = CTL_KERN;
4214568Sgibbs		mib[1] = KERN_CLOCKRATE;
4228104Sgibbs		len = sizeof (struct clockinfo);
4234568Sgibbs		if (sysctl(mib, 2, &clockinfo, &len, NULL, 0) == 0)
4244568Sgibbs			_clock_res_usec = clockinfo.tick;
4254568Sgibbs		else
4264568Sgibbs			_clock_res_usec = CLOCK_RES_USEC;
4278104Sgibbs
4285562Sgibbs		_thr_page_size = getpagesize();
4298104Sgibbs		_thr_guard_default = _thr_page_size;
4304568Sgibbs		init_once = 1;	/* Don't do this again. */
4318104Sgibbs	} else {
4328104Sgibbs		/*
4338104Sgibbs		 * Destroy the locks before creating them.  We don't
4348104Sgibbs		 * know what state they are in so it is better to just
4354568Sgibbs		 * recreate them.
4368104Sgibbs		 */
4378104Sgibbs		_lock_destroy(&_thread_signal_lock);
4388104Sgibbs		_lock_destroy(&_mutex_static_lock);
4398104Sgibbs		_lock_destroy(&_rwlock_static_lock);
4408104Sgibbs		_lock_destroy(&_keytable_lock);
4418104Sgibbs	}
4428104Sgibbs
4438104Sgibbs	/* Initialize everything else. */
4444568Sgibbs	TAILQ_INIT(&_thread_list);
4454568Sgibbs	TAILQ_INIT(&_thread_gc_list);
4464568Sgibbs	TAILQ_INIT(&_thr_atfork_list);
4474568Sgibbs	_pthread_mutex_init(&_thr_atfork_mutex, NULL);
4484568Sgibbs
4494568Sgibbs	/*
4504568Sgibbs	 * Initialize the lock for temporary installation of signal
4514568Sgibbs	 * handlers (to support sigwait() semantics) and for the
4524568Sgibbs	 * process signal mask and pending signal sets.
4534568Sgibbs	 */
4544568Sgibbs	if (_lock_init(&_thread_signal_lock, LCK_ADAPTIVE,
4554568Sgibbs	    _kse_lock_wait, _kse_lock_wakeup) != 0)
4564568Sgibbs		PANIC("Cannot initialize _thread_signal_lock");
4574568Sgibbs	if (_lock_init(&_mutex_static_lock, LCK_ADAPTIVE,
4584568Sgibbs	    _thr_lock_wait, _thr_lock_wakeup) != 0)
4594568Sgibbs		PANIC("Cannot initialize mutex static init lock");
4604568Sgibbs	if (_lock_init(&_rwlock_static_lock, LCK_ADAPTIVE,
4614568Sgibbs	    _thr_lock_wait, _thr_lock_wakeup) != 0)
4624568Sgibbs		PANIC("Cannot initialize rwlock static init lock");
4634568Sgibbs	if (_lock_init(&_keytable_lock, LCK_ADAPTIVE,
4644568Sgibbs	    _thr_lock_wait, _thr_lock_wakeup) != 0)
4654568Sgibbs		PANIC("Cannot initialize thread specific keytable lock");
4664568Sgibbs	_thr_spinlock_init();
4674568Sgibbs
4684568Sgibbs	/* Clear pending signals and get the process signal mask. */
4695647Sgibbs	SIGEMPTYSET(_thr_proc_sigpending);
4704568Sgibbs
4714568Sgibbs	/* Are we in M:N mode (default) or 1:1 mode? */
4724568Sgibbs#ifdef SYSTEM_SCOPE_ONLY
4739928Sgibbs	_thread_scope_system = 1;
4749928Sgibbs#else
4759928Sgibbs	if (getenv("LIBPTHREAD_SYSTEM_SCOPE") != NULL)
4764568Sgibbs		_thread_scope_system = 1;
4779928Sgibbs	else if (getenv("LIBPTHREAD_PROCESS_SCOPE") != NULL)
4789928Sgibbs		_thread_scope_system = -1;
4799928Sgibbs#endif
4809928Sgibbs
4819928Sgibbs	/*
4829928Sgibbs	 * _thread_list_lock and _kse_count are initialized
4834568Sgibbs	 * by _kse_init()
4849928Sgibbs	 */
4859928Sgibbs}
4869928Sgibbs