thr_init.c revision 22315
1/* 2 * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by John Birrell. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 */ 33 34/* Allocate space for global thread variables here: */ 35#define GLOBAL_PTHREAD_PRIVATE 36 37#include <errno.h> 38#include <stdlib.h> 39#include <string.h> 40#include <fcntl.h> 41#include <unistd.h> 42#include <sys/time.h> 43#ifdef _THREAD_SAFE 44#include <machine/reg.h> 45#include <pthread.h> 46#include "pthread_private.h" 47extern int _thread_autoinit_dummy_decl; 48 49/* 50 * Threaded process initialization 51 */ 52void 53_thread_init(void) 54{ 55 int flags; 56 int i; 57 struct sigaction act; 58 59 /* Ensure that the auto-initialization routine is linked in: */ 60 _thread_autoinit_dummy_decl = 1; 61 62 /* Check if this function has already been called: */ 63 if (_thread_initial) 64 /* Only initialise the threaded application once. */ 65 return; 66 67 /* Get the standard I/O flags before messing with them : */ 68 for (i = 0; i < 3; i++) 69 if ((_pthread_stdio_flags[i] = 70 _thread_sys_fcntl(i,F_GETFL, NULL)) == -1) 71 PANIC("Cannot get stdio flags"); 72 73 /* 74 * Create a pipe that is written to by the signal handler to prevent 75 * signals being missed in calls to _thread_sys_select: 76 */ 77 if (_thread_sys_pipe(_thread_kern_pipe) != 0) { 78 /* Cannot create pipe, so abort: */ 79 PANIC("Cannot create kernel pipe"); 80 } 81 /* Get the flags for the read pipe: */ 82 else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) { 83 /* Abort this application: */ 84 PANIC("Cannot get kernel read pipe flags"); 85 } 86 /* Make the read pipe non-blocking: */ 87 else if (_thread_sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) { 88 /* Abort this application: */ 89 PANIC("Cannot make kernel read pipe non-blocking"); 90 } 91 /* Get the flags for the write pipe: */ 92 else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) { 93 /* Abort this application: */ 94 PANIC("Cannot get kernel write pipe flags"); 95 } 96 /* Make the write pipe non-blocking: */ 97 else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) { 98 /* Abort this application: */ 99 PANIC("Cannot get kernel write pipe flags"); 100 } 101 /* Allocate memory for the thread structure of the initial thread: */ 102 else if ((_thread_initial = (pthread_t) malloc(sizeof(struct pthread))) == NULL) { 103 /* 104 * Insufficient memory to initialise this application, so 105 * abort: 106 */ 107 PANIC("Cannot allocate memory for initial thread"); 108 } else { 109 /* Zero the global kernel thread structure: */ 110 memset(&_thread_kern_thread, 0, sizeof(struct pthread)); 111 memset(_thread_initial, 0, sizeof(struct pthread)); 112 113 /* Default the priority of the initial thread: */ 114 _thread_initial->pthread_priority = PTHREAD_DEFAULT_PRIORITY; 115 116 /* Initialise the state of the initial thread: */ 117 _thread_initial->state = PS_RUNNING; 118 119 /* Initialise the queue: */ 120 _thread_queue_init(&(_thread_initial->join_queue)); 121 122 /* Initialise the rest of the fields: */ 123 _thread_initial->parent_thread = NULL; 124 _thread_initial->specific_data = NULL; 125 _thread_initial->cleanup = NULL; 126 _thread_initial->queue = NULL; 127 _thread_initial->qnxt = NULL; 128 _thread_initial->nxt = NULL; 129 _thread_initial->flags = 0; 130 _thread_initial->error = 0; 131 _thread_link_list = _thread_initial; 132 _thread_run = _thread_initial; 133 134 /* Enter a loop to get the existing signal status: */ 135 for (i = 1; i < NSIG; i++) { 136 /* Check for signals which cannot be trapped: */ 137 if (i == SIGKILL || i == SIGSTOP) { 138 } 139 /* Get the signal handler details: */ 140 else if (_thread_sys_sigaction(i, NULL, &act) != 0) { 141 /* 142 * Abort this process if signal 143 * initialisation fails: 144 */ 145 PANIC("Cannot read signal handler info"); 146 } 147 /* Set the signal handler for the initial thread: */ 148 else if (sigaction(i, &act, NULL) != 0) { 149 /* 150 * Abort this process if signal 151 * initialisation fails: 152 */ 153 PANIC("Cannot initialise signal handler for initial thread"); 154 } 155 } 156 157 /* Initialise the global signal action structure: */ 158 sigfillset(&act.sa_mask); 159 act.sa_handler = (void (*) ()) _thread_sig_handler; 160 act.sa_flags = SA_RESTART; 161 162 /* Enter a loop to initialise the rest of the signals: */ 163 for (i = 1; i < NSIG; i++) { 164 /* Check for signals which cannot be trapped: */ 165 if (i == SIGKILL || i == SIGSTOP) { 166 } 167 /* Initialise the signal for default handling: */ 168 else if (_thread_sys_sigaction(i, &act, NULL) != 0) { 169 /* 170 * Abort this process if signal 171 * initialisation fails: 172 */ 173 PANIC("Cannot initialise signal handler"); 174 } 175 } 176 177 /* Get the table size: */ 178 if ((_thread_dtablesize = getdtablesize()) < 0) { 179 /* 180 * Cannot get the system defined table size, so abort 181 * this process. 182 */ 183 PANIC("Cannot get dtablesize"); 184 } 185 /* Allocate memory for the file descriptor table: */ 186 if ((_thread_fd_table = (struct fd_table_entry **) malloc(sizeof(struct fd_table_entry) * _thread_dtablesize)) == NULL) { 187 /* 188 * Cannot allocate memory for the file descriptor 189 * table, so abort this process. 190 */ 191 PANIC("Cannot allocate memory for file descriptor table"); 192 } else { 193 /* 194 * Enter a loop to initialise the file descriptor 195 * table: 196 */ 197 for (i = 0; i < _thread_dtablesize; i++) { 198 /* Initialise the file descriptor table: */ 199 _thread_fd_table[i] = NULL; 200 } 201 } 202 } 203 return; 204} 205 206/* 207 * Special start up code for NetBSD/Alpha 208 */ 209#if defined(__NetBSD__) && defined(__alpha__) 210int 211main(int argc, char *argv[], char *env); 212 213int 214_thread_main(int argc, char *argv[], char *env) 215{ 216 _thread_init(); 217 return (main(argc, argv, env)); 218} 219#endif 220#else 221/* 222 * A stub for non-threaded programs. 223 */ 224void 225_thread_init(void) 226{ 227} 228#endif 229