1/* 2 * Copyright (c) 1995-1998 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 AUTHOR 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 *
| 1/* 2 * Copyright (c) 1995-1998 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 AUTHOR 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 * $FreeBSD: head/lib/libkse/thread/thr_fork.c 54138 1999-12-04 22:55:59Z deischen $
| 32 * $FreeBSD: head/lib/libkse/thread/thr_fork.c 55194 1999-12-28 18:13:04Z deischen $
|
33 */ 34#include <errno.h> 35#include <string.h>
| 33 */ 34#include <errno.h> 35#include <string.h>
|
| 36#include <stdlib.h>
|
36#include <unistd.h> 37#include <fcntl.h> 38#ifdef _THREAD_SAFE 39#include <pthread.h> 40#include "pthread_private.h" 41 42pid_t 43fork(void) 44{ 45 int i, flags; 46 pid_t ret; 47 pthread_t pthread; 48 pthread_t pthread_save; 49 50 /* 51 * Defer signals to protect the scheduling queues from access 52 * by the signal handler: 53 */ 54 _thread_kern_sig_defer(); 55 56 /* Fork a new process: */ 57 if ((ret = _thread_sys_fork()) != 0) { 58 /* Parent process or error. Nothing to do here. */ 59 } else { 60 /* Close the pthread kernel pipe: */ 61 _thread_sys_close(_thread_kern_pipe[0]); 62 _thread_sys_close(_thread_kern_pipe[1]); 63 64 /* Reset signals pending for the running thread: */ 65 sigemptyset(&_thread_run->sigpend); 66 67 /* 68 * Create a pipe that is written to by the signal handler to 69 * prevent signals being missed in calls to 70 * _thread_sys_select: 71 */ 72 if (_thread_sys_pipe(_thread_kern_pipe) != 0) { 73 /* Cannot create pipe, so abort: */ 74 PANIC("Cannot create pthread kernel pipe for forked process"); 75 } 76 /* Get the flags for the read pipe: */ 77 else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) { 78 /* Abort this application: */ 79 abort(); 80 } 81 /* Make the read pipe non-blocking: */ 82 else if (_thread_sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) { 83 /* Abort this application: */ 84 abort(); 85 } 86 /* Get the flags for the write pipe: */ 87 else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) { 88 /* Abort this application: */ 89 abort(); 90 } 91 /* Make the write pipe non-blocking: */ 92 else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) { 93 /* Abort this application: */ 94 abort(); 95 } 96 /* Reinitialize the GC mutex: */ 97 else if (_mutex_reinit(&_gc_mutex) != 0) { 98 /* Abort this application: */ 99 PANIC("Cannot initialize GC mutex for forked process"); 100 } 101 /* Reinitialize the GC condition variable: */ 102 else if (_cond_reinit(&_gc_cond) != 0) { 103 /* Abort this application: */ 104 PANIC("Cannot initialize GC condvar for forked process"); 105 } 106 /* Initialize the ready queue: */ 107 else if (_pq_init(&_readyq) != 0) { 108 /* Abort this application: */ 109 PANIC("Cannot initialize priority ready queue."); 110 } else { 111 /* 112 * Enter a loop to remove all threads other than 113 * the running thread from the thread list: 114 */ 115 pthread = TAILQ_FIRST(&_thread_list); 116 while (pthread != NULL) { 117 /* Save the thread to be freed: */ 118 pthread_save = pthread; 119 120 /* 121 * Advance to the next thread before 122 * destroying the current thread: 123 */ 124 pthread = TAILQ_NEXT(pthread, dle); 125 126 /* Make sure this isn't the running thread: */ 127 if (pthread_save != _thread_run) { 128 /* Remove this thread from the list: */ 129 TAILQ_REMOVE(&_thread_list, 130 pthread_save, tle); 131 132 if (pthread_save->attr.stackaddr_attr ==
| 37#include <unistd.h> 38#include <fcntl.h> 39#ifdef _THREAD_SAFE 40#include <pthread.h> 41#include "pthread_private.h" 42 43pid_t 44fork(void) 45{ 46 int i, flags; 47 pid_t ret; 48 pthread_t pthread; 49 pthread_t pthread_save; 50 51 /* 52 * Defer signals to protect the scheduling queues from access 53 * by the signal handler: 54 */ 55 _thread_kern_sig_defer(); 56 57 /* Fork a new process: */ 58 if ((ret = _thread_sys_fork()) != 0) { 59 /* Parent process or error. Nothing to do here. */ 60 } else { 61 /* Close the pthread kernel pipe: */ 62 _thread_sys_close(_thread_kern_pipe[0]); 63 _thread_sys_close(_thread_kern_pipe[1]); 64 65 /* Reset signals pending for the running thread: */ 66 sigemptyset(&_thread_run->sigpend); 67 68 /* 69 * Create a pipe that is written to by the signal handler to 70 * prevent signals being missed in calls to 71 * _thread_sys_select: 72 */ 73 if (_thread_sys_pipe(_thread_kern_pipe) != 0) { 74 /* Cannot create pipe, so abort: */ 75 PANIC("Cannot create pthread kernel pipe for forked process"); 76 } 77 /* Get the flags for the read pipe: */ 78 else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) { 79 /* Abort this application: */ 80 abort(); 81 } 82 /* Make the read pipe non-blocking: */ 83 else if (_thread_sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) { 84 /* Abort this application: */ 85 abort(); 86 } 87 /* Get the flags for the write pipe: */ 88 else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) { 89 /* Abort this application: */ 90 abort(); 91 } 92 /* Make the write pipe non-blocking: */ 93 else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) { 94 /* Abort this application: */ 95 abort(); 96 } 97 /* Reinitialize the GC mutex: */ 98 else if (_mutex_reinit(&_gc_mutex) != 0) { 99 /* Abort this application: */ 100 PANIC("Cannot initialize GC mutex for forked process"); 101 } 102 /* Reinitialize the GC condition variable: */ 103 else if (_cond_reinit(&_gc_cond) != 0) { 104 /* Abort this application: */ 105 PANIC("Cannot initialize GC condvar for forked process"); 106 } 107 /* Initialize the ready queue: */ 108 else if (_pq_init(&_readyq) != 0) { 109 /* Abort this application: */ 110 PANIC("Cannot initialize priority ready queue."); 111 } else { 112 /* 113 * Enter a loop to remove all threads other than 114 * the running thread from the thread list: 115 */ 116 pthread = TAILQ_FIRST(&_thread_list); 117 while (pthread != NULL) { 118 /* Save the thread to be freed: */ 119 pthread_save = pthread; 120 121 /* 122 * Advance to the next thread before 123 * destroying the current thread: 124 */ 125 pthread = TAILQ_NEXT(pthread, dle); 126 127 /* Make sure this isn't the running thread: */ 128 if (pthread_save != _thread_run) { 129 /* Remove this thread from the list: */ 130 TAILQ_REMOVE(&_thread_list, 131 pthread_save, tle); 132 133 if (pthread_save->attr.stackaddr_attr ==
|
133 NULL && pthread_save->stack != NULL)
| 134 NULL && pthread_save->stack != NULL) {
|
134 if (pthread_save->attr.stacksize_attr 135 == PTHREAD_STACK_DEFAULT) { 136 /*
| 135 if (pthread_save->attr.stacksize_attr 136 == PTHREAD_STACK_DEFAULT) { 137 /*
|
137 * Default-size stack. Cache 138 * it:
| 138 * Default-size stack. 139 * Cache it:
|
139 */ 140 struct stack *spare_stack; 141 142 spare_stack 143 = (pthread_save->stack
| 140 */ 141 struct stack *spare_stack; 142 143 spare_stack 144 = (pthread_save->stack
|
144 + PTHREAD_STACK_DEFAULT 145 - sizeof(struct stack)); 146 SLIST_INSERT_HEAD( 147 &_stackq, 148 spare_stack, 149 qe);
| 145 + PTHREAD_STACK_DEFAULT 146 - sizeof(struct stack)); 147 SLIST_INSERT_HEAD(&_stackq, 148 spare_stack, qe);
|
150 } else 151 /* 152 * Free the stack of 153 * the dead thread: 154 */ 155 free(pthread_save->stack);
| 149 } else 150 /* 151 * Free the stack of 152 * the dead thread: 153 */ 154 free(pthread_save->stack);
|
| 155 }
|
156 157 if (pthread_save->specific_data != NULL) 158 free(pthread_save->specific_data); 159 160 if (pthread_save->poll_data.fds != NULL) 161 free(pthread_save->poll_data.fds); 162 163 free(pthread_save); 164 } 165 } 166 167 /* Treat the current thread as the initial thread: */ 168 _thread_initial = _thread_run; 169 170 /* Re-init the dead thread list: */ 171 TAILQ_INIT(&_dead_list); 172 173 /* Re-init the waiting and work queues. */ 174 TAILQ_INIT(&_waitingq); 175 TAILQ_INIT(&_workq); 176 177 /* Re-init the threads mutex queue: */ 178 TAILQ_INIT(&_thread_run->mutexq); 179 180 /* No spinlocks yet: */ 181 _spinblock_count = 0; 182 183 /* Don't queue signals yet: */ 184 _queue_signals = 0; 185 186 /* Initialize signal handling: */ 187 _thread_sig_init(); 188 189 /* Initialize the scheduling switch hook routine: */ 190 _sched_switch_hook = NULL; 191 192 /* Clear out any locks in the file descriptor table: */ 193 for (i = 0; i < _thread_dtablesize; i++) { 194 if (_thread_fd_table[i] != NULL) { 195 /* Initialise the file locks: */ 196 memset(&_thread_fd_table[i]->lock, 0, 197 sizeof(_thread_fd_table[i]->lock)); 198 _thread_fd_table[i]->r_owner = NULL; 199 _thread_fd_table[i]->w_owner = NULL; 200 _thread_fd_table[i]->r_fname = NULL; 201 _thread_fd_table[i]->w_fname = NULL; 202 _thread_fd_table[i]->r_lineno = 0;; 203 _thread_fd_table[i]->w_lineno = 0;; 204 _thread_fd_table[i]->r_lockcount = 0;; 205 _thread_fd_table[i]->w_lockcount = 0;; 206 207 /* Initialise the read/write queues: */ 208 TAILQ_INIT(&_thread_fd_table[i]->r_queue); 209 TAILQ_INIT(&_thread_fd_table[i]->w_queue); 210 } 211 } 212 } 213 } 214 215 /* 216 * Undefer and handle pending signals, yielding if necessary: 217 */ 218 _thread_kern_sig_undefer(); 219 220 /* Return the process ID: */ 221 return (ret); 222} 223#endif
| 156 157 if (pthread_save->specific_data != NULL) 158 free(pthread_save->specific_data); 159 160 if (pthread_save->poll_data.fds != NULL) 161 free(pthread_save->poll_data.fds); 162 163 free(pthread_save); 164 } 165 } 166 167 /* Treat the current thread as the initial thread: */ 168 _thread_initial = _thread_run; 169 170 /* Re-init the dead thread list: */ 171 TAILQ_INIT(&_dead_list); 172 173 /* Re-init the waiting and work queues. */ 174 TAILQ_INIT(&_waitingq); 175 TAILQ_INIT(&_workq); 176 177 /* Re-init the threads mutex queue: */ 178 TAILQ_INIT(&_thread_run->mutexq); 179 180 /* No spinlocks yet: */ 181 _spinblock_count = 0; 182 183 /* Don't queue signals yet: */ 184 _queue_signals = 0; 185 186 /* Initialize signal handling: */ 187 _thread_sig_init(); 188 189 /* Initialize the scheduling switch hook routine: */ 190 _sched_switch_hook = NULL; 191 192 /* Clear out any locks in the file descriptor table: */ 193 for (i = 0; i < _thread_dtablesize; i++) { 194 if (_thread_fd_table[i] != NULL) { 195 /* Initialise the file locks: */ 196 memset(&_thread_fd_table[i]->lock, 0, 197 sizeof(_thread_fd_table[i]->lock)); 198 _thread_fd_table[i]->r_owner = NULL; 199 _thread_fd_table[i]->w_owner = NULL; 200 _thread_fd_table[i]->r_fname = NULL; 201 _thread_fd_table[i]->w_fname = NULL; 202 _thread_fd_table[i]->r_lineno = 0;; 203 _thread_fd_table[i]->w_lineno = 0;; 204 _thread_fd_table[i]->r_lockcount = 0;; 205 _thread_fd_table[i]->w_lockcount = 0;; 206 207 /* Initialise the read/write queues: */ 208 TAILQ_INIT(&_thread_fd_table[i]->r_queue); 209 TAILQ_INIT(&_thread_fd_table[i]->w_queue); 210 } 211 } 212 } 213 } 214 215 /* 216 * Undefer and handle pending signals, yielding if necessary: 217 */ 218 _thread_kern_sig_undefer(); 219 220 /* Return the process ID: */ 221 return (ret); 222} 223#endif
|