diff options
author | David Leonard <d@cvs.openbsd.org> | 1999-11-25 07:01:48 +0000 |
---|---|---|
committer | David Leonard <d@cvs.openbsd.org> | 1999-11-25 07:01:48 +0000 |
commit | 0fe78c3128864d128b2b10153b8d533ff8c00375 (patch) | |
tree | 5229c3d97eed15f4d71927a5f454180aef2632f6 /lib/libc_r/uthread/uthread_fork.c | |
parent | ed00fa742a6455d22e3b56cf846dc5acd7a51fd7 (diff) |
sync with FreeBSD
Diffstat (limited to 'lib/libc_r/uthread/uthread_fork.c')
-rw-r--r-- | lib/libc_r/uthread/uthread_fork.c | 112 |
1 files changed, 73 insertions, 39 deletions
diff --git a/lib/libc_r/uthread/uthread_fork.c b/lib/libc_r/uthread/uthread_fork.c index ed1566915bd..0e9aef59a20 100644 --- a/lib/libc_r/uthread/uthread_fork.c +++ b/lib/libc_r/uthread/uthread_fork.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fork.c,v 1.7 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,13 +30,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fork.c,v 1.6 1999/06/15 00:07:39 d Exp $ + * $FreeBSD: uthread_fork.c,v 1.14 1999/09/29 15:18:38 marcel Exp $ */ #include <errno.h> #include <string.h> #include <unistd.h> #include <fcntl.h> -#include <stdlib.h> #ifdef _THREAD_SAFE #include <pthread.h> #include "pthread_private.h" @@ -46,10 +46,13 @@ fork(void) int i, flags; pid_t ret; pthread_t pthread; - pthread_t pthread_next; + pthread_t pthread_save; - /* Lock the thread list: */ - _lock_thread_list(); + /* + * Defer signals to protect the scheduling queues from access + * by the signal handler: + */ + _thread_kern_sig_defer(); /* Fork a new process: */ if ((ret = _thread_sys_fork()) != 0) { @@ -60,7 +63,7 @@ fork(void) _thread_sys_close(_thread_kern_pipe[1]); /* Reset signals pending for the running thread: */ - _thread_run->sigpend = 0; + sigemptyset(&_thread_run->sigpend); /* * Create a pipe that is written to by the signal handler to @@ -90,45 +93,74 @@ fork(void) else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) { /* Abort this application: */ abort(); + } + /* Reinitialize the GC mutex: */ + else if (_mutex_reinit(&_gc_mutex) != 0) { + /* Abort this application: */ + PANIC("Cannot initialize GC mutex for forked process"); + } + /* Reinitialize the GC condition variable: */ + else if (_cond_reinit(&_gc_cond) != 0) { + /* Abort this application: */ + PANIC("Cannot initialize GC condvar for forked process"); + } /* Initialize the ready queue: */ - } else if (_pq_init(&_readyq, PTHREAD_MIN_PRIORITY, - PTHREAD_MAX_PRIORITY) != 0) { + else if (_pq_init(&_readyq) != 0) { /* Abort this application: */ - PANIC("Cannot allocate priority ready queue."); + PANIC("Cannot initialize priority ready queue."); } else { - /* Point to the first thread in the list: */ - pthread = _thread_link_list; - /* * Enter a loop to remove all threads other than * the running thread from the thread list: */ + pthread = TAILQ_FIRST(&_thread_list); while (pthread != NULL) { - pthread_next = pthread->nxt; - if (pthread == _thread_run) { - _thread_link_list = pthread; - pthread->nxt = NULL; - } else { - if (pthread->attr.stackaddr_attr == - NULL && pthread->stack != NULL) - /* - * Free the stack of the - * dead thread: - */ - free(pthread->stack); - - if (pthread->specific_data != NULL) - free(pthread->specific_data); - - free(pthread); - } + /* Save the thread to be freed: */ + pthread_save = pthread; + + /* + * Advance to the next thread before + * destroying the current thread: + */ + pthread = TAILQ_NEXT(pthread, dle); + + /* Make sure this isn't the running thread: */ + if (pthread_save != _thread_run) { + /* Remove this thread from the list: */ + TAILQ_REMOVE(&_thread_list, + pthread_save, tle); - /* Point to the next thread: */ - pthread = pthread_next; + if(pthread_save->stack != NULL) + _thread_stack_free(pthread_save->stack); + + if (pthread_save->specific_data != NULL) + free(pthread_save->specific_data); + + if (pthread_save->poll_data.fds != NULL) + free(pthread_save->poll_data.fds); + + free(pthread_save); + } } - /* Re-init the waiting queues. */ + /* Re-init the dead thread list: */ + TAILQ_INIT(&_dead_list); + + /* Re-init the waiting and work queues. */ TAILQ_INIT(&_waitingq); + TAILQ_INIT(&_workq); + + /* Re-init the threads mutex queue: */ + TAILQ_INIT(&_thread_run->mutexq); + + /* No spinlocks yet: */ + _spinblock_count = 0; + + /* Don't queue signals yet: */ + _queue_signals = 0; + + /* Initialize signal handling: */ + _thread_sig_init(); /* Initialize the scheduling switch hook routine: */ _sched_switch_hook = NULL; @@ -137,7 +169,7 @@ fork(void) for (i = 0; i < _thread_dtablesize; i++) { if (_thread_fd_table[i] != NULL) { /* Initialise the file locks: */ - _SPINUNLOCK(&_thread_fd_table[i]->lock); + _SPINLOCK_INIT(&_thread_fd_table[i]->lock); _thread_fd_table[i]->r_owner = NULL; _thread_fd_table[i]->w_owner = NULL; _thread_fd_table[i]->r_fname = NULL; @@ -148,15 +180,17 @@ fork(void) _thread_fd_table[i]->w_lockcount = 0;; /* Initialise the read/write queues: */ - _thread_queue_init(&_thread_fd_table[i]->r_queue); - _thread_queue_init(&_thread_fd_table[i]->w_queue); + TAILQ_INIT(&_thread_fd_table[i]->r_queue); + TAILQ_INIT(&_thread_fd_table[i]->w_queue); } } } } - /* Unock the thread list: */ - _unlock_thread_list(); + /* + * Undefer and handle pending signals, yielding if necessary: + */ + _thread_kern_sig_undefer(); /* Return the process ID: */ return (ret); |