1bb535300SJeff Roberson /* 2bb535300SJeff Roberson * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> 3bb535300SJeff Roberson * All rights reserved. 4bb535300SJeff Roberson * 5bb535300SJeff Roberson * Redistribution and use in source and binary forms, with or without 6bb535300SJeff Roberson * modification, are permitted provided that the following conditions 7bb535300SJeff Roberson * are met: 8bb535300SJeff Roberson * 1. Redistributions of source code must retain the above copyright 9bb535300SJeff Roberson * notice, this list of conditions and the following disclaimer. 10bb535300SJeff Roberson * 2. Redistributions in binary form must reproduce the above copyright 11bb535300SJeff Roberson * notice, this list of conditions and the following disclaimer in the 12bb535300SJeff Roberson * documentation and/or other materials provided with the distribution. 13bb535300SJeff Roberson * 3. All advertising materials mentioning features or use of this software 14bb535300SJeff Roberson * must display the following acknowledgement: 15bb535300SJeff Roberson * This product includes software developed by John Birrell. 16bb535300SJeff Roberson * 4. Neither the name of the author nor the names of any co-contributors 17bb535300SJeff Roberson * may be used to endorse or promote products derived from this software 18bb535300SJeff Roberson * without specific prior written permission. 19bb535300SJeff Roberson * 20bb535300SJeff Roberson * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 21bb535300SJeff Roberson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22bb535300SJeff Roberson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23bb535300SJeff Roberson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24bb535300SJeff Roberson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25bb535300SJeff Roberson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26bb535300SJeff Roberson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27bb535300SJeff Roberson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28bb535300SJeff Roberson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29bb535300SJeff Roberson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30bb535300SJeff Roberson * SUCH DAMAGE. 31bb535300SJeff Roberson * 32bb535300SJeff Roberson * $FreeBSD$ 33bb535300SJeff Roberson */ 34bb535300SJeff Roberson 35bb535300SJeff Roberson /* Allocate space for global thread variables here: */ 36bb535300SJeff Roberson #define GLOBAL_PTHREAD_PRIVATE 37bb535300SJeff Roberson 38bb535300SJeff Roberson #include "namespace.h" 39bb535300SJeff Roberson #include <sys/param.h> 40bb535300SJeff Roberson #include <sys/types.h> 41bb535300SJeff Roberson #include <machine/reg.h> 42bb535300SJeff Roberson 43bb535300SJeff Roberson #include <sys/ioctl.h> 44bb535300SJeff Roberson #include <sys/mount.h> 45bb535300SJeff Roberson #include <sys/uio.h> 46bb535300SJeff Roberson #include <sys/socket.h> 47bb535300SJeff Roberson #include <sys/event.h> 48bb535300SJeff Roberson #include <sys/stat.h> 49bb535300SJeff Roberson #include <sys/sysctl.h> 50bb535300SJeff Roberson #include <sys/time.h> 51bb535300SJeff Roberson #include <sys/ttycom.h> 52bb535300SJeff Roberson #include <sys/user.h> 53bb535300SJeff Roberson #include <sys/wait.h> 54bb535300SJeff Roberson #include <sys/mman.h> 55bb535300SJeff Roberson #include <dirent.h> 56bb535300SJeff Roberson #include <errno.h> 57bb535300SJeff Roberson #include <fcntl.h> 58bb535300SJeff Roberson #include <paths.h> 59bb535300SJeff Roberson #include <pthread.h> 60bb535300SJeff Roberson #include <signal.h> 61bb535300SJeff Roberson #include <stdio.h> 62bb535300SJeff Roberson #include <stdlib.h> 63bb535300SJeff Roberson #include <string.h> 64bb535300SJeff Roberson #include <unistd.h> 65bb535300SJeff Roberson #include "un-namespace.h" 66bb535300SJeff Roberson 67bb535300SJeff Roberson #include "thr_private.h" 68bb535300SJeff Roberson 697c916264SJohn Polstra /* 707c916264SJohn Polstra * Early implementations of sigtimedwait interpreted the signal 717c916264SJohn Polstra * set incorrectly. 727c916264SJohn Polstra */ 737c916264SJohn Polstra #define SIGTIMEDWAIT_SET_IS_INVERTED(osreldate) \ 747c916264SJohn Polstra ((500100 <= (osreldate) && (osreldate) <= 500113) || \ 757c916264SJohn Polstra (osreldate) == 501000 || (osreldate) == 501100) 767c916264SJohn Polstra 774dee39feSMike Makonnen extern void _thread_init_hack(void); 784dee39feSMike Makonnen 79bb535300SJeff Roberson /* 80bb535300SJeff Roberson * All weak references used within libc should be in this table. 81bb535300SJeff Roberson * This will is so that static libraries will work. 82bb535300SJeff Roberson * 83bb535300SJeff Roberson * XXXTHR - Check this list. 84bb535300SJeff Roberson */ 85bb535300SJeff Roberson static void *references[] = { 864dee39feSMike Makonnen &_thread_init_hack, 874dee39feSMike Makonnen &_thread_init, 88bb535300SJeff Roberson &_accept, 89bb535300SJeff Roberson &_bind, 90bb535300SJeff Roberson &_close, 91bb535300SJeff Roberson &_connect, 92bb535300SJeff Roberson &_dup, 93bb535300SJeff Roberson &_dup2, 94bb535300SJeff Roberson &_execve, 95bb535300SJeff Roberson &_fcntl, 96bb535300SJeff Roberson &_flock, 97bb535300SJeff Roberson &_flockfile, 98bb535300SJeff Roberson &_fstat, 99bb535300SJeff Roberson &_fstatfs, 100bb535300SJeff Roberson &_fsync, 101bb535300SJeff Roberson &_funlockfile, 102bb535300SJeff Roberson &_getdirentries, 103bb535300SJeff Roberson &_getlogin, 104bb535300SJeff Roberson &_getpeername, 105bb535300SJeff Roberson &_getsockname, 106bb535300SJeff Roberson &_getsockopt, 107bb535300SJeff Roberson &_ioctl, 108bb535300SJeff Roberson &_kevent, 109bb535300SJeff Roberson &_listen, 110bb535300SJeff Roberson &_nanosleep, 111bb535300SJeff Roberson &_open, 112bb535300SJeff Roberson &_pthread_getspecific, 113bb535300SJeff Roberson &_pthread_key_create, 114bb535300SJeff Roberson &_pthread_key_delete, 115bb535300SJeff Roberson &_pthread_mutex_destroy, 116bb535300SJeff Roberson &_pthread_mutex_init, 117bb535300SJeff Roberson &_pthread_mutex_lock, 118bb535300SJeff Roberson &_pthread_mutex_trylock, 119bb535300SJeff Roberson &_pthread_mutex_unlock, 120bb535300SJeff Roberson &_pthread_mutexattr_init, 121bb535300SJeff Roberson &_pthread_mutexattr_destroy, 122bb535300SJeff Roberson &_pthread_mutexattr_settype, 123bb535300SJeff Roberson &_pthread_once, 124bb535300SJeff Roberson &_pthread_setspecific, 125bb535300SJeff Roberson &_read, 126bb535300SJeff Roberson &_readv, 127bb535300SJeff Roberson &_recvfrom, 128bb535300SJeff Roberson &_recvmsg, 129bb535300SJeff Roberson &_select, 130bb535300SJeff Roberson &_sendmsg, 131bb535300SJeff Roberson &_sendto, 132bb535300SJeff Roberson &_setsockopt, 133bb535300SJeff Roberson &_sigaction, 134bb535300SJeff Roberson &_sigprocmask, 135bb535300SJeff Roberson &_sigsuspend, 136bb535300SJeff Roberson &_socket, 137bb535300SJeff Roberson &_socketpair, 138bb535300SJeff Roberson &_wait4, 139bb535300SJeff Roberson &_write, 140bb535300SJeff Roberson &_writev 141bb535300SJeff Roberson }; 142bb535300SJeff Roberson 143bb535300SJeff Roberson /* 144bb535300SJeff Roberson * These are needed when linking statically. All references within 145bb535300SJeff Roberson * libgcc (and in the future libc) to these routines are weak, but 146bb535300SJeff Roberson * if they are not (strongly) referenced by the application or other 147bb535300SJeff Roberson * libraries, then the actual functions will not be loaded. 148bb535300SJeff Roberson */ 149bb535300SJeff Roberson static void *libgcc_references[] = { 1504dee39feSMike Makonnen &_thread_init_hack, 1514dee39feSMike Makonnen &_thread_init, 152bb535300SJeff Roberson &_pthread_once, 153bb535300SJeff Roberson &_pthread_key_create, 154bb535300SJeff Roberson &_pthread_key_delete, 155bb535300SJeff Roberson &_pthread_getspecific, 156bb535300SJeff Roberson &_pthread_setspecific, 157bb535300SJeff Roberson &_pthread_mutex_init, 158bb535300SJeff Roberson &_pthread_mutex_destroy, 159bb535300SJeff Roberson &_pthread_mutex_lock, 160bb535300SJeff Roberson &_pthread_mutex_trylock, 161bb535300SJeff Roberson &_pthread_mutex_unlock 162bb535300SJeff Roberson }; 163bb535300SJeff Roberson 164bb535300SJeff Roberson int _pthread_guard_default; 165bb535300SJeff Roberson int _pthread_page_size; 166bb535300SJeff Roberson 167bb535300SJeff Roberson /* 168f2c3dd08SMike Makonnen * Initialize the current thread. 169f2c3dd08SMike Makonnen */ 170f2c3dd08SMike Makonnen void 171f2c3dd08SMike Makonnen init_td_common(struct pthread *td, struct pthread_attr *attrp, int reinit) 172f2c3dd08SMike Makonnen { 173f2c3dd08SMike Makonnen /* 174f2c3dd08SMike Makonnen * Some parts of a pthread are initialized only once. 175f2c3dd08SMike Makonnen */ 176f2c3dd08SMike Makonnen if (!reinit) { 177f2c3dd08SMike Makonnen memset(td, 0, sizeof(struct pthread)); 178f2c3dd08SMike Makonnen td->cancelflags = PTHREAD_CANCEL_ENABLE | 179f2c3dd08SMike Makonnen PTHREAD_CANCEL_DEFERRED; 180f2c3dd08SMike Makonnen memcpy(&td->attr, attrp, sizeof(struct pthread_attr)); 181f2c3dd08SMike Makonnen td->magic = PTHREAD_MAGIC; 182f2c3dd08SMike Makonnen TAILQ_INIT(&td->mutexq); 183f2c3dd08SMike Makonnen } else { 184f2c3dd08SMike Makonnen memset(&td->join_status, 0, sizeof(struct join_status)); 185f2c3dd08SMike Makonnen } 186f2c3dd08SMike Makonnen td->joiner = NULL; 187f2c3dd08SMike Makonnen td->error = 0; 188f2c3dd08SMike Makonnen td->flags = 0; 189f2c3dd08SMike Makonnen } 190f2c3dd08SMike Makonnen 191f2c3dd08SMike Makonnen /* 192f2c3dd08SMike Makonnen * Initialize the active and dead threads list. Any threads in the active 193f2c3dd08SMike Makonnen * list will be removed and the thread td * will be marked as the 194f2c3dd08SMike Makonnen * initial thread and inserted in the list as the only thread. Any threads 195f2c3dd08SMike Makonnen * in the dead threads list will also be removed. 196f2c3dd08SMike Makonnen */ 197f2c3dd08SMike Makonnen void 198f2c3dd08SMike Makonnen init_tdlist(struct pthread *td, int reinit) 199f2c3dd08SMike Makonnen { 200f2c3dd08SMike Makonnen struct pthread *tdTemp, *tdTemp2; 201f2c3dd08SMike Makonnen 202f2c3dd08SMike Makonnen _thread_initial = td; 203f2c3dd08SMike Makonnen td->name = strdup("_thread_initial"); 204f2c3dd08SMike Makonnen 205f2c3dd08SMike Makonnen /* 206f2c3dd08SMike Makonnen * If this is not the first initialization, remove any entries 207f2c3dd08SMike Makonnen * that may be in the list and deallocate their memory. Also 208f2c3dd08SMike Makonnen * destroy any global pthread primitives (they will be recreated). 209f2c3dd08SMike Makonnen */ 210f2c3dd08SMike Makonnen if (reinit) { 211f2c3dd08SMike Makonnen TAILQ_FOREACH_SAFE(tdTemp, &_thread_list, tle, tdTemp2) { 212f2c3dd08SMike Makonnen if (tdTemp != NULL) { 213f2c3dd08SMike Makonnen TAILQ_REMOVE(&_thread_list, tdTemp, tle); 214f2c3dd08SMike Makonnen free(tdTemp); 215f2c3dd08SMike Makonnen } 216f2c3dd08SMike Makonnen } 217f2c3dd08SMike Makonnen TAILQ_FOREACH_SAFE(tdTemp, &_dead_list, dle, tdTemp2) { 218f2c3dd08SMike Makonnen if (tdTemp != NULL) { 219f2c3dd08SMike Makonnen TAILQ_REMOVE(&_dead_list, tdTemp, dle); 220f2c3dd08SMike Makonnen free(tdTemp); 221f2c3dd08SMike Makonnen } 222f2c3dd08SMike Makonnen } 223f2c3dd08SMike Makonnen _pthread_mutex_destroy(&dead_list_lock); 224f2c3dd08SMike Makonnen _pthread_cond_destroy(&_gc_cond); 225f2c3dd08SMike Makonnen } else { 226f2c3dd08SMike Makonnen TAILQ_INIT(&_thread_list); 227f2c3dd08SMike Makonnen TAILQ_INIT(&_dead_list); 228f2c3dd08SMike Makonnen } 229f2c3dd08SMike Makonnen 230f2c3dd08SMike Makonnen /* Insert this thread as the first thread in the active list */ 231f2c3dd08SMike Makonnen TAILQ_INSERT_HEAD(&_thread_list, td, tle); 232f2c3dd08SMike Makonnen 233f2c3dd08SMike Makonnen /* 234f2c3dd08SMike Makonnen * Initialize the active thread list lock and the 235f2c3dd08SMike Makonnen * dead threads list lock & associated condition variable. 236f2c3dd08SMike Makonnen */ 237f2c3dd08SMike Makonnen memset(&thread_list_lock, 0, sizeof(spinlock_t)); 238f2c3dd08SMike Makonnen if (_pthread_mutex_init(&dead_list_lock,NULL) != 0 || 239f2c3dd08SMike Makonnen _pthread_cond_init(&_gc_cond,NULL) != 0) 240f2c3dd08SMike Makonnen PANIC("Failed to initialize garbage collector primitives"); 241f2c3dd08SMike Makonnen } 242f2c3dd08SMike Makonnen 243f2c3dd08SMike Makonnen /* 244bb535300SJeff Roberson * Threaded process initialization 245bb535300SJeff Roberson */ 246bb535300SJeff Roberson void 247bb535300SJeff Roberson _thread_init(void) 248bb535300SJeff Roberson { 249bb535300SJeff Roberson struct pthread *pthread; 250bb535300SJeff Roberson int fd; 251bb535300SJeff Roberson int i; 252bb535300SJeff Roberson size_t len; 253bb535300SJeff Roberson int mib[2]; 254bb535300SJeff Roberson sigset_t set; 2557c916264SJohn Polstra int osreldate; 25612c407a4SMike Makonnen int error; 257bb535300SJeff Roberson 258bb535300SJeff Roberson struct clockinfo clockinfo; 259bb535300SJeff Roberson struct sigaction act; 260bb535300SJeff Roberson 261bb535300SJeff Roberson /* Check if this function has already been called: */ 262bb535300SJeff Roberson if (_thread_initial) 263bb535300SJeff Roberson /* Only initialise the threaded application once. */ 264bb535300SJeff Roberson return; 265bb535300SJeff Roberson 266bb535300SJeff Roberson _pthread_page_size = getpagesize(); 267bb535300SJeff Roberson _pthread_guard_default = getpagesize(); 268bb535300SJeff Roberson 269bb535300SJeff Roberson pthread_attr_default.guardsize_attr = _pthread_guard_default; 270bb535300SJeff Roberson 271bb535300SJeff Roberson 272bb535300SJeff Roberson /* 273bb535300SJeff Roberson * Make gcc quiescent about {,libgcc_}references not being 274bb535300SJeff Roberson * referenced: 275bb535300SJeff Roberson */ 276bb535300SJeff Roberson if ((references[0] == NULL) || (libgcc_references[0] == NULL)) 277bb535300SJeff Roberson PANIC("Failed loading mandatory references in _thread_init"); 278bb535300SJeff Roberson 279bb535300SJeff Roberson /* 280bb535300SJeff Roberson * Check for the special case of this process running as 281bb535300SJeff Roberson * or in place of init as pid = 1: 282bb535300SJeff Roberson */ 283bb535300SJeff Roberson if (getpid() == 1) { 284bb535300SJeff Roberson /* 285bb535300SJeff Roberson * Setup a new session for this process which is 286bb535300SJeff Roberson * assumed to be running as root. 287bb535300SJeff Roberson */ 288bb535300SJeff Roberson if (setsid() == -1) 289bb535300SJeff Roberson PANIC("Can't set session ID"); 290bb535300SJeff Roberson if (revoke(_PATH_CONSOLE) != 0) 291bb535300SJeff Roberson PANIC("Can't revoke console"); 292bb535300SJeff Roberson if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0) 293bb535300SJeff Roberson PANIC("Can't open console"); 294bb535300SJeff Roberson if (setlogin("root") == -1) 295bb535300SJeff Roberson PANIC("Can't set login to root"); 296bb535300SJeff Roberson if (__sys_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1) 297bb535300SJeff Roberson PANIC("Can't set controlling terminal"); 298bb535300SJeff Roberson if (__sys_dup2(fd, 0) == -1 || 299bb535300SJeff Roberson __sys_dup2(fd, 1) == -1 || 300bb535300SJeff Roberson __sys_dup2(fd, 2) == -1) 301bb535300SJeff Roberson PANIC("Can't dup2"); 302bb535300SJeff Roberson } 303bb535300SJeff Roberson 304bb535300SJeff Roberson /* Allocate memory for the thread structure of the initial thread: */ 305bb535300SJeff Roberson if ((pthread = (pthread_t) malloc(sizeof(struct pthread))) == NULL) { 306bb535300SJeff Roberson /* 307bb535300SJeff Roberson * Insufficient memory to initialise this application, so 308bb535300SJeff Roberson * abort: 309bb535300SJeff Roberson */ 310bb535300SJeff Roberson PANIC("Cannot allocate memory for initial thread"); 311bb535300SJeff Roberson } 3123f07b4bcSMike Makonnen 313f2c3dd08SMike Makonnen init_tdlist(pthread, 0); 314f2c3dd08SMike Makonnen init_td_common(pthread, &pthread_attr_default, 0); 31512c407a4SMike Makonnen pthread->arch_id = _set_curthread(NULL, pthread, &error); 316bb535300SJeff Roberson 317bb535300SJeff Roberson /* Get our thread id. */ 318bb535300SJeff Roberson thr_self(&pthread->thr_id); 319bb535300SJeff Roberson 320bb535300SJeff Roberson /* Find the stack top */ 321bb535300SJeff Roberson mib[0] = CTL_KERN; 322bb535300SJeff Roberson mib[1] = KERN_USRSTACK; 323bb535300SJeff Roberson len = sizeof (_usrstack); 324bb535300SJeff Roberson if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) == -1) 325bb535300SJeff Roberson _usrstack = (void *)USRSTACK; 326bb535300SJeff Roberson /* 327bb535300SJeff Roberson * Create a red zone below the main stack. All other stacks are 328bb535300SJeff Roberson * constrained to a maximum size by the paramters passed to 329bb535300SJeff Roberson * mmap(), but this stack is only limited by resource limits, so 330bb535300SJeff Roberson * this stack needs an explicitly mapped red zone to protect the 331bb535300SJeff Roberson * thread stack that is just beyond. 332bb535300SJeff Roberson */ 333bb535300SJeff Roberson if (mmap(_usrstack - PTHREAD_STACK_INITIAL - 334bb535300SJeff Roberson _pthread_guard_default, _pthread_guard_default, 0, 335bb535300SJeff Roberson MAP_ANON, -1, 0) == MAP_FAILED) 336bb535300SJeff Roberson PANIC("Cannot allocate red zone for initial thread"); 337bb535300SJeff Roberson 338bb535300SJeff Roberson /* Set the main thread stack pointer. */ 339bb535300SJeff Roberson pthread->stack = _usrstack - PTHREAD_STACK_INITIAL; 340bb535300SJeff Roberson 341bb535300SJeff Roberson /* Set the stack attributes. */ 342bb535300SJeff Roberson pthread->attr.stackaddr_attr = pthread->stack; 343bb535300SJeff Roberson pthread->attr.stacksize_attr = PTHREAD_STACK_INITIAL; 344bb535300SJeff Roberson 345bb535300SJeff Roberson /* Setup the context for initial thread. */ 346bb535300SJeff Roberson getcontext(&pthread->ctx); 347bb535300SJeff Roberson pthread->ctx.uc_stack.ss_sp = pthread->stack; 348bb535300SJeff Roberson pthread->ctx.uc_stack.ss_size = PTHREAD_STACK_INITIAL; 349bb535300SJeff Roberson 350bb535300SJeff Roberson /* Default the priority of the initial thread: */ 351bb535300SJeff Roberson pthread->base_priority = PTHREAD_DEFAULT_PRIORITY; 352bb535300SJeff Roberson pthread->active_priority = PTHREAD_DEFAULT_PRIORITY; 353bb535300SJeff Roberson pthread->inherited_priority = 0; 354bb535300SJeff Roberson 355bb535300SJeff Roberson /* Initialise the state of the initial thread: */ 356bb535300SJeff Roberson pthread->state = PS_RUNNING; 357bb535300SJeff Roberson 358bb535300SJeff Roberson /* Enter a loop to get the existing signal status: */ 359bb535300SJeff Roberson for (i = 1; i < NSIG; i++) { 360bb535300SJeff Roberson /* Check for signals which cannot be trapped. */ 361bb535300SJeff Roberson if (i == SIGKILL || i == SIGSTOP) 362bb535300SJeff Roberson continue; 363bb535300SJeff Roberson 364bb535300SJeff Roberson /* Get the signal handler details. */ 365bb535300SJeff Roberson if (__sys_sigaction(i, NULL, 366bb535300SJeff Roberson &_thread_sigact[i - 1]) != 0) 367bb535300SJeff Roberson PANIC("Cannot read signal handler info"); 368bb535300SJeff Roberson } 369bb535300SJeff Roberson act.sa_sigaction = _thread_sig_wrapper; 370bb535300SJeff Roberson act.sa_flags = SA_SIGINFO; 371bb535300SJeff Roberson SIGFILLSET(act.sa_mask); 372bb535300SJeff Roberson 373bb535300SJeff Roberson if (__sys_sigaction(SIGTHR, &act, NULL)) 374bb535300SJeff Roberson PANIC("Cannot set SIGTHR handler.\n"); 375bb535300SJeff Roberson 376bb535300SJeff Roberson SIGEMPTYSET(set); 377bb535300SJeff Roberson SIGADDSET(set, SIGTHR); 378bb535300SJeff Roberson __sys_sigprocmask(SIG_BLOCK, &set, 0); 379bb535300SJeff Roberson 3807c916264SJohn Polstra /* 3817c916264SJohn Polstra * Precompute the signal set used by _thread_suspend to wait 3827c916264SJohn Polstra * for SIGTHR. 3837c916264SJohn Polstra */ 3847c916264SJohn Polstra mib[0] = CTL_KERN; 3857c916264SJohn Polstra mib[1] = KERN_OSRELDATE; 3867c916264SJohn Polstra len = sizeof(osreldate); 3877c916264SJohn Polstra if (sysctl(mib, 2, &osreldate, &len, NULL, 0) == 0 && 3887c916264SJohn Polstra SIGTIMEDWAIT_SET_IS_INVERTED(osreldate)) { 3897c916264SJohn Polstra /* Kernel bug requires an inverted signal set. */ 3907c916264SJohn Polstra SIGFILLSET(_thread_suspend_sigset); 3917c916264SJohn Polstra SIGDELSET(_thread_suspend_sigset, SIGTHR); 3927c916264SJohn Polstra } else { 3937c916264SJohn Polstra SIGEMPTYSET(_thread_suspend_sigset); 3947c916264SJohn Polstra SIGADDSET(_thread_suspend_sigset, SIGTHR); 3957c916264SJohn Polstra } 396393441d4SMike Makonnen #ifdef _PTHREADS_INVARIANTS 397393441d4SMike Makonnen SIGADDSET(_thread_suspend_sigset, SIGALRM); 398393441d4SMike Makonnen #endif 3997c916264SJohn Polstra 400bb535300SJeff Roberson /* Get the kernel clockrate: */ 401bb535300SJeff Roberson mib[0] = CTL_KERN; 402bb535300SJeff Roberson mib[1] = KERN_CLOCKRATE; 403bb535300SJeff Roberson len = sizeof (struct clockinfo); 404bb535300SJeff Roberson if (sysctl(mib, 2, &clockinfo, &len, NULL, 0) == 0) 405bb535300SJeff Roberson _clock_res_usec = clockinfo.tick > CLOCK_RES_USEC_MIN ? 406bb535300SJeff Roberson clockinfo.tick : CLOCK_RES_USEC_MIN; 407bb535300SJeff Roberson } 408bb535300SJeff Roberson 409bb535300SJeff Roberson /* 410bb535300SJeff Roberson * Special start up code for NetBSD/Alpha 411bb535300SJeff Roberson */ 412bb535300SJeff Roberson #if defined(__NetBSD__) && defined(__alpha__) 413bb535300SJeff Roberson int 414bb535300SJeff Roberson main(int argc, char *argv[], char *env); 415bb535300SJeff Roberson 416bb535300SJeff Roberson int 417bb535300SJeff Roberson _thread_main(int argc, char *argv[], char *env) 418bb535300SJeff Roberson { 419bb535300SJeff Roberson _thread_init(); 420bb535300SJeff Roberson return (main(argc, argv, env)); 421bb535300SJeff Roberson } 422bb535300SJeff Roberson #endif 423