113546Sjulian/*
2113661Sdeischen * Copyright (c) 2003 Daniel M. Eischen <deischen@freebsd.org>
335509Sjb * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
413546Sjulian * All rights reserved.
513546Sjulian *
613546Sjulian * Redistribution and use in source and binary forms, with or without
713546Sjulian * modification, are permitted provided that the following conditions
813546Sjulian * are met:
913546Sjulian * 1. Redistributions of source code must retain the above copyright
1013546Sjulian *    notice, this list of conditions and the following disclaimer.
1113546Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1213546Sjulian *    notice, this list of conditions and the following disclaimer in the
1313546Sjulian *    documentation and/or other materials provided with the distribution.
14165967Simp * 3. Neither the name of the author nor the names of any co-contributors
1513546Sjulian *    may be used to endorse or promote products derived from this software
1613546Sjulian *    without specific prior written permission.
1713546Sjulian *
1813546Sjulian * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
1913546Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2013546Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2144963Sjb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2213546Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2313546Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2413546Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2513546Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2613546Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2713546Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2813546Sjulian * SUCH DAMAGE.
2913546Sjulian *
3050476Speter * $FreeBSD$
3113546Sjulian */
3213546Sjulian
3313546Sjulian/* Allocate space for global thread variables here: */
3413546Sjulian#define GLOBAL_PTHREAD_PRIVATE
3513546Sjulian
3671581Sdeischen#include "namespace.h"
3771581Sdeischen#include <sys/param.h>
3871581Sdeischen#include <sys/types.h>
39116977Sdavidxu#include <sys/signalvar.h>
4071581Sdeischen#include <machine/reg.h>
4171581Sdeischen
4253812Salfred#include <sys/ioctl.h>
4371581Sdeischen#include <sys/mount.h>
4471581Sdeischen#include <sys/uio.h>
4571581Sdeischen#include <sys/socket.h>
4671581Sdeischen#include <sys/event.h>
4771581Sdeischen#include <sys/stat.h>
4848046Sjb#include <sys/sysctl.h>
4913546Sjulian#include <sys/time.h>
5038208Sjb#include <sys/ttycom.h>
5171581Sdeischen#include <sys/wait.h>
5248569Sjasone#include <sys/mman.h>
5371581Sdeischen#include <dirent.h>
5471581Sdeischen#include <errno.h>
5571581Sdeischen#include <fcntl.h>
5671581Sdeischen#include <paths.h>
5713546Sjulian#include <pthread.h>
58113658Sdeischen#include <pthread_np.h>
5971581Sdeischen#include <signal.h>
6071581Sdeischen#include <stdio.h>
6171581Sdeischen#include <stdlib.h>
6271581Sdeischen#include <string.h>
6371581Sdeischen#include <unistd.h>
6471581Sdeischen#include "un-namespace.h"
6571581Sdeischen
66113658Sdeischen#include "libc_private.h"
67103388Smini#include "thr_private.h"
6813546Sjulian
69113658Sdeischenint	__pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
70113658Sdeischenint	__pthread_mutex_lock(pthread_mutex_t *);
71113658Sdeischenint	__pthread_mutex_trylock(pthread_mutex_t *);
72115080Sdeischenvoid	_thread_init_hack(void);
73134115Sdavidxuextern int _thread_state_running;
74113658Sdeischen
75113658Sdeischenstatic void init_private(void);
76113658Sdeischenstatic void init_main_thread(struct pthread *thread);
77113658Sdeischen
7870702Sobrien/*
7971581Sdeischen * All weak references used within libc should be in this table.
80113658Sdeischen * This is so that static libraries will work.
8171581Sdeischen */
8271581Sdeischenstatic void *references[] = {
8371581Sdeischen	&_accept,
8471581Sdeischen	&_bind,
8571581Sdeischen	&_close,
8671581Sdeischen	&_connect,
8771581Sdeischen	&_dup,
8871581Sdeischen	&_dup2,
8971581Sdeischen	&_execve,
9071581Sdeischen	&_fcntl,
9171581Sdeischen	&_flock,
9271581Sdeischen	&_flockfile,
9371581Sdeischen	&_fstat,
9471581Sdeischen	&_fstatfs,
9571581Sdeischen	&_fsync,
9671581Sdeischen	&_funlockfile,
9771581Sdeischen	&_getdirentries,
9871581Sdeischen	&_getlogin,
9971581Sdeischen	&_getpeername,
10071581Sdeischen	&_getsockname,
10171581Sdeischen	&_getsockopt,
10271581Sdeischen	&_ioctl,
10371581Sdeischen	&_kevent,
10471581Sdeischen	&_listen,
10571581Sdeischen	&_nanosleep,
10671581Sdeischen	&_open,
10771581Sdeischen	&_pthread_getspecific,
10871581Sdeischen	&_pthread_key_create,
10971581Sdeischen	&_pthread_key_delete,
11071581Sdeischen	&_pthread_mutex_destroy,
11171581Sdeischen	&_pthread_mutex_init,
11271581Sdeischen	&_pthread_mutex_lock,
11371581Sdeischen	&_pthread_mutex_trylock,
11471581Sdeischen	&_pthread_mutex_unlock,
11571581Sdeischen	&_pthread_mutexattr_init,
11671581Sdeischen	&_pthread_mutexattr_destroy,
11771581Sdeischen	&_pthread_mutexattr_settype,
11871581Sdeischen	&_pthread_once,
11971581Sdeischen	&_pthread_setspecific,
12071581Sdeischen	&_read,
12171581Sdeischen	&_readv,
12271581Sdeischen	&_recvfrom,
12371581Sdeischen	&_recvmsg,
12471581Sdeischen	&_select,
12571581Sdeischen	&_sendmsg,
12671581Sdeischen	&_sendto,
12771581Sdeischen	&_setsockopt,
12871581Sdeischen	&_sigaction,
12971581Sdeischen	&_sigprocmask,
13071581Sdeischen	&_sigsuspend,
13171581Sdeischen	&_socket,
13271581Sdeischen	&_socketpair,
133115080Sdeischen	&_thread_init_hack,
13471581Sdeischen	&_wait4,
13571581Sdeischen	&_write,
13671581Sdeischen	&_writev
13771581Sdeischen};
13871581Sdeischen
13971581Sdeischen/*
14070702Sobrien * These are needed when linking statically.  All references within
14170702Sobrien * libgcc (and in the future libc) to these routines are weak, but
14270702Sobrien * if they are not (strongly) referenced by the application or other
14370702Sobrien * libraries, then the actual functions will not be loaded.
14470702Sobrien */
14571581Sdeischenstatic void *libgcc_references[] = {
14671581Sdeischen	&_pthread_once,
14771581Sdeischen	&_pthread_key_create,
14871581Sdeischen	&_pthread_key_delete,
14971581Sdeischen	&_pthread_getspecific,
15071581Sdeischen	&_pthread_setspecific,
15171581Sdeischen	&_pthread_mutex_init,
15271581Sdeischen	&_pthread_mutex_destroy,
15371581Sdeischen	&_pthread_mutex_lock,
15471581Sdeischen	&_pthread_mutex_trylock,
15571581Sdeischen	&_pthread_mutex_unlock
15670702Sobrien};
15770702Sobrien
158113658Sdeischen#define	DUAL_ENTRY(entry)	\
159113658Sdeischen	(pthread_func_t)entry, (pthread_func_t)entry
16033292Sjulian
161113658Sdeischenstatic pthread_func_t jmp_table[][2] = {
162156319Sdeischen	{DUAL_ENTRY(_pthread_atfork)},	/* PJT_ATFORK */
163156319Sdeischen	{DUAL_ENTRY(_pthread_attr_destroy)},	/* PJT_ATTR_DESTROY */
164156319Sdeischen	{DUAL_ENTRY(_pthread_attr_getdetachstate)},	/* PJT_ATTR_GETDETACHSTATE */
165156319Sdeischen	{DUAL_ENTRY(_pthread_attr_getguardsize)},	/* PJT_ATTR_GETGUARDSIZE */
166156319Sdeischen	{DUAL_ENTRY(_pthread_attr_getinheritsched)},	/* PJT_ATTR_GETINHERITSCHED */
167156319Sdeischen	{DUAL_ENTRY(_pthread_attr_getschedparam)},	/* PJT_ATTR_GETSCHEDPARAM */
168156319Sdeischen	{DUAL_ENTRY(_pthread_attr_getschedpolicy)},	/* PJT_ATTR_GETSCHEDPOLICY */
169156319Sdeischen	{DUAL_ENTRY(_pthread_attr_getscope)},	/* PJT_ATTR_GETSCOPE */
170156319Sdeischen	{DUAL_ENTRY(_pthread_attr_getstackaddr)},	/* PJT_ATTR_GETSTACKADDR */
171156319Sdeischen	{DUAL_ENTRY(_pthread_attr_getstacksize)},	/* PJT_ATTR_GETSTACKSIZE */
172156319Sdeischen	{DUAL_ENTRY(_pthread_attr_init)},	/* PJT_ATTR_INIT */
173156319Sdeischen	{DUAL_ENTRY(_pthread_attr_setdetachstate)},	/* PJT_ATTR_SETDETACHSTATE */
174156319Sdeischen	{DUAL_ENTRY(_pthread_attr_setguardsize)},	/* PJT_ATTR_SETGUARDSIZE */
175156319Sdeischen	{DUAL_ENTRY(_pthread_attr_setinheritsched)},	/* PJT_ATTR_SETINHERITSCHED */
176156319Sdeischen	{DUAL_ENTRY(_pthread_attr_setschedparam)},	/* PJT_ATTR_SETSCHEDPARAM */
177156319Sdeischen	{DUAL_ENTRY(_pthread_attr_setschedpolicy)},	/* PJT_ATTR_SETSCHEDPOLICY */
178156319Sdeischen	{DUAL_ENTRY(_pthread_attr_setscope)},	/* PJT_ATTR_SETSCOPE */
179156319Sdeischen	{DUAL_ENTRY(_pthread_attr_setstackaddr)},	/* PJT_ATTR_SETSTACKADDR */
180156319Sdeischen	{DUAL_ENTRY(_pthread_attr_setstacksize)},	/* PJT_ATTR_SETSTACKSIZE */
181156319Sdeischen	{DUAL_ENTRY(_pthread_cancel)},	/* PJT_CANCEL */
182156319Sdeischen	{DUAL_ENTRY(_pthread_cleanup_pop)},	/* PJT_CLEANUP_POP */
183156319Sdeischen	{DUAL_ENTRY(_pthread_cleanup_push)},	/* PJT_CLEANUP_PUSH */
184113658Sdeischen	{DUAL_ENTRY(_pthread_cond_broadcast)},	/* PJT_COND_BROADCAST */
185113658Sdeischen	{DUAL_ENTRY(_pthread_cond_destroy)},	/* PJT_COND_DESTROY */
186113658Sdeischen	{DUAL_ENTRY(_pthread_cond_init)},	/* PJT_COND_INIT */
187113658Sdeischen	{DUAL_ENTRY(_pthread_cond_signal)},	/* PJT_COND_SIGNAL */
188156319Sdeischen	{DUAL_ENTRY(_pthread_cond_timedwait)},	/* PJT_COND_TIMEDWAIT */
189113658Sdeischen	{(pthread_func_t)__pthread_cond_wait,
190113658Sdeischen	 (pthread_func_t)_pthread_cond_wait},	/* PJT_COND_WAIT */
191156319Sdeischen	{DUAL_ENTRY(_pthread_detach)},	/* PJT_DETACH */
192156319Sdeischen	{DUAL_ENTRY(_pthread_equal)},	/* PJT_EQUAL */
193156319Sdeischen	{DUAL_ENTRY(_pthread_exit)},	/* PJT_EXIT */
194113658Sdeischen	{DUAL_ENTRY(_pthread_getspecific)},	/* PJT_GETSPECIFIC */
195156319Sdeischen	{DUAL_ENTRY(_pthread_join)},	/* PJT_JOIN */
196113658Sdeischen	{DUAL_ENTRY(_pthread_key_create)},	/* PJT_KEY_CREATE */
197113658Sdeischen	{DUAL_ENTRY(_pthread_key_delete)},	/* PJT_KEY_DELETE*/
198156319Sdeischen	{DUAL_ENTRY(_pthread_kill)},	/* PJT_KILL */
199113658Sdeischen	{DUAL_ENTRY(_pthread_main_np)},		/* PJT_MAIN_NP */
200156319Sdeischen	{DUAL_ENTRY(_pthread_mutexattr_destroy)}, /* PJT_MUTEXATTR_DESTROY */
201156319Sdeischen	{DUAL_ENTRY(_pthread_mutexattr_init)},	/* PJT_MUTEXATTR_INIT */
202156319Sdeischen	{DUAL_ENTRY(_pthread_mutexattr_settype)}, /* PJT_MUTEXATTR_SETTYPE */
203113658Sdeischen	{DUAL_ENTRY(_pthread_mutex_destroy)},	/* PJT_MUTEX_DESTROY */
204113658Sdeischen	{DUAL_ENTRY(_pthread_mutex_init)},	/* PJT_MUTEX_INIT */
205113658Sdeischen	{(pthread_func_t)__pthread_mutex_lock,
206113658Sdeischen	 (pthread_func_t)_pthread_mutex_lock},	/* PJT_MUTEX_LOCK */
207113658Sdeischen	{(pthread_func_t)__pthread_mutex_trylock,
208113658Sdeischen	 (pthread_func_t)_pthread_mutex_trylock},/* PJT_MUTEX_TRYLOCK */
209113658Sdeischen	{DUAL_ENTRY(_pthread_mutex_unlock)},	/* PJT_MUTEX_UNLOCK */
210113658Sdeischen	{DUAL_ENTRY(_pthread_once)},		/* PJT_ONCE */
211113658Sdeischen	{DUAL_ENTRY(_pthread_rwlock_destroy)},	/* PJT_RWLOCK_DESTROY */
212113658Sdeischen	{DUAL_ENTRY(_pthread_rwlock_init)},	/* PJT_RWLOCK_INIT */
213113658Sdeischen	{DUAL_ENTRY(_pthread_rwlock_rdlock)},	/* PJT_RWLOCK_RDLOCK */
214113658Sdeischen	{DUAL_ENTRY(_pthread_rwlock_tryrdlock)},/* PJT_RWLOCK_TRYRDLOCK */
215113658Sdeischen	{DUAL_ENTRY(_pthread_rwlock_trywrlock)},/* PJT_RWLOCK_TRYWRLOCK */
216113658Sdeischen	{DUAL_ENTRY(_pthread_rwlock_unlock)},	/* PJT_RWLOCK_UNLOCK */
217113658Sdeischen	{DUAL_ENTRY(_pthread_rwlock_wrlock)},	/* PJT_RWLOCK_WRLOCK */
218113658Sdeischen	{DUAL_ENTRY(_pthread_self)},		/* PJT_SELF */
219156319Sdeischen	{DUAL_ENTRY(_pthread_setcancelstate)},	/* PJT_SETCANCELSTATE */
220156319Sdeischen	{DUAL_ENTRY(_pthread_setcanceltype)},	/* PJT_SETCANCELTYPE */
221113658Sdeischen	{DUAL_ENTRY(_pthread_setspecific)},	/* PJT_SETSPECIFIC */
222156319Sdeischen	{DUAL_ENTRY(_pthread_sigmask)},		/* PJT_SIGMASK */
223156319Sdeischen	{DUAL_ENTRY(_pthread_testcancel)}	/* PJT_TESTCANCEL */
224113658Sdeischen};
225113658Sdeischen
226113658Sdeischenstatic int	init_once = 0;
227113658Sdeischen
22822315Sjulian/*
229113658Sdeischen * Threaded process initialization.
230113658Sdeischen *
231113658Sdeischen * This is only called under two conditions:
232113658Sdeischen *
233113658Sdeischen *   1) Some thread routines have detected that the library hasn't yet
234113658Sdeischen *      been initialized (_thr_initial == NULL && curthread == NULL), or
235113658Sdeischen *
236113658Sdeischen *   2) An explicit call to reinitialize after a fork (indicated
237113658Sdeischen *      by curthread != NULL)
23822315Sjulian */
23913546Sjulianvoid
240113658Sdeischen_libpthread_init(struct pthread *curthread)
24113546Sjulian{
242113658Sdeischen	int fd;
24396501Salfred
244111035Smini	/* Check if this function has already been called: */
245113658Sdeischen	if ((_thr_initial != NULL) && (curthread == NULL))
246113658Sdeischen		/* Only initialize the threaded application once. */
247111035Smini		return;
248111035Smini
24938208Sjb	/*
25071581Sdeischen	 * Make gcc quiescent about {,libgcc_}references not being
25170702Sobrien	 * referenced:
25270702Sobrien	 */
25371581Sdeischen	if ((references[0] == NULL) || (libgcc_references[0] == NULL))
25471581Sdeischen		PANIC("Failed loading mandatory references in _thread_init");
25570702Sobrien
256134115Sdavidxu	/* Pull debug symbols in for static binary */
257134115Sdavidxu	_thread_state_running = PS_RUNNING;
258134115Sdavidxu
25970702Sobrien	/*
260113658Sdeischen	 * Check the size of the jump table to make sure it is preset
261113658Sdeischen	 * with the correct number of entries.
262113658Sdeischen	 */
263113658Sdeischen	if (sizeof(jmp_table) != (sizeof(pthread_func_t) * PJT_MAX * 2))
264113658Sdeischen		PANIC("Thread jump table not properly initialized");
265113658Sdeischen	memcpy(__thr_jtable, jmp_table, sizeof(jmp_table));
266113658Sdeischen
267113658Sdeischen	/*
26838208Sjb	 * Check for the special case of this process running as
26938208Sjb	 * or in place of init as pid = 1:
27038208Sjb	 */
271113658Sdeischen	if ((_thr_pid = getpid()) == 1) {
27238208Sjb		/*
27338208Sjb		 * Setup a new session for this process which is
27438208Sjb		 * assumed to be running as root.
27538208Sjb		 */
27648569Sjasone		if (setsid() == -1)
27738208Sjb			PANIC("Can't set session ID");
27848569Sjasone		if (revoke(_PATH_CONSOLE) != 0)
27938208Sjb			PANIC("Can't revoke console");
28071581Sdeischen		if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0)
28138208Sjb			PANIC("Can't open console");
28248569Sjasone		if (setlogin("root") == -1)
28338208Sjb			PANIC("Can't set login to root");
28497204Sdeischen		if (__sys_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1)
28538208Sjb			PANIC("Can't set controlling terminal");
28638208Sjb	}
28738208Sjb
288113658Sdeischen	/* Initialize pthread private data. */
289113658Sdeischen	init_private();
290113658Sdeischen	_kse_init();
29113546Sjulian
292113658Sdeischen	/* Initialize the initial kse and kseg. */
293133563Sdeischen	_kse_initial = _kse_alloc(NULL, _thread_scope_system > 0);
294113658Sdeischen	if (_kse_initial == NULL)
295113658Sdeischen		PANIC("Can't allocate initial kse.");
296113658Sdeischen	_kse_initial->k_kseg = _kseg_alloc(NULL);
297113658Sdeischen	if (_kse_initial->k_kseg == NULL)
298113658Sdeischen		PANIC("Can't allocate initial kseg.");
299117706Sdavidxu	_kse_initial->k_kseg->kg_flags |= KGF_SINGLE_THREAD;
300113658Sdeischen	_kse_initial->k_schedq = &_kse_initial->k_kseg->kg_schedq;
30144963Sjb
302113870Sdeischen	TAILQ_INSERT_TAIL(&_kse_initial->k_kseg->kg_kseq, _kse_initial, k_kgqe);
303113870Sdeischen	_kse_initial->k_kseg->kg_ksecount = 1;
304113870Sdeischen
305113658Sdeischen	/* Set the initial thread. */
306113658Sdeischen	if (curthread == NULL) {
307113658Sdeischen		/* Create and initialize the initial thread. */
308113658Sdeischen		curthread = _thr_alloc(NULL);
309113658Sdeischen		if (curthread == NULL)
310113658Sdeischen			PANIC("Can't allocate initial thread");
311113658Sdeischen		_thr_initial = curthread;
312113658Sdeischen		init_main_thread(curthread);
313113658Sdeischen	} else {
31455222Sjasone		/*
315113658Sdeischen		 * The initial thread is the current thread.  It is
316113658Sdeischen		 * assumed that the current thread is already initialized
317113658Sdeischen		 * because it is left over from a fork().
31855222Sjasone		 */
319113658Sdeischen		_thr_initial = curthread;
320113658Sdeischen	}
321113661Sdeischen	_kse_initial->k_kseg->kg_threadcount = 0;
322113658Sdeischen	_thr_initial->kse = _kse_initial;
323113658Sdeischen	_thr_initial->kseg = _kse_initial->k_kseg;
324113658Sdeischen	_thr_initial->active = 1;
32555193Sdeischen
326113658Sdeischen	/*
327113658Sdeischen	 * Add the thread to the thread list and to the KSEG's thread
328113658Sdeischen         * queue.
329113658Sdeischen	 */
330113658Sdeischen	THR_LIST_ADD(_thr_initial);
331113661Sdeischen	KSEG_THRQ_ADD(_kse_initial->k_kseg, _thr_initial);
33256277Sjasone
333113658Sdeischen	/* Setup the KSE/thread specific data for the current KSE/thread. */
334113658Sdeischen	_thr_initial->kse->k_curthread = _thr_initial;
335118510Sdeischen	_kcb_set(_thr_initial->kse->k_kcb);
336118510Sdeischen	_tcb_set(_thr_initial->kse->k_kcb, _thr_initial->tcb);
337113658Sdeischen	_thr_initial->kse->k_flags |= KF_INITIALIZED;
338119063Sdavidxu
339119063Sdavidxu	_thr_signal_init();
340119063Sdavidxu	_kse_critical_leave(&_thr_initial->tcb->tcb_tmbx);
341132121Sdavidxu	/*
342132121Sdavidxu	 * activate threaded mode as soon as possible if we are
343132121Sdavidxu	 * being debugged
344132121Sdavidxu	 */
345132121Sdavidxu	if (_libkse_debug)
346132121Sdavidxu		_kse_setthreaded(1);
347113658Sdeischen}
34856277Sjasone
349113658Sdeischen/*
350113658Sdeischen * This function and pthread_create() do a lot of the same things.
351113658Sdeischen * It'd be nice to consolidate the common stuff in one place.
352113658Sdeischen */
353113658Sdeischenstatic void
354113658Sdeischeninit_main_thread(struct pthread *thread)
355113658Sdeischen{
356113658Sdeischen	/* Setup the thread attributes. */
357113658Sdeischen	thread->attr = _pthread_attr_default;
358117706Sdavidxu	thread->attr.flags |= PTHREAD_SCOPE_SYSTEM;
359113658Sdeischen	/*
360113658Sdeischen	 * Set up the thread stack.
361113658Sdeischen	 *
362113658Sdeischen	 * Create a red zone below the main stack.  All other stacks
363113658Sdeischen	 * are constrained to a maximum size by the parameters
364113658Sdeischen	 * passed to mmap(), but this stack is only limited by
365113658Sdeischen	 * resource limits, so this stack needs an explicitly mapped
366113658Sdeischen	 * red zone to protect the thread stack that is just beyond.
367113658Sdeischen	 */
368174112Sdeischen	if (mmap((void *)((uintptr_t)_usrstack - _thr_stack_initial -
369174112Sdeischen	    _thr_guard_default), _thr_guard_default, 0, MAP_ANON,
370113658Sdeischen	    -1, 0) == MAP_FAILED)
371113658Sdeischen		PANIC("Cannot allocate red zone for initial thread");
37253812Salfred
373113658Sdeischen	/*
374113658Sdeischen	 * Mark the stack as an application supplied stack so that it
375113658Sdeischen	 * isn't deallocated.
376113658Sdeischen	 *
377113658Sdeischen	 * XXX - I'm not sure it would hurt anything to deallocate
378113658Sdeischen	 *       the main thread stack because deallocation doesn't
379113658Sdeischen	 *       actually free() it; it just puts it in the free
380113658Sdeischen	 *       stack queue for later reuse.
381113658Sdeischen	 */
382174112Sdeischen	thread->attr.stackaddr_attr = (void *)((uintptr_t)_usrstack -
383174112Sdeischen	     _thr_stack_initial);
384141822Sdeischen	thread->attr.stacksize_attr = _thr_stack_initial;
385113658Sdeischen	thread->attr.guardsize_attr = _thr_guard_default;
386113658Sdeischen	thread->attr.flags |= THR_STACK_USER;
387103419Smini
388113658Sdeischen	/*
389113658Sdeischen	 * Write a magic value to the thread structure
390113658Sdeischen	 * to help identify valid ones:
391113658Sdeischen	 */
392113658Sdeischen	thread->magic = THR_MAGIC;
39313546Sjulian
394113658Sdeischen	thread->slice_usec = -1;
395113658Sdeischen	thread->cancelflags = PTHREAD_CANCEL_ENABLE | PTHREAD_CANCEL_DEFERRED;
396113658Sdeischen	thread->name = strdup("initial thread");
39713546Sjulian
398113658Sdeischen	/* Initialize the thread for signals: */
399116977Sdavidxu	SIGEMPTYSET(thread->sigmask);
40071581Sdeischen
401113658Sdeischen	/*
402113658Sdeischen	 * Set up the thread mailbox.  The threads saved context
403113658Sdeischen	 * is also in the mailbox.
404113658Sdeischen	 */
405118510Sdeischen	thread->tcb->tcb_tmbx.tm_udata = thread;
406118510Sdeischen	thread->tcb->tcb_tmbx.tm_context.uc_stack.ss_size =
407118510Sdeischen	    thread->attr.stacksize_attr;
408118510Sdeischen	thread->tcb->tcb_tmbx.tm_context.uc_stack.ss_sp =
409118510Sdeischen	    thread->attr.stackaddr_attr;
41013546Sjulian
411113658Sdeischen	/* Default the priority of the initial thread: */
412113658Sdeischen	thread->base_priority = THR_DEFAULT_PRIORITY;
413113658Sdeischen	thread->active_priority = THR_DEFAULT_PRIORITY;
414113658Sdeischen	thread->inherited_priority = 0;
41544963Sjb
416113658Sdeischen	/* Initialize the mutex queue: */
417113658Sdeischen	TAILQ_INIT(&thread->mutexq);
41856236Sdeischen
419113658Sdeischen	/* Initialize hooks in the thread structure: */
420113658Sdeischen	thread->specific = NULL;
421113658Sdeischen	thread->cleanup = NULL;
422113658Sdeischen	thread->flags = 0;
423139023Sdeischen	thread->sigbackout = NULL;
424113658Sdeischen	thread->continuation = NULL;
42513546Sjulian
426113658Sdeischen	thread->state = PS_RUNNING;
427113658Sdeischen	thread->uniqueid = 0;
428113658Sdeischen}
429111035Smini
430113658Sdeischenstatic void
431113658Sdeischeninit_private(void)
432113658Sdeischen{
433113658Sdeischen	struct clockinfo clockinfo;
434113658Sdeischen	size_t len;
435113658Sdeischen	int mib[2];
436111035Smini
437113658Sdeischen	/*
438113658Sdeischen	 * Avoid reinitializing some things if they don't need to be,
439113658Sdeischen	 * e.g. after a fork().
440113658Sdeischen	 */
441113658Sdeischen	if (init_once == 0) {
442113658Sdeischen		/* Find the stack top */
443113658Sdeischen		mib[0] = CTL_KERN;
444113658Sdeischen		mib[1] = KERN_USRSTACK;
445113658Sdeischen		len = sizeof (_usrstack);
446113658Sdeischen		if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) == -1)
447113658Sdeischen			PANIC("Cannot get kern.usrstack from sysctl");
44848046Sjb		/* Get the kernel clockrate: */
44948046Sjb		mib[0] = CTL_KERN;
45048046Sjb		mib[1] = KERN_CLOCKRATE;
45148046Sjb		len = sizeof (struct clockinfo);
45248046Sjb		if (sysctl(mib, 2, &clockinfo, &len, NULL, 0) == 0)
453142047Sdeischen			_clock_res_usec = 1000000 / clockinfo.stathz;
454113658Sdeischen		else
455113658Sdeischen			_clock_res_usec = CLOCK_RES_USEC;
45648046Sjb
457113658Sdeischen		_thr_page_size = getpagesize();
458113658Sdeischen		_thr_guard_default = _thr_page_size;
459141822Sdeischen		if (sizeof(void *) == 8) {
460141822Sdeischen			_thr_stack_default = THR_STACK64_DEFAULT;
461141822Sdeischen			_thr_stack_initial = THR_STACK64_INITIAL;
462141822Sdeischen		}
463141822Sdeischen		else {
464141822Sdeischen			_thr_stack_default = THR_STACK32_DEFAULT;
465141822Sdeischen			_thr_stack_initial = THR_STACK32_INITIAL;
466141822Sdeischen		}
467141949Sdeischen		_pthread_attr_default.guardsize_attr = _thr_guard_default;
468141949Sdeischen		_pthread_attr_default.stacksize_attr = _thr_stack_default;
469150499Sbrian		TAILQ_INIT(&_thr_atfork_list);
470113658Sdeischen		init_once = 1;	/* Don't do this again. */
471113658Sdeischen	} else {
472113658Sdeischen		/*
473113658Sdeischen		 * Destroy the locks before creating them.  We don't
474113658Sdeischen		 * know what state they are in so it is better to just
475113658Sdeischen		 * recreate them.
476113658Sdeischen		 */
477113658Sdeischen		_lock_destroy(&_thread_signal_lock);
478113658Sdeischen		_lock_destroy(&_mutex_static_lock);
479113658Sdeischen		_lock_destroy(&_rwlock_static_lock);
480113658Sdeischen		_lock_destroy(&_keytable_lock);
48113546Sjulian	}
48233292Sjulian
483113658Sdeischen	/* Initialize everything else. */
484113658Sdeischen	TAILQ_INIT(&_thread_list);
485113658Sdeischen	TAILQ_INIT(&_thread_gc_list);
486122075Sdeischen	_pthread_mutex_init(&_thr_atfork_mutex, NULL);
48713546Sjulian
488113658Sdeischen	/*
489113658Sdeischen	 * Initialize the lock for temporary installation of signal
490113658Sdeischen	 * handlers (to support sigwait() semantics) and for the
491113658Sdeischen	 * process signal mask and pending signal sets.
492113658Sdeischen	 */
493113658Sdeischen	if (_lock_init(&_thread_signal_lock, LCK_ADAPTIVE,
494173967Sjasone	    _kse_lock_wait, _kse_lock_wakeup, calloc) != 0)
495113658Sdeischen		PANIC("Cannot initialize _thread_signal_lock");
496113658Sdeischen	if (_lock_init(&_mutex_static_lock, LCK_ADAPTIVE,
497173967Sjasone	    _thr_lock_wait, _thr_lock_wakeup, calloc) != 0)
498113658Sdeischen		PANIC("Cannot initialize mutex static init lock");
499113658Sdeischen	if (_lock_init(&_rwlock_static_lock, LCK_ADAPTIVE,
500173967Sjasone	    _thr_lock_wait, _thr_lock_wakeup, calloc) != 0)
501113658Sdeischen		PANIC("Cannot initialize rwlock static init lock");
502113658Sdeischen	if (_lock_init(&_keytable_lock, LCK_ADAPTIVE,
503173967Sjasone	    _thr_lock_wait, _thr_lock_wakeup, calloc) != 0)
504113658Sdeischen		PANIC("Cannot initialize thread specific keytable lock");
505115381Sdeischen	_thr_spinlock_init();
506113658Sdeischen
507113658Sdeischen	/* Clear pending signals and get the process signal mask. */
508116977Sdavidxu	SIGEMPTYSET(_thr_proc_sigpending);
509113658Sdeischen
510133269Sdeischen	/* Are we in M:N mode (default) or 1:1 mode? */
511133269Sdeischen#ifdef SYSTEM_SCOPE_ONLY
512133269Sdeischen	_thread_scope_system = 1;
513133269Sdeischen#else
514133269Sdeischen	if (getenv("LIBPTHREAD_SYSTEM_SCOPE") != NULL)
515133269Sdeischen		_thread_scope_system = 1;
516133563Sdeischen	else if (getenv("LIBPTHREAD_PROCESS_SCOPE") != NULL)
517133563Sdeischen		_thread_scope_system = -1;
518133269Sdeischen#endif
519156330Sdeischen	if (getenv("LIBPTHREAD_DEBUG") != NULL)
520156330Sdeischen		_thr_debug_flags |= DBG_INFO_DUMP;
521133269Sdeischen
522113658Sdeischen	/*
523113658Sdeischen	 * _thread_list_lock and _kse_count are initialized
524113658Sdeischen	 * by _kse_init()
525113658Sdeischen	 */
52613546Sjulian}
527