thr_init.c revision 277317
1214501Srpaulo/*
2214501Srpaulo * Copyright (c) 2003 Daniel M. Eischen <deischen@freebsd.org>
3214501Srpaulo * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
4214501Srpaulo * All rights reserved.
5252726Srpaulo *
6252726Srpaulo * Redistribution and use in source and binary forms, with or without
7214501Srpaulo * modification, are permitted provided that the following conditions
8214501Srpaulo * are met:
9214501Srpaulo * 1. Redistributions of source code must retain the above copyright
10214501Srpaulo *    notice, this list of conditions and the following disclaimer.
11214501Srpaulo * 2. Redistributions in binary form must reproduce the above copyright
12214501Srpaulo *    notice, this list of conditions and the following disclaimer in the
13214501Srpaulo *    documentation and/or other materials provided with the distribution.
14214501Srpaulo * 3. All advertising materials mentioning features or use of this software
15214501Srpaulo *    must display the following acknowledgement:
16252726Srpaulo *	This product includes software developed by John Birrell.
17214501Srpaulo * 4. Neither the name of the author nor the names of any co-contributors
18214501Srpaulo *    may be used to endorse or promote products derived from this software
19214501Srpaulo *    without specific prior written permission.
20214501Srpaulo *
21214501Srpaulo * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
22214501Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23214501Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24214501Srpaulo * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25214501Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26214501Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27214501Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28214501Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29214501Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30214501Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31214501Srpaulo * SUCH DAMAGE.
32214501Srpaulo *
33214501Srpaulo * $FreeBSD: stable/10/lib/libthr/thread/thr_init.c 277317 2015-01-18 11:54:20Z kib $
34214501Srpaulo */
35214501Srpaulo
36214501Srpaulo#include "namespace.h"
37214501Srpaulo#include <sys/types.h>
38214501Srpaulo#include <sys/signalvar.h>
39214501Srpaulo#include <sys/ioctl.h>
40214501Srpaulo#include <sys/link_elf.h>
41214501Srpaulo#include <sys/resource.h>
42214501Srpaulo#include <sys/sysctl.h>
43214501Srpaulo#include <sys/ttycom.h>
44214501Srpaulo#include <sys/mman.h>
45214501Srpaulo#include <sys/rtprio.h>
46214501Srpaulo#include <errno.h>
47214501Srpaulo#include <fcntl.h>
48214501Srpaulo#include <paths.h>
49214501Srpaulo#include <pthread.h>
50214501Srpaulo#include <pthread_np.h>
51214501Srpaulo#include <signal.h>
52214501Srpaulo#include <stdlib.h>
53214501Srpaulo#include <string.h>
54214501Srpaulo#include <time.h>
55214501Srpaulo#include <unistd.h>
56214501Srpaulo#include "un-namespace.h"
57214501Srpaulo
58214501Srpaulo#include "libc_private.h"
59214501Srpaulo#include "thr_private.h"
60214501Srpaulo
61214501Srpaulochar		*_usrstack;
62214501Srpaulostruct pthread	*_thr_initial;
63214501Srpauloint		_libthr_debug;
64252726Srpauloint		_thread_event_mask;
65214501Srpaulostruct pthread	*_thread_last_event;
66214501Srpaulopthreadlist	_thread_list = TAILQ_HEAD_INITIALIZER(_thread_list);
67214501Srpaulopthreadlist 	_thread_gc_list = TAILQ_HEAD_INITIALIZER(_thread_gc_list);
68214501Srpauloint		_thread_active_threads = 1;
69214501Srpauloatfork_head	_thr_atfork_list = TAILQ_HEAD_INITIALIZER(_thr_atfork_list);
70214501Srpaulostruct urwlock	_thr_atfork_lock = DEFAULT_URWLOCK;
71214501Srpaulo
72214501Srpaulostruct pthread_prio	_thr_priorities[3] = {
73214501Srpaulo	{RTP_PRIO_MIN,  RTP_PRIO_MAX, 0}, /* FIFO */
74214501Srpaulo	{0, 0, 63}, /* OTHER */
75214501Srpaulo	{RTP_PRIO_MIN, RTP_PRIO_MAX, 0}  /* RR */
76214501Srpaulo};
77214501Srpaulo
78214501Srpaulostruct pthread_attr _pthread_attr_default = {
79214501Srpaulo	.sched_policy = SCHED_OTHER,
80214501Srpaulo	.sched_inherit = PTHREAD_INHERIT_SCHED,
81214501Srpaulo	.prio = 0,
82214501Srpaulo	.suspend = THR_CREATE_RUNNING,
83214501Srpaulo	.flags = PTHREAD_SCOPE_SYSTEM,
84214501Srpaulo	.stackaddr_attr = NULL,
85214501Srpaulo	.stacksize_attr = THR_STACK_DEFAULT,
86214501Srpaulo	.guardsize_attr = 0,
87214501Srpaulo	.cpusetsize = 0,
88214501Srpaulo	.cpuset = NULL
89214501Srpaulo};
90214501Srpaulo
91214501Srpaulostruct pthread_mutex_attr _pthread_mutexattr_default = {
92214501Srpaulo	.m_type = PTHREAD_MUTEX_DEFAULT,
93214501Srpaulo	.m_protocol = PTHREAD_PRIO_NONE,
94214501Srpaulo	.m_ceiling = 0
95214501Srpaulo};
96214501Srpaulo
97214501Srpaulostruct pthread_mutex_attr _pthread_mutexattr_adaptive_default = {
98214501Srpaulo	.m_type = PTHREAD_MUTEX_ADAPTIVE_NP,
99214501Srpaulo	.m_protocol = PTHREAD_PRIO_NONE,
100214501Srpaulo	.m_ceiling = 0
101214501Srpaulo};
102214501Srpaulo
103214501Srpaulo/* Default condition variable attributes: */
104214501Srpaulostruct pthread_cond_attr _pthread_condattr_default = {
105214501Srpaulo	.c_pshared = PTHREAD_PROCESS_PRIVATE,
106214501Srpaulo	.c_clockid = CLOCK_REALTIME
107214501Srpaulo};
108214501Srpaulo
109214501Srpaulopid_t		_thr_pid;
110214501Srpauloint		_thr_is_smp = 0;
111214501Srpaulosize_t		_thr_guard_default;
112214501Srpaulosize_t		_thr_stack_default = THR_STACK_DEFAULT;
113214501Srpaulosize_t		_thr_stack_initial = THR_STACK_INITIAL;
114214501Srpauloint		_thr_page_size;
115214501Srpauloint		_thr_spinloops;
116214501Srpauloint		_thr_yieldloops;
117214501Srpauloint		_thr_queuefifo = 4;
118214501Srpauloint		_gc_count;
119214501Srpaulostruct umutex	_mutex_static_lock = DEFAULT_UMUTEX;
120214501Srpaulostruct umutex	_cond_static_lock = DEFAULT_UMUTEX;
121214501Srpaulostruct umutex	_rwlock_static_lock = DEFAULT_UMUTEX;
122252726Srpaulostruct umutex	_keytable_lock = DEFAULT_UMUTEX;
123252726Srpaulostruct urwlock	_thr_list_lock = DEFAULT_URWLOCK;
124214501Srpaulostruct umutex	_thr_event_lock = DEFAULT_UMUTEX;
125252726Srpaulostruct umutex	_suspend_all_lock = DEFAULT_UMUTEX;
126214501Srpaulostruct pthread	*_single_thread;
127214501Srpauloint		_suspend_all_cycle;
128214501Srpauloint		_suspend_all_waiters;
129214501Srpaulo
130214501Srpauloint	__pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
131214501Srpauloint	__pthread_mutex_lock(pthread_mutex_t *);
132214501Srpauloint	__pthread_mutex_trylock(pthread_mutex_t *);
133214501Srpaulovoid	_thread_init_hack(void) __attribute__ ((constructor));
134214501Srpaulo
135214501Srpaulostatic void init_private(void);
136214501Srpaulostatic void init_main_thread(struct pthread *thread);
137214501Srpaulo
138214501Srpaulo/*
139214501Srpaulo * All weak references used within libc should be in this table.
140214501Srpaulo * This is so that static libraries will work.
141214501Srpaulo */
142214501Srpaulo
143214501SrpauloSTATIC_LIB_REQUIRE(_fork);
144214501SrpauloSTATIC_LIB_REQUIRE(_pthread_getspecific);
145214501SrpauloSTATIC_LIB_REQUIRE(_pthread_key_create);
146214501SrpauloSTATIC_LIB_REQUIRE(_pthread_key_delete);
147214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutex_destroy);
148214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutex_init);
149214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutex_lock);
150214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutex_trylock);
151214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutex_unlock);
152214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutexattr_init);
153214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutexattr_destroy);
154214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutexattr_settype);
155214501SrpauloSTATIC_LIB_REQUIRE(_pthread_once);
156214501SrpauloSTATIC_LIB_REQUIRE(_pthread_setspecific);
157214501SrpauloSTATIC_LIB_REQUIRE(_raise);
158214501SrpauloSTATIC_LIB_REQUIRE(_sem_destroy);
159214501SrpauloSTATIC_LIB_REQUIRE(_sem_getvalue);
160214501SrpauloSTATIC_LIB_REQUIRE(_sem_init);
161214501SrpauloSTATIC_LIB_REQUIRE(_sem_post);
162214501SrpauloSTATIC_LIB_REQUIRE(_sem_timedwait);
163214501SrpauloSTATIC_LIB_REQUIRE(_sem_trywait);
164214501SrpauloSTATIC_LIB_REQUIRE(_sem_wait);
165214501SrpauloSTATIC_LIB_REQUIRE(_sigaction);
166214501SrpauloSTATIC_LIB_REQUIRE(_sigprocmask);
167214501SrpauloSTATIC_LIB_REQUIRE(_sigsuspend);
168214501SrpauloSTATIC_LIB_REQUIRE(_sigtimedwait);
169214501SrpauloSTATIC_LIB_REQUIRE(_sigwait);
170214501SrpauloSTATIC_LIB_REQUIRE(_sigwaitinfo);
171214501SrpauloSTATIC_LIB_REQUIRE(_spinlock);
172214501SrpauloSTATIC_LIB_REQUIRE(_spinlock_debug);
173214501SrpauloSTATIC_LIB_REQUIRE(_spinunlock);
174214501SrpauloSTATIC_LIB_REQUIRE(_thread_init_hack);
175214501Srpaulo
176214501Srpaulo/*
177214501Srpaulo * These are needed when linking statically.  All references within
178214501Srpaulo * libgcc (and in the future libc) to these routines are weak, but
179214501Srpaulo * if they are not (strongly) referenced by the application or other
180214501Srpaulo * libraries, then the actual functions will not be loaded.
181214501Srpaulo */
182214501SrpauloSTATIC_LIB_REQUIRE(_pthread_once);
183214501SrpauloSTATIC_LIB_REQUIRE(_pthread_key_create);
184214501SrpauloSTATIC_LIB_REQUIRE(_pthread_key_delete);
185214501SrpauloSTATIC_LIB_REQUIRE(_pthread_getspecific);
186214501SrpauloSTATIC_LIB_REQUIRE(_pthread_setspecific);
187214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutex_init);
188214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutex_destroy);
189214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutex_lock);
190214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutex_trylock);
191214501SrpauloSTATIC_LIB_REQUIRE(_pthread_mutex_unlock);
192214501SrpauloSTATIC_LIB_REQUIRE(_pthread_create);
193214501Srpaulo
194214501Srpaulo/* Pull in all symbols required by libthread_db */
195214501SrpauloSTATIC_LIB_REQUIRE(_thread_state_running);
196214501Srpaulo
197214501Srpaulo#define	DUAL_ENTRY(entry)	\
198214501Srpaulo	(pthread_func_t)entry, (pthread_func_t)entry
199214501Srpaulo
200214501Srpaulostatic pthread_func_t jmp_table[][2] = {
201214501Srpaulo	{DUAL_ENTRY(_pthread_atfork)},	/* PJT_ATFORK */
202214501Srpaulo	{DUAL_ENTRY(_pthread_attr_destroy)},	/* PJT_ATTR_DESTROY */
203214501Srpaulo	{DUAL_ENTRY(_pthread_attr_getdetachstate)},	/* PJT_ATTR_GETDETACHSTATE */
204214501Srpaulo	{DUAL_ENTRY(_pthread_attr_getguardsize)},	/* PJT_ATTR_GETGUARDSIZE */
205214501Srpaulo	{DUAL_ENTRY(_pthread_attr_getinheritsched)},	/* PJT_ATTR_GETINHERITSCHED */
206214501Srpaulo	{DUAL_ENTRY(_pthread_attr_getschedparam)},	/* PJT_ATTR_GETSCHEDPARAM */
207214501Srpaulo	{DUAL_ENTRY(_pthread_attr_getschedpolicy)},	/* PJT_ATTR_GETSCHEDPOLICY */
208214501Srpaulo	{DUAL_ENTRY(_pthread_attr_getscope)},	/* PJT_ATTR_GETSCOPE */
209214501Srpaulo	{DUAL_ENTRY(_pthread_attr_getstackaddr)},	/* PJT_ATTR_GETSTACKADDR */
210214501Srpaulo	{DUAL_ENTRY(_pthread_attr_getstacksize)},	/* PJT_ATTR_GETSTACKSIZE */
211214501Srpaulo	{DUAL_ENTRY(_pthread_attr_init)},	/* PJT_ATTR_INIT */
212214501Srpaulo	{DUAL_ENTRY(_pthread_attr_setdetachstate)},	/* PJT_ATTR_SETDETACHSTATE */
213214501Srpaulo	{DUAL_ENTRY(_pthread_attr_setguardsize)},	/* PJT_ATTR_SETGUARDSIZE */
214214501Srpaulo	{DUAL_ENTRY(_pthread_attr_setinheritsched)},	/* PJT_ATTR_SETINHERITSCHED */
215214501Srpaulo	{DUAL_ENTRY(_pthread_attr_setschedparam)},	/* PJT_ATTR_SETSCHEDPARAM */
216214501Srpaulo	{DUAL_ENTRY(_pthread_attr_setschedpolicy)},	/* PJT_ATTR_SETSCHEDPOLICY */
217214501Srpaulo	{DUAL_ENTRY(_pthread_attr_setscope)},	/* PJT_ATTR_SETSCOPE */
218214501Srpaulo	{DUAL_ENTRY(_pthread_attr_setstackaddr)},	/* PJT_ATTR_SETSTACKADDR */
219214501Srpaulo	{DUAL_ENTRY(_pthread_attr_setstacksize)},	/* PJT_ATTR_SETSTACKSIZE */
220214501Srpaulo	{DUAL_ENTRY(_pthread_cancel)},	/* PJT_CANCEL */
221214501Srpaulo	{DUAL_ENTRY(_pthread_cleanup_pop)},	/* PJT_CLEANUP_POP */
222214501Srpaulo	{DUAL_ENTRY(_pthread_cleanup_push)},	/* PJT_CLEANUP_PUSH */
223214501Srpaulo	{DUAL_ENTRY(_pthread_cond_broadcast)},	/* PJT_COND_BROADCAST */
224214501Srpaulo	{DUAL_ENTRY(_pthread_cond_destroy)},	/* PJT_COND_DESTROY */
225214501Srpaulo	{DUAL_ENTRY(_pthread_cond_init)},	/* PJT_COND_INIT */
226214501Srpaulo	{DUAL_ENTRY(_pthread_cond_signal)},	/* PJT_COND_SIGNAL */
227214501Srpaulo	{DUAL_ENTRY(_pthread_cond_timedwait)},	/* PJT_COND_TIMEDWAIT */
228214501Srpaulo	{(pthread_func_t)__pthread_cond_wait,
229214501Srpaulo	 (pthread_func_t)_pthread_cond_wait},	/* PJT_COND_WAIT */
230214501Srpaulo	{DUAL_ENTRY(_pthread_detach)},	/* PJT_DETACH */
231214501Srpaulo	{DUAL_ENTRY(_pthread_equal)},	/* PJT_EQUAL */
232214501Srpaulo	{DUAL_ENTRY(_pthread_exit)},	/* PJT_EXIT */
233214501Srpaulo	{DUAL_ENTRY(_pthread_getspecific)},	/* PJT_GETSPECIFIC */
234214501Srpaulo	{DUAL_ENTRY(_pthread_join)},	/* PJT_JOIN */
235214501Srpaulo	{DUAL_ENTRY(_pthread_key_create)},	/* PJT_KEY_CREATE */
236214501Srpaulo	{DUAL_ENTRY(_pthread_key_delete)},	/* PJT_KEY_DELETE*/
237214501Srpaulo	{DUAL_ENTRY(_pthread_kill)},	/* PJT_KILL */
238214501Srpaulo	{DUAL_ENTRY(_pthread_main_np)},		/* PJT_MAIN_NP */
239214501Srpaulo	{DUAL_ENTRY(_pthread_mutexattr_destroy)}, /* PJT_MUTEXATTR_DESTROY */
240214501Srpaulo	{DUAL_ENTRY(_pthread_mutexattr_init)},	/* PJT_MUTEXATTR_INIT */
241214501Srpaulo	{DUAL_ENTRY(_pthread_mutexattr_settype)}, /* PJT_MUTEXATTR_SETTYPE */
242214501Srpaulo	{DUAL_ENTRY(_pthread_mutex_destroy)},	/* PJT_MUTEX_DESTROY */
243214501Srpaulo	{DUAL_ENTRY(_pthread_mutex_init)},	/* PJT_MUTEX_INIT */
244214501Srpaulo	{(pthread_func_t)__pthread_mutex_lock,
245214501Srpaulo	 (pthread_func_t)_pthread_mutex_lock},	/* PJT_MUTEX_LOCK */
246214501Srpaulo	{(pthread_func_t)__pthread_mutex_trylock,
247214501Srpaulo	 (pthread_func_t)_pthread_mutex_trylock},/* PJT_MUTEX_TRYLOCK */
248214501Srpaulo	{DUAL_ENTRY(_pthread_mutex_unlock)},	/* PJT_MUTEX_UNLOCK */
249214501Srpaulo	{DUAL_ENTRY(_pthread_once)},		/* PJT_ONCE */
250214501Srpaulo	{DUAL_ENTRY(_pthread_rwlock_destroy)},	/* PJT_RWLOCK_DESTROY */
251214501Srpaulo	{DUAL_ENTRY(_pthread_rwlock_init)},	/* PJT_RWLOCK_INIT */
252214501Srpaulo	{DUAL_ENTRY(_pthread_rwlock_rdlock)},	/* PJT_RWLOCK_RDLOCK */
253214501Srpaulo	{DUAL_ENTRY(_pthread_rwlock_tryrdlock)},/* PJT_RWLOCK_TRYRDLOCK */
254214501Srpaulo	{DUAL_ENTRY(_pthread_rwlock_trywrlock)},/* PJT_RWLOCK_TRYWRLOCK */
255214501Srpaulo	{DUAL_ENTRY(_pthread_rwlock_unlock)},	/* PJT_RWLOCK_UNLOCK */
256214501Srpaulo	{DUAL_ENTRY(_pthread_rwlock_wrlock)},	/* PJT_RWLOCK_WRLOCK */
257214501Srpaulo	{DUAL_ENTRY(_pthread_self)},		/* PJT_SELF */
258214501Srpaulo	{DUAL_ENTRY(_pthread_setcancelstate)},	/* PJT_SETCANCELSTATE */
259214501Srpaulo	{DUAL_ENTRY(_pthread_setcanceltype)},	/* PJT_SETCANCELTYPE */
260214501Srpaulo	{DUAL_ENTRY(_pthread_setspecific)},	/* PJT_SETSPECIFIC */
261214501Srpaulo	{DUAL_ENTRY(_pthread_sigmask)},		/* PJT_SIGMASK */
262214501Srpaulo	{DUAL_ENTRY(_pthread_testcancel)},	/* PJT_TESTCANCEL */
263214501Srpaulo	{DUAL_ENTRY(__pthread_cleanup_pop_imp)},/* PJT_CLEANUP_POP_IMP */
264214501Srpaulo	{DUAL_ENTRY(__pthread_cleanup_push_imp)},/* PJT_CLEANUP_PUSH_IMP */
265214501Srpaulo	{DUAL_ENTRY(_pthread_cancel_enter)},	/* PJT_CANCEL_ENTER */
266214501Srpaulo	{DUAL_ENTRY(_pthread_cancel_leave)}		/* PJT_CANCEL_LEAVE */
267214501Srpaulo};
268214501Srpaulo
269214501Srpaulostatic int init_once = 0;
270214501Srpaulo
271214501Srpaulo/*
272214501Srpaulo * For the shared version of the threads library, the above is sufficient.
273214501Srpaulo * But for the archive version of the library, we need a little bit more.
274214501Srpaulo * Namely, we must arrange for this particular module to be pulled in from
275214501Srpaulo * the archive library at link time.  To accomplish that, we define and
276214501Srpaulo * initialize a variable, "_thread_autoinit_dummy_decl".  This variable is
277214501Srpaulo * referenced (as an extern) from libc/stdlib/exit.c. This will always
278214501Srpaulo * create a need for this module, ensuring that it is present in the
279214501Srpaulo * executable.
280214501Srpaulo */
281214501Srpauloextern int _thread_autoinit_dummy_decl;
282214501Srpauloint _thread_autoinit_dummy_decl = 0;
283214501Srpaulo
284214501Srpaulovoid
285214501Srpaulo_thread_init_hack(void)
286214501Srpaulo{
287214501Srpaulo
288214501Srpaulo	_libpthread_init(NULL);
289214501Srpaulo}
290214501Srpaulo
291214501Srpaulo
292214501Srpaulo/*
293214501Srpaulo * Threaded process initialization.
294214501Srpaulo *
295214501Srpaulo * This is only called under two conditions:
296214501Srpaulo *
297214501Srpaulo *   1) Some thread routines have detected that the library hasn't yet
298214501Srpaulo *      been initialized (_thr_initial == NULL && curthread == NULL), or
299214501Srpaulo *
300214501Srpaulo *   2) An explicit call to reinitialize after a fork (indicated
301214501Srpaulo *      by curthread != NULL)
302214501Srpaulo */
303214501Srpaulovoid
304214501Srpaulo_libpthread_init(struct pthread *curthread)
305214501Srpaulo{
306214501Srpaulo	int fd, first, dlopened;
307214501Srpaulo
308214501Srpaulo	/* Check if this function has already been called: */
309214501Srpaulo	if ((_thr_initial != NULL) && (curthread == NULL))
310214501Srpaulo		/* Only initialize the threaded application once. */
311214501Srpaulo		return;
312214501Srpaulo
313214501Srpaulo	/*
314214501Srpaulo	 * Check the size of the jump table to make sure it is preset
315214501Srpaulo	 * with the correct number of entries.
316214501Srpaulo	 */
317214501Srpaulo	if (sizeof(jmp_table) != (sizeof(pthread_func_t) * PJT_MAX * 2))
318214501Srpaulo		PANIC("Thread jump table not properly initialized");
319214501Srpaulo	memcpy(__thr_jtable, jmp_table, sizeof(jmp_table));
320214501Srpaulo	__thr_interpose_libc();
321214501Srpaulo
322214501Srpaulo	/*
323214501Srpaulo	 * Check for the special case of this process running as
324214501Srpaulo	 * or in place of init as pid = 1:
325214501Srpaulo	 */
326214501Srpaulo	if ((_thr_pid = getpid()) == 1) {
327214501Srpaulo		/*
328214501Srpaulo		 * Setup a new session for this process which is
329214501Srpaulo		 * assumed to be running as root.
330214501Srpaulo		 */
331214501Srpaulo		if (setsid() == -1)
332214501Srpaulo			PANIC("Can't set session ID");
333214501Srpaulo		if (revoke(_PATH_CONSOLE) != 0)
334214501Srpaulo			PANIC("Can't revoke console");
335214501Srpaulo		if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0)
336214501Srpaulo			PANIC("Can't open console");
337214501Srpaulo		if (setlogin("root") == -1)
338214501Srpaulo			PANIC("Can't set login to root");
339214501Srpaulo		if (_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1)
340214501Srpaulo			PANIC("Can't set controlling terminal");
341214501Srpaulo	}
342214501Srpaulo
343214501Srpaulo	/* Initialize pthread private data. */
344214501Srpaulo	init_private();
345214501Srpaulo
346214501Srpaulo	/* Set the initial thread. */
347214501Srpaulo	if (curthread == NULL) {
348214501Srpaulo		first = 1;
349214501Srpaulo		/* Create and initialize the initial thread. */
350214501Srpaulo		curthread = _thr_alloc(NULL);
351214501Srpaulo		if (curthread == NULL)
352214501Srpaulo			PANIC("Can't allocate initial thread");
353214501Srpaulo		init_main_thread(curthread);
354214501Srpaulo	} else {
355214501Srpaulo		first = 0;
356214501Srpaulo	}
357214501Srpaulo
358214501Srpaulo	/*
359214501Srpaulo	 * Add the thread to the thread list queue.
360214501Srpaulo	 */
361214501Srpaulo	THR_LIST_ADD(curthread);
362214501Srpaulo	_thread_active_threads = 1;
363214501Srpaulo
364214501Srpaulo	/* Setup the thread specific data */
365214501Srpaulo	_tcb_set(curthread->tcb);
366214501Srpaulo
367214501Srpaulo	if (first) {
368214501Srpaulo		_thr_initial = curthread;
369214501Srpaulo		dlopened = _rtld_is_dlopened(&_thread_autoinit_dummy_decl) != 0;
370214501Srpaulo		_thr_signal_init(dlopened);
371214501Srpaulo		if (_thread_event_mask & TD_CREATE)
372214501Srpaulo			_thr_report_creation(curthread, curthread);
373214501Srpaulo		/*
374214501Srpaulo		 * Always use our rtld lock implementation.
375214501Srpaulo		 * It is faster because it postpones signal handlers
376214501Srpaulo		 * instead of calling sigprocmask(2).
377214501Srpaulo		 */
378214501Srpaulo		_thr_rtld_init();
379214501Srpaulo	}
380214501Srpaulo}
381214501Srpaulo
382214501Srpaulo/*
383214501Srpaulo * This function and pthread_create() do a lot of the same things.
384214501Srpaulo * It'd be nice to consolidate the common stuff in one place.
385214501Srpaulo */
386214501Srpaulostatic void
387214501Srpauloinit_main_thread(struct pthread *thread)
388214501Srpaulo{
389214501Srpaulo	struct sched_param sched_param;
390214501Srpaulo
391214501Srpaulo	/* Setup the thread attributes. */
392214501Srpaulo	thr_self(&thread->tid);
393214501Srpaulo	thread->attr = _pthread_attr_default;
394214501Srpaulo	/*
395214501Srpaulo	 * Set up the thread stack.
396214501Srpaulo	 *
397214501Srpaulo	 * Create a red zone below the main stack.  All other stacks
398214501Srpaulo	 * are constrained to a maximum size by the parameters
399214501Srpaulo	 * passed to mmap(), but this stack is only limited by
400214501Srpaulo	 * resource limits, so this stack needs an explicitly mapped
401214501Srpaulo	 * red zone to protect the thread stack that is just beyond.
402214501Srpaulo	 */
403214501Srpaulo	if (mmap(_usrstack - _thr_stack_initial -
404214501Srpaulo	    _thr_guard_default, _thr_guard_default, 0, MAP_ANON,
405214501Srpaulo	    -1, 0) == MAP_FAILED)
406214501Srpaulo		PANIC("Cannot allocate red zone for initial thread");
407214501Srpaulo
408214501Srpaulo	/*
409214501Srpaulo	 * Mark the stack as an application supplied stack so that it
410214501Srpaulo	 * isn't deallocated.
411214501Srpaulo	 *
412214501Srpaulo	 * XXX - I'm not sure it would hurt anything to deallocate
413214501Srpaulo	 *       the main thread stack because deallocation doesn't
414214501Srpaulo	 *       actually free() it; it just puts it in the free
415214501Srpaulo	 *       stack queue for later reuse.
416214501Srpaulo	 */
417214501Srpaulo	thread->attr.stackaddr_attr = _usrstack - _thr_stack_initial;
418214501Srpaulo	thread->attr.stacksize_attr = _thr_stack_initial;
419214501Srpaulo	thread->attr.guardsize_attr = _thr_guard_default;
420214501Srpaulo	thread->attr.flags |= THR_STACK_USER;
421214501Srpaulo
422214501Srpaulo	/*
423214501Srpaulo	 * Write a magic value to the thread structure
424214501Srpaulo	 * to help identify valid ones:
425214501Srpaulo	 */
426214501Srpaulo	thread->magic = THR_MAGIC;
427214501Srpaulo
428214501Srpaulo	thread->cancel_enable = 1;
429214501Srpaulo	thread->cancel_async = 0;
430214501Srpaulo
431214501Srpaulo	/* Initialize the mutex queue: */
432214501Srpaulo	TAILQ_INIT(&thread->mutexq);
433214501Srpaulo	TAILQ_INIT(&thread->pp_mutexq);
434214501Srpaulo
435214501Srpaulo	thread->state = PS_RUNNING;
436214501Srpaulo
437214501Srpaulo	_thr_getscheduler(thread->tid, &thread->attr.sched_policy,
438214501Srpaulo		 &sched_param);
439214501Srpaulo	thread->attr.prio = sched_param.sched_priority;
440214501Srpaulo
441214501Srpaulo#ifdef _PTHREAD_FORCED_UNWIND
442214501Srpaulo	thread->unwind_stackend = _usrstack;
443214501Srpaulo#endif
444214501Srpaulo
445214501Srpaulo	/* Others cleared to zero by thr_alloc() */
446214501Srpaulo}
447214501Srpaulo
448214501Srpaulostatic void
449214501Srpauloinit_private(void)
450214501Srpaulo{
451214501Srpaulo	struct rlimit rlim;
452214501Srpaulo	size_t len;
453214501Srpaulo	int mib[2];
454214501Srpaulo	char *env, *env_bigstack, *env_splitstack;
455214501Srpaulo
456214501Srpaulo	_thr_umutex_init(&_mutex_static_lock);
457214501Srpaulo	_thr_umutex_init(&_cond_static_lock);
458214501Srpaulo	_thr_umutex_init(&_rwlock_static_lock);
459214501Srpaulo	_thr_umutex_init(&_keytable_lock);
460214501Srpaulo	_thr_urwlock_init(&_thr_atfork_lock);
461214501Srpaulo	_thr_umutex_init(&_thr_event_lock);
462214501Srpaulo	_thr_umutex_init(&_suspend_all_lock);
463214501Srpaulo	_thr_once_init();
464214501Srpaulo	_thr_spinlock_init();
465214501Srpaulo	_thr_list_init();
466214501Srpaulo	_thr_wake_addr_init();
467214501Srpaulo	_sleepq_init();
468214501Srpaulo	_single_thread = NULL;
469214501Srpaulo	_suspend_all_waiters = 0;
470214501Srpaulo
471214501Srpaulo	/*
472214501Srpaulo	 * Avoid reinitializing some things if they don't need to be,
473214501Srpaulo	 * e.g. after a fork().
474214501Srpaulo	 */
475214501Srpaulo	if (init_once == 0) {
476214501Srpaulo		/* Find the stack top */
477214501Srpaulo		mib[0] = CTL_KERN;
478214501Srpaulo		mib[1] = KERN_USRSTACK;
479214501Srpaulo		len = sizeof (_usrstack);
480214501Srpaulo		if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) == -1)
481214501Srpaulo			PANIC("Cannot get kern.usrstack from sysctl");
482214501Srpaulo		env_bigstack = getenv("LIBPTHREAD_BIGSTACK_MAIN");
483214501Srpaulo		env_splitstack = getenv("LIBPTHREAD_SPLITSTACK_MAIN");
484214501Srpaulo		if (env_bigstack != NULL || env_splitstack == NULL) {
485214501Srpaulo			if (getrlimit(RLIMIT_STACK, &rlim) == -1)
486214501Srpaulo				PANIC("Cannot get stack rlimit");
487214501Srpaulo			_thr_stack_initial = rlim.rlim_cur;
488214501Srpaulo		}
489214501Srpaulo		len = sizeof(_thr_is_smp);
490214501Srpaulo		sysctlbyname("kern.smp.cpus", &_thr_is_smp, &len, NULL, 0);
491214501Srpaulo		_thr_is_smp = (_thr_is_smp > 1);
492214501Srpaulo		_thr_page_size = getpagesize();
493214501Srpaulo		_thr_guard_default = _thr_page_size;
494214501Srpaulo		_pthread_attr_default.guardsize_attr = _thr_guard_default;
495214501Srpaulo		_pthread_attr_default.stacksize_attr = _thr_stack_default;
496214501Srpaulo		env = getenv("LIBPTHREAD_SPINLOOPS");
497214501Srpaulo		if (env)
498214501Srpaulo			_thr_spinloops = atoi(env);
499214501Srpaulo		env = getenv("LIBPTHREAD_YIELDLOOPS");
500214501Srpaulo		if (env)
501214501Srpaulo			_thr_yieldloops = atoi(env);
502214501Srpaulo		env = getenv("LIBPTHREAD_QUEUE_FIFO");
503214501Srpaulo		if (env)
504214501Srpaulo			_thr_queuefifo = atoi(env);
505214501Srpaulo		TAILQ_INIT(&_thr_atfork_list);
506214501Srpaulo	}
507214501Srpaulo	init_once = 1;
508214501Srpaulo}
509214501Srpaulo