1/* 2 * Copyright (c) 2003 Daniel M. Eischen <deischen@freebsd.org> 3 * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by John Birrell. 17 * 4. Neither the name of the author nor the names of any co-contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 *
| 1/* 2 * Copyright (c) 2003 Daniel M. Eischen <deischen@freebsd.org> 3 * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by John Birrell. 17 * 4. Neither the name of the author nor the names of any co-contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 *
|
34 */ 35 36/* Allocate space for global thread variables here: */ 37#define GLOBAL_PTHREAD_PRIVATE 38 39#include "namespace.h" 40#include <sys/param.h> 41#include <sys/types.h> 42#include <sys/signalvar.h> 43#include <machine/reg.h> 44 45#include <sys/ioctl.h> 46#include <sys/mount.h> 47#include <sys/uio.h> 48#include <sys/socket.h> 49#include <sys/event.h> 50#include <sys/stat.h> 51#include <sys/sysctl.h> 52#include <sys/time.h> 53#include <sys/ttycom.h> 54#include <sys/wait.h> 55#include <sys/mman.h> 56#include <dirent.h> 57#include <errno.h> 58#include <fcntl.h> 59#include <paths.h> 60#include <pthread.h> 61#include <pthread_np.h> 62#include <signal.h> 63#include <stdio.h> 64#include <stdlib.h> 65#include <string.h> 66#include <unistd.h> 67#include "un-namespace.h" 68 69#include "libc_private.h" 70#include "thr_private.h" 71 72int __pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *); 73int __pthread_mutex_lock(pthread_mutex_t *); 74int __pthread_mutex_trylock(pthread_mutex_t *); 75void _thread_init_hack(void); 76extern int _thread_state_running; 77 78static void init_private(void); 79static void init_main_thread(struct pthread *thread); 80 81/* 82 * All weak references used within libc should be in this table. 83 * This is so that static libraries will work. 84 */ 85static void *references[] = { 86 &_accept, 87 &_bind, 88 &_close, 89 &_connect, 90 &_dup, 91 &_dup2, 92 &_execve, 93 &_fcntl, 94 &_flock, 95 &_flockfile, 96 &_fstat, 97 &_fstatfs, 98 &_fsync, 99 &_funlockfile, 100 &_getdirentries, 101 &_getlogin, 102 &_getpeername, 103 &_getsockname, 104 &_getsockopt, 105 &_ioctl, 106 &_kevent, 107 &_listen, 108 &_nanosleep, 109 &_open, 110 &_pthread_getspecific, 111 &_pthread_key_create, 112 &_pthread_key_delete, 113 &_pthread_mutex_destroy, 114 &_pthread_mutex_init, 115 &_pthread_mutex_lock, 116 &_pthread_mutex_trylock, 117 &_pthread_mutex_unlock, 118 &_pthread_mutexattr_init, 119 &_pthread_mutexattr_destroy, 120 &_pthread_mutexattr_settype, 121 &_pthread_once, 122 &_pthread_setspecific, 123 &_read, 124 &_readv, 125 &_recvfrom, 126 &_recvmsg, 127 &_select, 128 &_sendmsg, 129 &_sendto, 130 &_setsockopt, 131 &_sigaction, 132 &_sigprocmask, 133 &_sigsuspend, 134 &_socket, 135 &_socketpair, 136 &_thread_init_hack, 137 &_wait4, 138 &_write, 139 &_writev 140}; 141 142/* 143 * These are needed when linking statically. All references within 144 * libgcc (and in the future libc) to these routines are weak, but 145 * if they are not (strongly) referenced by the application or other 146 * libraries, then the actual functions will not be loaded. 147 */ 148static void *libgcc_references[] = { 149 &_pthread_once, 150 &_pthread_key_create, 151 &_pthread_key_delete, 152 &_pthread_getspecific, 153 &_pthread_setspecific, 154 &_pthread_mutex_init, 155 &_pthread_mutex_destroy, 156 &_pthread_mutex_lock, 157 &_pthread_mutex_trylock, 158 &_pthread_mutex_unlock 159}; 160 161#define DUAL_ENTRY(entry) \ 162 (pthread_func_t)entry, (pthread_func_t)entry 163 164static pthread_func_t jmp_table[][2] = { 165 {DUAL_ENTRY(_pthread_cond_broadcast)}, /* PJT_COND_BROADCAST */ 166 {DUAL_ENTRY(_pthread_cond_destroy)}, /* PJT_COND_DESTROY */ 167 {DUAL_ENTRY(_pthread_cond_init)}, /* PJT_COND_INIT */ 168 {DUAL_ENTRY(_pthread_cond_signal)}, /* PJT_COND_SIGNAL */ 169 {(pthread_func_t)__pthread_cond_wait, 170 (pthread_func_t)_pthread_cond_wait}, /* PJT_COND_WAIT */ 171 {DUAL_ENTRY(_pthread_getspecific)}, /* PJT_GETSPECIFIC */ 172 {DUAL_ENTRY(_pthread_key_create)}, /* PJT_KEY_CREATE */ 173 {DUAL_ENTRY(_pthread_key_delete)}, /* PJT_KEY_DELETE*/ 174 {DUAL_ENTRY(_pthread_main_np)}, /* PJT_MAIN_NP */ 175 {DUAL_ENTRY(_pthread_mutex_destroy)}, /* PJT_MUTEX_DESTROY */ 176 {DUAL_ENTRY(_pthread_mutex_init)}, /* PJT_MUTEX_INIT */ 177 {(pthread_func_t)__pthread_mutex_lock, 178 (pthread_func_t)_pthread_mutex_lock}, /* PJT_MUTEX_LOCK */ 179 {(pthread_func_t)__pthread_mutex_trylock, 180 (pthread_func_t)_pthread_mutex_trylock},/* PJT_MUTEX_TRYLOCK */ 181 {DUAL_ENTRY(_pthread_mutex_unlock)}, /* PJT_MUTEX_UNLOCK */ 182 {DUAL_ENTRY(_pthread_mutexattr_destroy)}, /* PJT_MUTEXATTR_DESTROY */ 183 {DUAL_ENTRY(_pthread_mutexattr_init)}, /* PJT_MUTEXATTR_INIT */ 184 {DUAL_ENTRY(_pthread_mutexattr_settype)}, /* PJT_MUTEXATTR_SETTYPE */ 185 {DUAL_ENTRY(_pthread_once)}, /* PJT_ONCE */ 186 {DUAL_ENTRY(_pthread_rwlock_destroy)}, /* PJT_RWLOCK_DESTROY */ 187 {DUAL_ENTRY(_pthread_rwlock_init)}, /* PJT_RWLOCK_INIT */ 188 {DUAL_ENTRY(_pthread_rwlock_rdlock)}, /* PJT_RWLOCK_RDLOCK */ 189 {DUAL_ENTRY(_pthread_rwlock_tryrdlock)},/* PJT_RWLOCK_TRYRDLOCK */ 190 {DUAL_ENTRY(_pthread_rwlock_trywrlock)},/* PJT_RWLOCK_TRYWRLOCK */ 191 {DUAL_ENTRY(_pthread_rwlock_unlock)}, /* PJT_RWLOCK_UNLOCK */ 192 {DUAL_ENTRY(_pthread_rwlock_wrlock)}, /* PJT_RWLOCK_WRLOCK */ 193 {DUAL_ENTRY(_pthread_self)}, /* PJT_SELF */ 194 {DUAL_ENTRY(_pthread_setspecific)}, /* PJT_SETSPECIFIC */ 195 {DUAL_ENTRY(_pthread_sigmask)} /* PJT_SIGMASK */ 196}; 197 198static int init_once = 0; 199 200/* 201 * Threaded process initialization. 202 * 203 * This is only called under two conditions: 204 * 205 * 1) Some thread routines have detected that the library hasn't yet 206 * been initialized (_thr_initial == NULL && curthread == NULL), or 207 * 208 * 2) An explicit call to reinitialize after a fork (indicated 209 * by curthread != NULL) 210 */ 211void 212_libpthread_init(struct pthread *curthread) 213{ 214 int fd; 215 216 /* Check if this function has already been called: */ 217 if ((_thr_initial != NULL) && (curthread == NULL)) 218 /* Only initialize the threaded application once. */ 219 return; 220 221 /* 222 * Make gcc quiescent about {,libgcc_}references not being 223 * referenced: 224 */ 225 if ((references[0] == NULL) || (libgcc_references[0] == NULL)) 226 PANIC("Failed loading mandatory references in _thread_init"); 227 228 /* Pull debug symbols in for static binary */ 229 _thread_state_running = PS_RUNNING; 230 231 /* 232 * Check the size of the jump table to make sure it is preset 233 * with the correct number of entries. 234 */ 235 if (sizeof(jmp_table) != (sizeof(pthread_func_t) * PJT_MAX * 2)) 236 PANIC("Thread jump table not properly initialized"); 237 memcpy(__thr_jtable, jmp_table, sizeof(jmp_table)); 238 239 /* 240 * Check for the special case of this process running as 241 * or in place of init as pid = 1: 242 */ 243 if ((_thr_pid = getpid()) == 1) { 244 /* 245 * Setup a new session for this process which is 246 * assumed to be running as root. 247 */ 248 if (setsid() == -1) 249 PANIC("Can't set session ID"); 250 if (revoke(_PATH_CONSOLE) != 0) 251 PANIC("Can't revoke console"); 252 if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0) 253 PANIC("Can't open console"); 254 if (setlogin("root") == -1) 255 PANIC("Can't set login to root"); 256 if (__sys_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1) 257 PANIC("Can't set controlling terminal"); 258 } 259 260 /* Initialize pthread private data. */ 261 init_private(); 262 _kse_init(); 263 264 /* Initialize the initial kse and kseg. */ 265 _kse_initial = _kse_alloc(NULL, _thread_scope_system > 0); 266 if (_kse_initial == NULL) 267 PANIC("Can't allocate initial kse."); 268 _kse_initial->k_kseg = _kseg_alloc(NULL); 269 if (_kse_initial->k_kseg == NULL) 270 PANIC("Can't allocate initial kseg."); 271 _kse_initial->k_kseg->kg_flags |= KGF_SINGLE_THREAD; 272 _kse_initial->k_schedq = &_kse_initial->k_kseg->kg_schedq; 273 274 TAILQ_INSERT_TAIL(&_kse_initial->k_kseg->kg_kseq, _kse_initial, k_kgqe); 275 _kse_initial->k_kseg->kg_ksecount = 1; 276 277 /* Set the initial thread. */ 278 if (curthread == NULL) { 279 /* Create and initialize the initial thread. */ 280 curthread = _thr_alloc(NULL); 281 if (curthread == NULL) 282 PANIC("Can't allocate initial thread"); 283 _thr_initial = curthread; 284 init_main_thread(curthread); 285 } else { 286 /* 287 * The initial thread is the current thread. It is 288 * assumed that the current thread is already initialized 289 * because it is left over from a fork(). 290 */ 291 _thr_initial = curthread; 292 } 293 _kse_initial->k_kseg->kg_threadcount = 0; 294 _thr_initial->kse = _kse_initial; 295 _thr_initial->kseg = _kse_initial->k_kseg; 296 _thr_initial->active = 1; 297 298 /* 299 * Add the thread to the thread list and to the KSEG's thread 300 * queue. 301 */ 302 THR_LIST_ADD(_thr_initial); 303 KSEG_THRQ_ADD(_kse_initial->k_kseg, _thr_initial); 304 305 /* Setup the KSE/thread specific data for the current KSE/thread. */ 306 _thr_initial->kse->k_curthread = _thr_initial; 307 _kcb_set(_thr_initial->kse->k_kcb); 308 _tcb_set(_thr_initial->kse->k_kcb, _thr_initial->tcb); 309 _thr_initial->kse->k_flags |= KF_INITIALIZED; 310 311 _thr_signal_init(); 312 _kse_critical_leave(&_thr_initial->tcb->tcb_tmbx); 313 /* 314 * activate threaded mode as soon as possible if we are 315 * being debugged 316 */ 317 if (_libkse_debug) 318 _kse_setthreaded(1); 319} 320 321/* 322 * This function and pthread_create() do a lot of the same things. 323 * It'd be nice to consolidate the common stuff in one place. 324 */ 325static void 326init_main_thread(struct pthread *thread) 327{ 328 /* Setup the thread attributes. */ 329 thread->attr = _pthread_attr_default; 330 thread->attr.flags |= PTHREAD_SCOPE_SYSTEM; 331 /* 332 * Set up the thread stack. 333 * 334 * Create a red zone below the main stack. All other stacks 335 * are constrained to a maximum size by the parameters 336 * passed to mmap(), but this stack is only limited by 337 * resource limits, so this stack needs an explicitly mapped 338 * red zone to protect the thread stack that is just beyond. 339 */
| 34 */ 35 36/* Allocate space for global thread variables here: */ 37#define GLOBAL_PTHREAD_PRIVATE 38 39#include "namespace.h" 40#include <sys/param.h> 41#include <sys/types.h> 42#include <sys/signalvar.h> 43#include <machine/reg.h> 44 45#include <sys/ioctl.h> 46#include <sys/mount.h> 47#include <sys/uio.h> 48#include <sys/socket.h> 49#include <sys/event.h> 50#include <sys/stat.h> 51#include <sys/sysctl.h> 52#include <sys/time.h> 53#include <sys/ttycom.h> 54#include <sys/wait.h> 55#include <sys/mman.h> 56#include <dirent.h> 57#include <errno.h> 58#include <fcntl.h> 59#include <paths.h> 60#include <pthread.h> 61#include <pthread_np.h> 62#include <signal.h> 63#include <stdio.h> 64#include <stdlib.h> 65#include <string.h> 66#include <unistd.h> 67#include "un-namespace.h" 68 69#include "libc_private.h" 70#include "thr_private.h" 71 72int __pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *); 73int __pthread_mutex_lock(pthread_mutex_t *); 74int __pthread_mutex_trylock(pthread_mutex_t *); 75void _thread_init_hack(void); 76extern int _thread_state_running; 77 78static void init_private(void); 79static void init_main_thread(struct pthread *thread); 80 81/* 82 * All weak references used within libc should be in this table. 83 * This is so that static libraries will work. 84 */ 85static void *references[] = { 86 &_accept, 87 &_bind, 88 &_close, 89 &_connect, 90 &_dup, 91 &_dup2, 92 &_execve, 93 &_fcntl, 94 &_flock, 95 &_flockfile, 96 &_fstat, 97 &_fstatfs, 98 &_fsync, 99 &_funlockfile, 100 &_getdirentries, 101 &_getlogin, 102 &_getpeername, 103 &_getsockname, 104 &_getsockopt, 105 &_ioctl, 106 &_kevent, 107 &_listen, 108 &_nanosleep, 109 &_open, 110 &_pthread_getspecific, 111 &_pthread_key_create, 112 &_pthread_key_delete, 113 &_pthread_mutex_destroy, 114 &_pthread_mutex_init, 115 &_pthread_mutex_lock, 116 &_pthread_mutex_trylock, 117 &_pthread_mutex_unlock, 118 &_pthread_mutexattr_init, 119 &_pthread_mutexattr_destroy, 120 &_pthread_mutexattr_settype, 121 &_pthread_once, 122 &_pthread_setspecific, 123 &_read, 124 &_readv, 125 &_recvfrom, 126 &_recvmsg, 127 &_select, 128 &_sendmsg, 129 &_sendto, 130 &_setsockopt, 131 &_sigaction, 132 &_sigprocmask, 133 &_sigsuspend, 134 &_socket, 135 &_socketpair, 136 &_thread_init_hack, 137 &_wait4, 138 &_write, 139 &_writev 140}; 141 142/* 143 * These are needed when linking statically. All references within 144 * libgcc (and in the future libc) to these routines are weak, but 145 * if they are not (strongly) referenced by the application or other 146 * libraries, then the actual functions will not be loaded. 147 */ 148static void *libgcc_references[] = { 149 &_pthread_once, 150 &_pthread_key_create, 151 &_pthread_key_delete, 152 &_pthread_getspecific, 153 &_pthread_setspecific, 154 &_pthread_mutex_init, 155 &_pthread_mutex_destroy, 156 &_pthread_mutex_lock, 157 &_pthread_mutex_trylock, 158 &_pthread_mutex_unlock 159}; 160 161#define DUAL_ENTRY(entry) \ 162 (pthread_func_t)entry, (pthread_func_t)entry 163 164static pthread_func_t jmp_table[][2] = { 165 {DUAL_ENTRY(_pthread_cond_broadcast)}, /* PJT_COND_BROADCAST */ 166 {DUAL_ENTRY(_pthread_cond_destroy)}, /* PJT_COND_DESTROY */ 167 {DUAL_ENTRY(_pthread_cond_init)}, /* PJT_COND_INIT */ 168 {DUAL_ENTRY(_pthread_cond_signal)}, /* PJT_COND_SIGNAL */ 169 {(pthread_func_t)__pthread_cond_wait, 170 (pthread_func_t)_pthread_cond_wait}, /* PJT_COND_WAIT */ 171 {DUAL_ENTRY(_pthread_getspecific)}, /* PJT_GETSPECIFIC */ 172 {DUAL_ENTRY(_pthread_key_create)}, /* PJT_KEY_CREATE */ 173 {DUAL_ENTRY(_pthread_key_delete)}, /* PJT_KEY_DELETE*/ 174 {DUAL_ENTRY(_pthread_main_np)}, /* PJT_MAIN_NP */ 175 {DUAL_ENTRY(_pthread_mutex_destroy)}, /* PJT_MUTEX_DESTROY */ 176 {DUAL_ENTRY(_pthread_mutex_init)}, /* PJT_MUTEX_INIT */ 177 {(pthread_func_t)__pthread_mutex_lock, 178 (pthread_func_t)_pthread_mutex_lock}, /* PJT_MUTEX_LOCK */ 179 {(pthread_func_t)__pthread_mutex_trylock, 180 (pthread_func_t)_pthread_mutex_trylock},/* PJT_MUTEX_TRYLOCK */ 181 {DUAL_ENTRY(_pthread_mutex_unlock)}, /* PJT_MUTEX_UNLOCK */ 182 {DUAL_ENTRY(_pthread_mutexattr_destroy)}, /* PJT_MUTEXATTR_DESTROY */ 183 {DUAL_ENTRY(_pthread_mutexattr_init)}, /* PJT_MUTEXATTR_INIT */ 184 {DUAL_ENTRY(_pthread_mutexattr_settype)}, /* PJT_MUTEXATTR_SETTYPE */ 185 {DUAL_ENTRY(_pthread_once)}, /* PJT_ONCE */ 186 {DUAL_ENTRY(_pthread_rwlock_destroy)}, /* PJT_RWLOCK_DESTROY */ 187 {DUAL_ENTRY(_pthread_rwlock_init)}, /* PJT_RWLOCK_INIT */ 188 {DUAL_ENTRY(_pthread_rwlock_rdlock)}, /* PJT_RWLOCK_RDLOCK */ 189 {DUAL_ENTRY(_pthread_rwlock_tryrdlock)},/* PJT_RWLOCK_TRYRDLOCK */ 190 {DUAL_ENTRY(_pthread_rwlock_trywrlock)},/* PJT_RWLOCK_TRYWRLOCK */ 191 {DUAL_ENTRY(_pthread_rwlock_unlock)}, /* PJT_RWLOCK_UNLOCK */ 192 {DUAL_ENTRY(_pthread_rwlock_wrlock)}, /* PJT_RWLOCK_WRLOCK */ 193 {DUAL_ENTRY(_pthread_self)}, /* PJT_SELF */ 194 {DUAL_ENTRY(_pthread_setspecific)}, /* PJT_SETSPECIFIC */ 195 {DUAL_ENTRY(_pthread_sigmask)} /* PJT_SIGMASK */ 196}; 197 198static int init_once = 0; 199 200/* 201 * Threaded process initialization. 202 * 203 * This is only called under two conditions: 204 * 205 * 1) Some thread routines have detected that the library hasn't yet 206 * been initialized (_thr_initial == NULL && curthread == NULL), or 207 * 208 * 2) An explicit call to reinitialize after a fork (indicated 209 * by curthread != NULL) 210 */ 211void 212_libpthread_init(struct pthread *curthread) 213{ 214 int fd; 215 216 /* Check if this function has already been called: */ 217 if ((_thr_initial != NULL) && (curthread == NULL)) 218 /* Only initialize the threaded application once. */ 219 return; 220 221 /* 222 * Make gcc quiescent about {,libgcc_}references not being 223 * referenced: 224 */ 225 if ((references[0] == NULL) || (libgcc_references[0] == NULL)) 226 PANIC("Failed loading mandatory references in _thread_init"); 227 228 /* Pull debug symbols in for static binary */ 229 _thread_state_running = PS_RUNNING; 230 231 /* 232 * Check the size of the jump table to make sure it is preset 233 * with the correct number of entries. 234 */ 235 if (sizeof(jmp_table) != (sizeof(pthread_func_t) * PJT_MAX * 2)) 236 PANIC("Thread jump table not properly initialized"); 237 memcpy(__thr_jtable, jmp_table, sizeof(jmp_table)); 238 239 /* 240 * Check for the special case of this process running as 241 * or in place of init as pid = 1: 242 */ 243 if ((_thr_pid = getpid()) == 1) { 244 /* 245 * Setup a new session for this process which is 246 * assumed to be running as root. 247 */ 248 if (setsid() == -1) 249 PANIC("Can't set session ID"); 250 if (revoke(_PATH_CONSOLE) != 0) 251 PANIC("Can't revoke console"); 252 if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0) 253 PANIC("Can't open console"); 254 if (setlogin("root") == -1) 255 PANIC("Can't set login to root"); 256 if (__sys_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1) 257 PANIC("Can't set controlling terminal"); 258 } 259 260 /* Initialize pthread private data. */ 261 init_private(); 262 _kse_init(); 263 264 /* Initialize the initial kse and kseg. */ 265 _kse_initial = _kse_alloc(NULL, _thread_scope_system > 0); 266 if (_kse_initial == NULL) 267 PANIC("Can't allocate initial kse."); 268 _kse_initial->k_kseg = _kseg_alloc(NULL); 269 if (_kse_initial->k_kseg == NULL) 270 PANIC("Can't allocate initial kseg."); 271 _kse_initial->k_kseg->kg_flags |= KGF_SINGLE_THREAD; 272 _kse_initial->k_schedq = &_kse_initial->k_kseg->kg_schedq; 273 274 TAILQ_INSERT_TAIL(&_kse_initial->k_kseg->kg_kseq, _kse_initial, k_kgqe); 275 _kse_initial->k_kseg->kg_ksecount = 1; 276 277 /* Set the initial thread. */ 278 if (curthread == NULL) { 279 /* Create and initialize the initial thread. */ 280 curthread = _thr_alloc(NULL); 281 if (curthread == NULL) 282 PANIC("Can't allocate initial thread"); 283 _thr_initial = curthread; 284 init_main_thread(curthread); 285 } else { 286 /* 287 * The initial thread is the current thread. It is 288 * assumed that the current thread is already initialized 289 * because it is left over from a fork(). 290 */ 291 _thr_initial = curthread; 292 } 293 _kse_initial->k_kseg->kg_threadcount = 0; 294 _thr_initial->kse = _kse_initial; 295 _thr_initial->kseg = _kse_initial->k_kseg; 296 _thr_initial->active = 1; 297 298 /* 299 * Add the thread to the thread list and to the KSEG's thread 300 * queue. 301 */ 302 THR_LIST_ADD(_thr_initial); 303 KSEG_THRQ_ADD(_kse_initial->k_kseg, _thr_initial); 304 305 /* Setup the KSE/thread specific data for the current KSE/thread. */ 306 _thr_initial->kse->k_curthread = _thr_initial; 307 _kcb_set(_thr_initial->kse->k_kcb); 308 _tcb_set(_thr_initial->kse->k_kcb, _thr_initial->tcb); 309 _thr_initial->kse->k_flags |= KF_INITIALIZED; 310 311 _thr_signal_init(); 312 _kse_critical_leave(&_thr_initial->tcb->tcb_tmbx); 313 /* 314 * activate threaded mode as soon as possible if we are 315 * being debugged 316 */ 317 if (_libkse_debug) 318 _kse_setthreaded(1); 319} 320 321/* 322 * This function and pthread_create() do a lot of the same things. 323 * It'd be nice to consolidate the common stuff in one place. 324 */ 325static void 326init_main_thread(struct pthread *thread) 327{ 328 /* Setup the thread attributes. */ 329 thread->attr = _pthread_attr_default; 330 thread->attr.flags |= PTHREAD_SCOPE_SYSTEM; 331 /* 332 * Set up the thread stack. 333 * 334 * Create a red zone below the main stack. All other stacks 335 * are constrained to a maximum size by the parameters 336 * passed to mmap(), but this stack is only limited by 337 * resource limits, so this stack needs an explicitly mapped 338 * red zone to protect the thread stack that is just beyond. 339 */
|