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.
This commit is contained in:
mtm 2003-12-26 08:16:17 +00:00
parent 57cde0f9a7
commit dd97c7c8fa
3 changed files with 81 additions and 63 deletions

View File

@ -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.

View File

@ -164,6 +164,82 @@ static void *libgcc_references[] = {
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
*/
@ -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");
}
/*

View File

@ -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);