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:
parent
57cde0f9a7
commit
dd97c7c8fa
@ -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.
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user