From: Ulrich Drepper Date: Wed, 10 Nov 1999 05:03:40 +0000 (+0000) Subject: Define __pthread_last_event. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2f30beef5c0e8c92c7327372871acdef53d82362;p=thirdparty%2Fglibc.git Define __pthread_last_event. (pthread_handle_create): Set __pthread_last_event. (pthread_exited): Likewise. (__pthread_threads_events): New variable. (pthread_handle_create): Take new parameters with event information. Signal TD_CREATE event if wanted. (__pthread_manager): Adjust pthread_handle_create call. (pthread_start_thread_event): New function. Block until manager is finished and then call pthread_start_thread. (pthread_exited): Signal TD_REAP event if wanted. --- diff --git a/linuxthreads/manager.c b/linuxthreads/manager.c index f78e14c55b3..4d8bedd45b8 100644 --- a/linuxthreads/manager.c +++ b/linuxthreads/manager.c @@ -38,16 +38,25 @@ struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] = { { LOCK_INITIALIZER, &__pthread_initial_thread, 0}, { LOCK_INITIALIZER, &__pthread_manager_thread, 0}, /* All NULLs */ }; +/* For debugging purposes put the maximum number of threads in a variable. */ +const int __linuxthreads_pthread_threads_max = PTHREAD_THREADS_MAX; + /* Indicate whether at least one thread has a user-defined stack (if 1), or if all threads have stacks supplied by LinuxThreads (if 0). */ -int __pthread_nonstandard_stacks = 0; +int __pthread_nonstandard_stacks; /* Number of active entries in __pthread_handles (used by gdb) */ volatile int __pthread_handles_num = 2; /* Whether to use debugger additional actions for thread creation (set to 1 by gdb) */ -volatile int __pthread_threads_debug = 0; +volatile int __pthread_threads_debug; + +/* Globally enabled events. */ +volatile td_thr_events_t __pthread_threads_events; + +/* Pointer to thread descriptor with last event. */ +volatile pthread_descr __pthread_last_event; /* Mapping from stack segment to thread descriptor. */ /* Stack segment numbers are also indices into the __pthread_handles array. */ @@ -77,7 +86,9 @@ static pthread_t pthread_threads_counter = 0; static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, void * (*start_routine)(void *), void *arg, - sigset_t *mask, int father_pid); + sigset_t *mask, int father_pid, + int report_events, + td_thr_events_t *event_maskp); static void pthread_handle_free(pthread_t th_id); static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode); static void pthread_reap_children(void); @@ -138,7 +149,9 @@ int __pthread_manager(void *arg) request.req_args.create.fn, request.req_args.create.arg, &request.req_args.create.mask, - request.req_thread->p_pid); + request.req_thread->p_pid, + request.req_thread->p_report_events, + &request.req_thread->p_eventbuf.eventmask); restart(request.req_thread); break; case REQ_FREE: @@ -217,6 +230,19 @@ static int pthread_start_thread(void *arg) return 0; } +static int pthread_start_thread_event(void *arg) +{ + pthread_descr self = thread_self (); + + /* Get the lock the manager will free once all is correctly set up. */ + __pthread_lock (THREAD_GETMEM(self, p_lock), NULL); + /* Free it immediately. */ + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + + /* Continue with the real function. */ + return pthread_start_thread (arg); +} + static int pthread_allocate_stack(const pthread_attr_t *attr, pthread_descr default_new_thread, int pagesize, @@ -294,7 +320,9 @@ static int pthread_allocate_stack(const pthread_attr_t *attr, static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, void * (*start_routine)(void *), void *arg, - sigset_t * mask, int father_pid) + sigset_t * mask, int father_pid, + int report_events, + td_thr_events_t *event_maskp) { size_t sseg; int pid; @@ -369,10 +397,48 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, new_thread->p_start_args.mask = *mask; /* Raise priority of thread manager if needed */ __pthread_manager_adjust_prio(new_thread->p_priority); - /* Do the cloning */ - pid = __clone(pthread_start_thread, (void **) new_thread, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | - __pthread_sig_cancel, new_thread); + /* Do the cloning. We have to use two different functions depending + on whether we are debugging or not. */ + pid = 0; /* Note that the thread never can have PID zero. */ + if (report_events) + { + /* See whether the TD_CREATE event bit is set in any of the + masks. */ + int idx = __td_eventword (TD_CREATE); + uint32_t mask = __td_eventmask (TD_CREATE); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | event_maskp->event_bits[idx])) != 0) + { + /* Lock the mutex the child will use now so that it will stop. */ + __pthread_lock(new_thread->p_lock, NULL); + + /* We have to report this event. */ + pid = __clone(pthread_start_thread_event, (void **) new_thread, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); + if (pid != -1) + { + /* Now fill in the information about the new thread in + the newly created thread's data structure. We cannot let + the new thread do this since we don't know whether it was + already scheduled when we send the event. */ + new_thread->p_eventbuf.eventdata = new_thread; + new_thread->p_eventbuf.eventnum = TD_CREATE; + __pthread_last_event = new_thread; + + /* Now call the function which signals the event. */ + __linuxthreads_create_event (); + + /* Now restart the thread. */ + __pthread_unlock(new_thread->p_lock); + } + } + } + if (pid == 0) + pid = __clone(pthread_start_thread, (void **) new_thread, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); /* Check if cloning succeeded */ if (pid == -1) { /* Free the stack if we allocated it */ @@ -448,6 +514,25 @@ static void pthread_exited(pid_t pid) /* Mark thread as exited, and if detached, free its resources */ __pthread_lock(th->p_lock, NULL); th->p_exited = 1; + /* If we have to signal this event do it now. */ + if (th->p_report_events) + { + /* See whether TD_DEATH is in any of the mask. */ + int idx = __td_eventword (TD_REAP); + uint32_t mask = __td_eventmask (TD_REAP); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | th->p_eventbuf.eventmask.event_bits[idx])) != 0) + { + /* Yep, we have to signal the death. */ + th->p_eventbuf.eventnum = TD_DEATH; + th->p_eventbuf.eventdata = th; + __pthread_last_event = th; + + /* Now call the function to signal the event. */ + __linuxthreads_reap_event(); + } + } detached = th->p_detached; __pthread_unlock(th->p_lock); if (detached)