171b3fa15SDavid Xu /*
271b3fa15SDavid Xu * Copyright (c) 2003 Daniel M. Eischen <deischen@freebsd.org>
371b3fa15SDavid Xu * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
471b3fa15SDavid Xu * All rights reserved.
571b3fa15SDavid Xu *
671b3fa15SDavid Xu * Redistribution and use in source and binary forms, with or without
771b3fa15SDavid Xu * modification, are permitted provided that the following conditions
871b3fa15SDavid Xu * are met:
971b3fa15SDavid Xu * 1. Redistributions of source code must retain the above copyright
1071b3fa15SDavid Xu * notice, this list of conditions and the following disclaimer.
1171b3fa15SDavid Xu * 2. Redistributions in binary form must reproduce the above copyright
1271b3fa15SDavid Xu * notice, this list of conditions and the following disclaimer in the
1371b3fa15SDavid Xu * documentation and/or other materials provided with the distribution.
1471b3fa15SDavid Xu * 3. All advertising materials mentioning features or use of this software
1571b3fa15SDavid Xu * must display the following acknowledgement:
1671b3fa15SDavid Xu * This product includes software developed by John Birrell.
1771b3fa15SDavid Xu * 4. Neither the name of the author nor the names of any co-contributors
1871b3fa15SDavid Xu * may be used to endorse or promote products derived from this software
1971b3fa15SDavid Xu * without specific prior written permission.
2071b3fa15SDavid Xu *
2171b3fa15SDavid Xu * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
2271b3fa15SDavid Xu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2371b3fa15SDavid Xu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2471b3fa15SDavid Xu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2571b3fa15SDavid Xu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2671b3fa15SDavid Xu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2771b3fa15SDavid Xu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2871b3fa15SDavid Xu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2971b3fa15SDavid Xu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3071b3fa15SDavid Xu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3171b3fa15SDavid Xu * SUCH DAMAGE.
3271b3fa15SDavid Xu */
3371b3fa15SDavid Xu
3471b3fa15SDavid Xu #include "namespace.h"
3571b3fa15SDavid Xu #include <sys/param.h>
3671b3fa15SDavid Xu #include <sys/signalvar.h>
3771b3fa15SDavid Xu #include <sys/ioctl.h>
3871b3fa15SDavid Xu #include <sys/sysctl.h>
3971b3fa15SDavid Xu #include <sys/time.h>
404b29dd4bSMichael Neumann #include <sys/types.h>
414b29dd4bSMichael Neumann #include <sys/resource.h>
4271b3fa15SDavid Xu #include <sys/ttycom.h>
4371b3fa15SDavid Xu #include <sys/mman.h>
44e7bf3f77SMatthew Dillon #include <stdio.h>
4571b3fa15SDavid Xu #include <fcntl.h>
4671b3fa15SDavid Xu #include <paths.h>
4771b3fa15SDavid Xu #include <pthread.h>
4871b3fa15SDavid Xu #include <signal.h>
4971b3fa15SDavid Xu #include <stdlib.h>
5071b3fa15SDavid Xu #include <string.h>
5171b3fa15SDavid Xu #include <unistd.h>
5271b3fa15SDavid Xu #include "un-namespace.h"
5371b3fa15SDavid Xu
5471b3fa15SDavid Xu #include "libc_private.h"
5571b3fa15SDavid Xu #include "thr_private.h"
5671b3fa15SDavid Xu
57602cfc0bSzrj /* Default thread attributes: */
58cf8046a9Szrj struct __pthread_attr_s _pthread_attr_default = {
59602cfc0bSzrj .sched_policy = SCHED_OTHER,
60602cfc0bSzrj .sched_inherit = 0,
61602cfc0bSzrj .prio = THR_DEFAULT_PRIORITY,
62602cfc0bSzrj .suspend = THR_CREATE_RUNNING,
63467ee1bbSzrj .flags = PTHREAD_SCOPE_SYSTEM,
64602cfc0bSzrj .stackaddr_attr = NULL,
65602cfc0bSzrj .stacksize_attr = THR_STACK_DEFAULT,
66602cfc0bSzrj .guardsize_attr = 0
67602cfc0bSzrj };
68602cfc0bSzrj
69602cfc0bSzrj /* Default mutex attributes: */
70cf8046a9Szrj struct __pthread_mutexattr_s _pthread_mutexattr_default = {
71602cfc0bSzrj .m_type = PTHREAD_MUTEX_DEFAULT,
72602cfc0bSzrj .m_protocol = PTHREAD_PRIO_NONE,
73602cfc0bSzrj .m_ceiling = 0,
74602cfc0bSzrj .m_flags = 0
75602cfc0bSzrj };
76602cfc0bSzrj
77602cfc0bSzrj /* Default condition variable attributes: */
78cf8046a9Szrj struct __pthread_condattr_s _pthread_condattr_default = {
79602cfc0bSzrj .c_pshared = PTHREAD_PROCESS_PRIVATE,
80602cfc0bSzrj .c_clockid = CLOCK_REALTIME
81602cfc0bSzrj };
82602cfc0bSzrj
8322d6e608SDavid Xu /* thr_attr.c */
8422d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_attr_init);
8522d6e608SDavid Xu /* thr_barrier.c */
8622d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_barrier_init);
8722d6e608SDavid Xu /* thr_barrierattr.c */
8822d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_barrierattr_init);
8922d6e608SDavid Xu /* thr_cancel.c */
9022d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_cancel);
9122d6e608SDavid Xu /* thr_clean.c */
9222d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_cleanup_push);
9322d6e608SDavid Xu /* thr_concurrency.c */
9434c13333SSascha Wildner STATIC_LIB_REQUIRE(_pthread_getconcurrency);
9534c13333SSascha Wildner STATIC_LIB_REQUIRE(_pthread_setconcurrency);
9622d6e608SDavid Xu /* thr_cond.c */
9722d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_cond_init);
9822d6e608SDavid Xu /* thr_condattr.c */
9922d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_condattr_init);
10022d6e608SDavid Xu /* thr_create.c */
10122d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_create);
10222d6e608SDavid Xu /* thr_detach.c */
10322d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_detach);
10422d6e608SDavid Xu /* thr_equal.c */
10522d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_equal);
10622d6e608SDavid Xu /* thr_exit.c */
10722d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_exit);
10822d6e608SDavid Xu /* thr_fork.c */
10922d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_atfork);
11022d6e608SDavid Xu STATIC_LIB_REQUIRE(_fork);
111b2920380SSepherosa Ziehau /* thr_affinity.c */
112b2920380SSepherosa Ziehau STATIC_LIB_REQUIRE(_pthread_getaffinity_np);
113725edadfSSascha Wildner /* thr_getcpuclockid.c */
114725edadfSSascha Wildner STATIC_LIB_REQUIRE(_pthread_getcpuclockid);
11522d6e608SDavid Xu /* thr_getprio.c */
11622d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_getprio);
11722d6e608SDavid Xu /* thr_getschedparam.c */
11822d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_getschedparam);
119c0f25c26SImre Vadász /* thr_getthreadid_np.c */
120c0f25c26SImre Vadász STATIC_LIB_REQUIRE(_pthread_getthreadid_np);
12122d6e608SDavid Xu /* thr_info.c */
122eb396e51SMatthew Dillon STATIC_LIB_REQUIRE(_pthread_get_name_np);
123eb396e51SMatthew Dillon /* thr_info.c */
124*ab5dc9acSSascha Wildner STATIC_LIB_REQUIRE(_pthread_getname_np);
125*ab5dc9acSSascha Wildner /* thr_info.c */
12622d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_set_name_np);
127*ab5dc9acSSascha Wildner /* thr_info.c */
128*ab5dc9acSSascha Wildner STATIC_LIB_REQUIRE(_pthread_setname_np);
129a809fd39SMarkus Pfeiffer /* thr_init.c */
130a809fd39SMarkus Pfeiffer STATIC_LIB_REQUIRE(_pthread_init_early);
13122d6e608SDavid Xu /* thr_join.c */
13222d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_join);
13322d6e608SDavid Xu /* thr_kill.c */
13422d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_kill);
13522d6e608SDavid Xu /* thr_main_np.c */
13622d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_main_np);
13722d6e608SDavid Xu /* thr_multi_np.c */
13822d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_multi_np);
13922d6e608SDavid Xu /* thr_mutex.c */
14022d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_mutex_init);
14122d6e608SDavid Xu /* thr_mutex_prioceiling.c */
14222d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_mutexattr_getprioceiling);
14322d6e608SDavid Xu /* thr_mutex_protocol.c */
14422d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_mutexattr_getprotocol);
14522d6e608SDavid Xu /* thr_mutexattr.c */
14622d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_mutexattr_init);
14722d6e608SDavid Xu /* thr_once.c */
14822d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_once);
14922d6e608SDavid Xu /* thr_pspinlock.c */
15022d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_spin_init);
15122d6e608SDavid Xu /* thr_resume_np.c */
15222d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_resume_np);
15322d6e608SDavid Xu /* thr_rwlock.c */
15422d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_rwlock_init);
15522d6e608SDavid Xu /* thr_rwlockattr.c */
15622d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_rwlockattr_init);
15722d6e608SDavid Xu /* thr_self.c */
15822d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_self);
15922d6e608SDavid Xu /* thr_sem.c */
16022d6e608SDavid Xu STATIC_LIB_REQUIRE(_sem_init);
161b2920380SSepherosa Ziehau /* thr_affinity.c */
162b2920380SSepherosa Ziehau STATIC_LIB_REQUIRE(_pthread_setaffinity_np);
16322d6e608SDavid Xu /* thr_setprio.c */
16422d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_setprio);
16522d6e608SDavid Xu /* thr_setschedparam.c */
16622d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_setschedparam);
16722d6e608SDavid Xu /* thr_sig.c */
16822d6e608SDavid Xu STATIC_LIB_REQUIRE(_sigwait);
16922d6e608SDavid Xu /* thr_single_np.c */
17022d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_single_np);
17122d6e608SDavid Xu /* thr_spec.c */
17222d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_key_create);
17322d6e608SDavid Xu /* thr_spinlock.c */
17422d6e608SDavid Xu STATIC_LIB_REQUIRE(_spinlock);
17522d6e608SDavid Xu /* thr_suspend_np.c */
17622d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_suspend_np);
17722d6e608SDavid Xu /* thr_switch_np.c */
17822d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_switch_add_np);
17922d6e608SDavid Xu /* thr_symbols.c */
18022d6e608SDavid Xu STATIC_LIB_REQUIRE(_thread_state_running);
18122d6e608SDavid Xu /* thr_syscalls.c */
18222d6e608SDavid Xu STATIC_LIB_REQUIRE(__wait4);
18322d6e608SDavid Xu /* thr_yield.c */
18422d6e608SDavid Xu STATIC_LIB_REQUIRE(_pthread_yield);
18522d6e608SDavid Xu
186fc71f871SDavid Xu char *_usrstack;
187940be950Szrj pthread_t _thr_initial;
1880dc5e56dSMatthew Dillon static void *_thr_main_redzone;
189e8382b15SDavid Xu
190e8382b15SDavid Xu pid_t _thr_pid;
191fc71f871SDavid Xu size_t _thr_guard_default;
192fc71f871SDavid Xu size_t _thr_stack_default = THR_STACK_DEFAULT;
193fc71f871SDavid Xu size_t _thr_stack_initial = THR_STACK_INITIAL;
194e8382b15SDavid Xu int _thr_page_size;
195e8382b15SDavid Xu
196e8382b15SDavid Xu static void init_private(void);
1970dc5e56dSMatthew Dillon static void _libpthread_uninit(void);
198940be950Szrj static void init_main_thread(pthread_t thread);
199e8382b15SDavid Xu
200e8382b15SDavid Xu void _thread_init(void) __attribute__ ((constructor));
201e8382b15SDavid Xu void
_thread_init(void)202e8382b15SDavid Xu _thread_init(void)
203e8382b15SDavid Xu {
204e8382b15SDavid Xu _libpthread_init(NULL);
205721505deSMatthew Dillon _libc_thr_init();
206e8382b15SDavid Xu }
207e8382b15SDavid Xu
2080dc5e56dSMatthew Dillon void _thread_uninit(void) __attribute__ ((destructor));
2090dc5e56dSMatthew Dillon void
_thread_uninit(void)2100dc5e56dSMatthew Dillon _thread_uninit(void)
2110dc5e56dSMatthew Dillon {
2120dc5e56dSMatthew Dillon _libpthread_uninit();
2130dc5e56dSMatthew Dillon }
2140dc5e56dSMatthew Dillon
21571b3fa15SDavid Xu /*
216a809fd39SMarkus Pfeiffer * This function is used by libc to initialise libpthread
217a809fd39SMarkus Pfeiffer * early during dynamic linking.
218a809fd39SMarkus Pfeiffer */
219a809fd39SMarkus Pfeiffer void _pthread_init_early(void);
220a809fd39SMarkus Pfeiffer void
_pthread_init_early(void)221a809fd39SMarkus Pfeiffer _pthread_init_early(void)
222a809fd39SMarkus Pfeiffer {
223a809fd39SMarkus Pfeiffer _libpthread_init(NULL);
224a809fd39SMarkus Pfeiffer }
225a809fd39SMarkus Pfeiffer
226a809fd39SMarkus Pfeiffer /*
22771b3fa15SDavid Xu * Threaded process initialization.
22871b3fa15SDavid Xu *
22971b3fa15SDavid Xu * This is only called under two conditions:
23071b3fa15SDavid Xu *
23171b3fa15SDavid Xu * 1) Some thread routines have detected that the library hasn't yet
23271b3fa15SDavid Xu * been initialized (_thr_initial == NULL && curthread == NULL), or
23371b3fa15SDavid Xu *
23471b3fa15SDavid Xu * 2) An explicit call to reinitialize after a fork (indicated
23571b3fa15SDavid Xu * by curthread != NULL)
23671b3fa15SDavid Xu */
23771b3fa15SDavid Xu void
_libpthread_init(pthread_t curthread)238940be950Szrj _libpthread_init(pthread_t curthread)
23971b3fa15SDavid Xu {
24071b3fa15SDavid Xu int fd, first = 0;
24171b3fa15SDavid Xu sigset_t sigset, oldset;
24271b3fa15SDavid Xu
24371b3fa15SDavid Xu /* Check if this function has already been called: */
24471b3fa15SDavid Xu if ((_thr_initial != NULL) && (curthread == NULL))
24571b3fa15SDavid Xu /* Only initialize the threaded application once. */
24671b3fa15SDavid Xu return;
24771b3fa15SDavid Xu
24871b3fa15SDavid Xu /*
24971b3fa15SDavid Xu * Check for the special case of this process running as
25071b3fa15SDavid Xu * or in place of init as pid = 1:
25171b3fa15SDavid Xu */
25271b3fa15SDavid Xu if ((_thr_pid = getpid()) == 1) {
25371b3fa15SDavid Xu /*
25471b3fa15SDavid Xu * Setup a new session for this process which is
25571b3fa15SDavid Xu * assumed to be running as root.
25671b3fa15SDavid Xu */
25771b3fa15SDavid Xu if (setsid() == -1)
25871b3fa15SDavid Xu PANIC("Can't set session ID");
25971b3fa15SDavid Xu if (revoke(_PATH_CONSOLE) != 0)
26071b3fa15SDavid Xu PANIC("Can't revoke console");
26171b3fa15SDavid Xu if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0)
26271b3fa15SDavid Xu PANIC("Can't open console");
26371b3fa15SDavid Xu if (setlogin("root") == -1)
26471b3fa15SDavid Xu PANIC("Can't set login to root");
2652038fb68SSascha Wildner if (__sys_ioctl(fd, TIOCSCTTY, NULL) == -1)
26671b3fa15SDavid Xu PANIC("Can't set controlling terminal");
26771b3fa15SDavid Xu }
26871b3fa15SDavid Xu
26971b3fa15SDavid Xu /* Initialize pthread private data. */
27071b3fa15SDavid Xu init_private();
27171b3fa15SDavid Xu
27271b3fa15SDavid Xu /* Set the initial thread. */
27371b3fa15SDavid Xu if (curthread == NULL) {
27471b3fa15SDavid Xu first = 1;
27571b3fa15SDavid Xu /* Create and initialize the initial thread. */
27671b3fa15SDavid Xu curthread = _thr_alloc(NULL);
27771b3fa15SDavid Xu if (curthread == NULL)
27871b3fa15SDavid Xu PANIC("Can't allocate initial thread");
27971b3fa15SDavid Xu init_main_thread(curthread);
28071b3fa15SDavid Xu }
28171b3fa15SDavid Xu /*
28271b3fa15SDavid Xu * Add the thread to the thread list queue.
28371b3fa15SDavid Xu */
28471b3fa15SDavid Xu THR_LIST_ADD(curthread);
28571b3fa15SDavid Xu _thread_active_threads = 1;
28671b3fa15SDavid Xu
28771b3fa15SDavid Xu /* Setup the thread specific data */
2889e2ee207SJoerg Sonnenberger tls_set_tcb(curthread->tcb);
28971b3fa15SDavid Xu
29071b3fa15SDavid Xu if (first) {
29171b3fa15SDavid Xu SIGFILLSET(sigset);
29271b3fa15SDavid Xu __sys_sigprocmask(SIG_SETMASK, &sigset, &oldset);
29371b3fa15SDavid Xu _thr_signal_init();
29471b3fa15SDavid Xu _thr_initial = curthread;
29571b3fa15SDavid Xu SIGDELSET(oldset, SIGCANCEL);
29671b3fa15SDavid Xu __sys_sigprocmask(SIG_SETMASK, &oldset, NULL);
2973cd47da3SDavid Xu if (td_eventismember(&_thread_event_mask, TD_CREATE))
2983cd47da3SDavid Xu _thr_report_creation(curthread, curthread);
29998247283SMatthew Dillon _thr_rtld_init();
300e2caf0e7SMatthew Dillon _thr_malloc_init();
30198247283SMatthew Dillon _thr_sem_init();
30271b3fa15SDavid Xu }
30371b3fa15SDavid Xu }
30471b3fa15SDavid Xu
3050dc5e56dSMatthew Dillon static void
_libpthread_uninit(void)3060dc5e56dSMatthew Dillon _libpthread_uninit(void)
3070dc5e56dSMatthew Dillon {
3080dc5e56dSMatthew Dillon if (_thr_initial == NULL)
3090dc5e56dSMatthew Dillon return;
3100dc5e56dSMatthew Dillon if (_thr_main_redzone && _thr_main_redzone != MAP_FAILED) {
3110dc5e56dSMatthew Dillon munmap(_thr_main_redzone, _thr_guard_default);
3120dc5e56dSMatthew Dillon _thr_main_redzone = NULL;
3130dc5e56dSMatthew Dillon }
3140dc5e56dSMatthew Dillon _thr_stack_cleanup();
3150dc5e56dSMatthew Dillon }
3160dc5e56dSMatthew Dillon
31771b3fa15SDavid Xu /*
31871b3fa15SDavid Xu * This function and pthread_create() do a lot of the same things.
31971b3fa15SDavid Xu * It'd be nice to consolidate the common stuff in one place.
32071b3fa15SDavid Xu */
32171b3fa15SDavid Xu static void
init_main_thread(pthread_t thread)322940be950Szrj init_main_thread(pthread_t thread)
32371b3fa15SDavid Xu {
32471b3fa15SDavid Xu /* Setup the thread attributes. */
32571b3fa15SDavid Xu thread->tid = _thr_get_tid();
32671b3fa15SDavid Xu thread->attr = _pthread_attr_default;
32771b3fa15SDavid Xu /*
32871b3fa15SDavid Xu * Set up the thread stack.
32971b3fa15SDavid Xu *
33071b3fa15SDavid Xu * Create a red zone below the main stack. All other stacks
33171b3fa15SDavid Xu * are constrained to a maximum size by the parameters
33271b3fa15SDavid Xu * passed to mmap(), but this stack is only limited by
33371b3fa15SDavid Xu * resource limits, so this stack needs an explicitly mapped
33471b3fa15SDavid Xu * red zone to protect the thread stack that is just beyond.
33571b3fa15SDavid Xu */
3360dc5e56dSMatthew Dillon _thr_main_redzone = mmap(_usrstack - _thr_stack_initial -
3372035b679SMatthew Dillon _thr_guard_default, _thr_guard_default,
3380dc5e56dSMatthew Dillon 0, MAP_ANON | MAP_TRYFIXED, -1, 0);
3390dc5e56dSMatthew Dillon if (_thr_main_redzone == MAP_FAILED) {
34071b3fa15SDavid Xu PANIC("Cannot allocate red zone for initial thread");
3412035b679SMatthew Dillon }
34271b3fa15SDavid Xu
34371b3fa15SDavid Xu /*
34471b3fa15SDavid Xu * Mark the stack as an application supplied stack so that it
34571b3fa15SDavid Xu * isn't deallocated.
34671b3fa15SDavid Xu *
34771b3fa15SDavid Xu * XXX - I'm not sure it would hurt anything to deallocate
34871b3fa15SDavid Xu * the main thread stack because deallocation doesn't
34971b3fa15SDavid Xu * actually free() it; it just puts it in the free
35071b3fa15SDavid Xu * stack queue for later reuse.
35171b3fa15SDavid Xu */
352fc71f871SDavid Xu thread->attr.stackaddr_attr = _usrstack - _thr_stack_initial;
353eddabc99SDavid Xu thread->attr.stacksize_attr = _thr_stack_initial;
35471b3fa15SDavid Xu thread->attr.guardsize_attr = _thr_guard_default;
35571b3fa15SDavid Xu thread->attr.flags |= THR_STACK_USER;
35671b3fa15SDavid Xu
35771b3fa15SDavid Xu /*
35871b3fa15SDavid Xu * Write a magic value to the thread structure
35971b3fa15SDavid Xu * to help identify valid ones:
36071b3fa15SDavid Xu */
36171b3fa15SDavid Xu thread->magic = THR_MAGIC;
36271b3fa15SDavid Xu
36371b3fa15SDavid Xu thread->cancelflags = PTHREAD_CANCEL_ENABLE | PTHREAD_CANCEL_DEFERRED;
364e7bf3f77SMatthew Dillon thread->name = __malloc(16);
365e7bf3f77SMatthew Dillon snprintf(thread->name, 16, "initial thread");
36671b3fa15SDavid Xu
36771b3fa15SDavid Xu /* Default the priority of the initial thread: */
36871b3fa15SDavid Xu thread->base_priority = THR_DEFAULT_PRIORITY;
36971b3fa15SDavid Xu thread->active_priority = THR_DEFAULT_PRIORITY;
37071b3fa15SDavid Xu thread->inherited_priority = 0;
37171b3fa15SDavid Xu
37271b3fa15SDavid Xu /* Initialize the mutex queue: */
37371b3fa15SDavid Xu TAILQ_INIT(&thread->mutexq);
37471b3fa15SDavid Xu
37571b3fa15SDavid Xu thread->state = PS_RUNNING;
37671b3fa15SDavid Xu thread->uniqueid = 0;
37771b3fa15SDavid Xu
37871b3fa15SDavid Xu /* Others cleared to zero by thr_alloc() */
37971b3fa15SDavid Xu }
38071b3fa15SDavid Xu
3814b29dd4bSMichael Neumann /*
3824b29dd4bSMichael Neumann * Determine the size of the main thread.
3834b29dd4bSMichael Neumann *
3844b29dd4bSMichael Neumann * Set the main thread's stack size equal to the value of RLIMIT_STACK for the
3854b29dd4bSMichael Neumann * process. The size of stacks for threads created by the process at run-time
3864b29dd4bSMichael Neumann * with pthread_create(3) is not affected by this and is still controlled by
3874b29dd4bSMichael Neumann * thread attributes.
3884b29dd4bSMichael Neumann *
3894b29dd4bSMichael Neumann * Note: FreeBSD uses environment variables LIBPTHREAD_BIGSTACK_MAIN and
3904b29dd4bSMichael Neumann * LIBPTHREAD_SPLITSTACK_MAIN to control use of RLIMIT_STACK vs the hard-coded
3914b29dd4bSMichael Neumann * 4MB with RLIMIT_STACK being the default behaviour. DragonFly instead respects
3924b29dd4bSMichael Neumann * RLIMIT_STACK unconditionally.
3934b29dd4bSMichael Neumann */
3944b29dd4bSMichael Neumann static int64_t
get_mainthread_size(void)3954b29dd4bSMichael Neumann get_mainthread_size(void)
3964b29dd4bSMichael Neumann {
3974b29dd4bSMichael Neumann struct rlimit rlim;
3984b29dd4bSMichael Neumann
3994b29dd4bSMichael Neumann if (getrlimit(RLIMIT_STACK, &rlim) == -1)
4004b29dd4bSMichael Neumann PANIC("Cannot get stack rlimit");
4014b29dd4bSMichael Neumann
4024b29dd4bSMichael Neumann return rlim.rlim_cur;
4034b29dd4bSMichael Neumann }
4044b29dd4bSMichael Neumann
40571b3fa15SDavid Xu static void
init_private(void)40671b3fa15SDavid Xu init_private(void)
40771b3fa15SDavid Xu {
408fcaa7a3aSMatthew Dillon static int init_once = 0;
40971b3fa15SDavid Xu size_t len;
41071b3fa15SDavid Xu int mib[2];
41171b3fa15SDavid Xu
41271b3fa15SDavid Xu /*
41371b3fa15SDavid Xu * Avoid reinitializing some things if they don't need to be,
41471b3fa15SDavid Xu * e.g. after a fork().
415fcaa7a3aSMatthew Dillon *
416fcaa7a3aSMatthew Dillon * NOTE: _thr_atfork_*list must remain intact after a fork.
41771b3fa15SDavid Xu */
41871b3fa15SDavid Xu if (init_once == 0) {
41971b3fa15SDavid Xu /* Find the stack top */
42071b3fa15SDavid Xu mib[0] = CTL_KERN;
42171b3fa15SDavid Xu mib[1] = KERN_USRSTACK;
42271b3fa15SDavid Xu len = sizeof (_usrstack);
42371b3fa15SDavid Xu if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) == -1)
42471b3fa15SDavid Xu PANIC("Cannot get kern.usrstack from sysctl");
4254b29dd4bSMichael Neumann _thr_stack_initial = get_mainthread_size();
42671b3fa15SDavid Xu _thr_page_size = getpagesize();
42771b3fa15SDavid Xu _thr_guard_default = _thr_page_size;
42871b3fa15SDavid Xu _pthread_attr_default.guardsize_attr = _thr_guard_default;
42971b3fa15SDavid Xu TAILQ_INIT(&_thr_atfork_list);
430fcaa7a3aSMatthew Dillon TAILQ_INIT(&_thr_atfork_kern_list);
43171b3fa15SDavid Xu init_once = 1;
43271b3fa15SDavid Xu }
433a809fd39SMarkus Pfeiffer
434fcaa7a3aSMatthew Dillon _thr_umtx_init(&_mutex_static_lock);
435fcaa7a3aSMatthew Dillon _thr_umtx_init(&_cond_static_lock);
436fcaa7a3aSMatthew Dillon _thr_umtx_init(&_rwlock_static_lock);
437fcaa7a3aSMatthew Dillon _thr_umtx_init(&_keytable_lock);
438fcaa7a3aSMatthew Dillon _thr_umtx_init(&_thr_atfork_lock);
439fcaa7a3aSMatthew Dillon _thr_umtx_init(&_thr_event_lock);
440fcaa7a3aSMatthew Dillon _thr_spinlock_init();
441fcaa7a3aSMatthew Dillon _thr_list_init();
442fcaa7a3aSMatthew Dillon }
443fcaa7a3aSMatthew Dillon
444a809fd39SMarkus Pfeiffer __strong_reference(_pthread_init_early, pthread_init_early);
445