From dd97c7c8fa6bc63be1c3715c5dfc8a981728d162 Mon Sep 17 00:00:00 2001 From: mtm Date: Fri, 26 Dec 2003 08:16:17 +0000 Subject: Preparations to make libthr work in multi-threaded fork()ing applications. o Remove some code duplication between _thread_init(), which is run once to initialize libthr and the intitial thread, and pthread_create(), which initializes newly created threads, into a new function called from both places: init_td_common() o Move initialization of certain parts of libthr into a separate function. These include: - Active threads list and it's lock - Dead threads list and it's lock & condition variable - Naming and insertion of the initial thread into the active threads list. --- lib/libthr/thread/thr_create.c | 25 +-------- lib/libthr/thread/thr_init.c | 117 ++++++++++++++++++++++++++-------------- lib/libthr/thread/thr_private.h | 2 + 3 files changed, 81 insertions(+), 63 deletions(-) (limited to 'lib') diff --git a/lib/libthr/thread/thr_create.c b/lib/libthr/thread/thr_create.c index 41019ad..f1a6301 100644 --- a/lib/libthr/thread/thr_create.c +++ b/lib/libthr/thread/thr_create.c @@ -97,20 +97,11 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, } /* Initialise the thread structure: */ - memset(new_thread, 0, sizeof(struct pthread)); + init_td_common(new_thread, pattr, 0); new_thread->stack = stack; new_thread->start_routine = start_routine; new_thread->arg = arg; - new_thread->cancelflags = PTHREAD_CANCEL_ENABLE | - PTHREAD_CANCEL_DEFERRED; - - /* - * Write a magic value to the thread structure - * to help identify valid ones: - */ - new_thread->magic = PTHREAD_MAGIC; - /* Initialise the machine context: */ getcontext(&new_thread->ctx); new_thread->ctx.uc_stack.ss_sp = new_thread->stack; @@ -128,9 +119,6 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, return (ret); } - /* Copy the thread attributes: */ - memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr)); - /* * Check if this thread is to inherit the scheduling * attributes from its parent: @@ -153,17 +141,6 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, new_thread->active_priority = new_thread->base_priority; new_thread->inherited_priority = 0; - /* Initialize joiner to NULL (no joiner): */ - new_thread->joiner = NULL; - - /* Initialize the mutex queue: */ - TAILQ_INIT(&new_thread->mutexq); - - /* Initialise hooks in the thread structure: */ - new_thread->specific = NULL; - new_thread->cleanup = NULL; - new_thread->flags = 0; - /* * Initialise the unique id which GDB uses to * track threads. diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c index 86622b6..514ed5c 100644 --- a/lib/libthr/thread/thr_init.c +++ b/lib/libthr/thread/thr_init.c @@ -165,6 +165,82 @@ int _pthread_guard_default; int _pthread_page_size; /* + * Initialize the current thread. + */ +void +init_td_common(struct pthread *td, struct pthread_attr *attrp, int reinit) +{ + /* + * Some parts of a pthread are initialized only once. + */ + if (!reinit) { + memset(td, 0, sizeof(struct pthread)); + td->cancelflags = PTHREAD_CANCEL_ENABLE | + PTHREAD_CANCEL_DEFERRED; + memcpy(&td->attr, attrp, sizeof(struct pthread_attr)); + td->magic = PTHREAD_MAGIC; + TAILQ_INIT(&td->mutexq); + } else { + memset(&td->join_status, 0, sizeof(struct join_status)); + } + td->joiner = NULL; + td->error = 0; + td->flags = 0; +} + +/* + * Initialize the active and dead threads list. Any threads in the active + * list will be removed and the thread td * will be marked as the + * initial thread and inserted in the list as the only thread. Any threads + * in the dead threads list will also be removed. + */ +void +init_tdlist(struct pthread *td, int reinit) +{ + struct pthread *tdTemp, *tdTemp2; + + _thread_initial = td; + td->name = strdup("_thread_initial"); + + /* + * If this is not the first initialization, remove any entries + * that may be in the list and deallocate their memory. Also + * destroy any global pthread primitives (they will be recreated). + */ + if (reinit) { + TAILQ_FOREACH_SAFE(tdTemp, &_thread_list, tle, tdTemp2) { + if (tdTemp != NULL) { + TAILQ_REMOVE(&_thread_list, tdTemp, tle); + free(tdTemp); + } + } + TAILQ_FOREACH_SAFE(tdTemp, &_dead_list, dle, tdTemp2) { + if (tdTemp != NULL) { + TAILQ_REMOVE(&_dead_list, tdTemp, dle); + free(tdTemp); + } + } + _pthread_mutex_destroy(&dead_list_lock); + _pthread_cond_destroy(&_gc_cond); + } else { + TAILQ_INIT(&_thread_list); + TAILQ_INIT(&_dead_list); + } + + /* Insert this thread as the first thread in the active list */ + TAILQ_INSERT_HEAD(&_thread_list, td, tle); + + /* + * Initialize the active thread list lock and the + * dead threads list lock & associated condition variable. + */ + memset(&thread_list_lock, 0, sizeof(spinlock_t)); + if (_pthread_mutex_init(&dead_list_lock,NULL) != 0 || + _pthread_cond_init(&_gc_cond,NULL) != 0) + PANIC("Failed to initialize garbage collector primitives"); +} + +/* * Threaded process initialization */ void @@ -233,19 +309,14 @@ _thread_init(void) */ PANIC("Cannot allocate memory for initial thread"); } - /* Zero the initial thread structure: */ - memset(pthread, 0, sizeof(struct pthread)); - _thread_initial = pthread; + init_tdlist(pthread, 0); + init_td_common(pthread, &pthread_attr_default, 0); pthread->arch_id = _set_curthread(NULL, pthread, &error); /* Get our thread id. */ thr_self(&pthread->thr_id); - /* Give this thread default attributes: */ - memcpy((void *) &pthread->attr, &pthread_attr_default, - sizeof(struct pthread_attr)); - /* Find the stack top */ mib[0] = CTL_KERN; mib[1] = KERN_USRSTACK; @@ -271,15 +342,6 @@ _thread_init(void) pthread->attr.stackaddr_attr = pthread->stack; pthread->attr.stacksize_attr = PTHREAD_STACK_INITIAL; - /* - * Write a magic value to the thread structure - * to help identify valid ones: - */ - pthread->magic = PTHREAD_MAGIC; - - /* Set the initial cancel state */ - pthread->cancelflags = PTHREAD_CANCEL_ENABLE | PTHREAD_CANCEL_DEFERRED; - /* Setup the context for initial thread. */ getcontext(&pthread->ctx); pthread->ctx.uc_stack.ss_sp = pthread->stack; @@ -293,24 +355,6 @@ _thread_init(void) /* Initialise the state of the initial thread: */ pthread->state = PS_RUNNING; - /* Set the name of the thread: */ - pthread->name = strdup("_thread_initial"); - - /* Initialize joiner to NULL (no joiner): */ - pthread->joiner = NULL; - - /* Initialize the owned mutex queue and count: */ - TAILQ_INIT(&(pthread->mutexq)); - pthread->priority_mutex_count = 0; - - /* Initialise the rest of the fields: */ - pthread->specific = NULL; - pthread->cleanup = NULL; - pthread->flags = 0; - pthread->error = 0; - TAILQ_INIT(&_thread_list); - TAILQ_INSERT_HEAD(&_thread_list, pthread, tle); - /* Enter a loop to get the existing signal status: */ for (i = 1; i < NSIG; i++) { /* Check for signals which cannot be trapped. */ @@ -360,11 +404,6 @@ _thread_init(void) if (sysctl(mib, 2, &clockinfo, &len, NULL, 0) == 0) _clock_res_usec = clockinfo.tick > CLOCK_RES_USEC_MIN ? clockinfo.tick : CLOCK_RES_USEC_MIN; - - /* Initialise the garbage collector mutex and condition variable. */ - if (_pthread_mutex_init(&dead_list_lock,NULL) != 0 || - _pthread_cond_init(&_gc_cond,NULL) != 0) - PANIC("Failed to initialise garbage collector mutex or condvar"); } /* diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index 8e6575e..c41b714 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -763,6 +763,8 @@ void _thread_critical_enter(pthread_t); void _thread_critical_exit(pthread_t); void _thread_sigblock(); void _thread_sigunblock(); +void init_td_common(struct pthread *, struct pthread_attr *, int); +void init_tdlist(struct pthread *, int); void proc_sigact_copyin(int, const struct sigaction *); void proc_sigact_copyout(int, struct sigaction *); struct sigaction *proc_sigact_sigaction(int); -- cgit v1.1