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