summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authormtm <mtm@FreeBSD.org>2003-12-26 08:16:17 +0000
committermtm <mtm@FreeBSD.org>2003-12-26 08:16:17 +0000
commitdd97c7c8fa6bc63be1c3715c5dfc8a981728d162 (patch)
treee82fd13767afbd3c3f05d29966af62c023d34a05 /lib
parent57cde0f9a725c266d83624b53174fd6d15564985 (diff)
downloadFreeBSD-src-dd97c7c8fa6bc63be1c3715c5dfc8a981728d162.zip
FreeBSD-src-dd97c7c8fa6bc63be1c3715c5dfc8a981728d162.tar.gz
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/libthr/thread/thr_create.c25
-rw-r--r--lib/libthr/thread/thr_init.c117
-rw-r--r--lib/libthr/thread/thr_private.h2
3 files changed, 81 insertions, 63 deletions
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);
OpenPOWER on IntegriCloud