diff options
Diffstat (limited to 'hurd/hurdsig.c')
-rw-r--r-- | hurd/hurdsig.c | 64 |
1 files changed, 44 insertions, 20 deletions
diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c index 12ea82955b..a69b87df0b 100644 --- a/hurd/hurdsig.c +++ b/hurd/hurdsig.c @@ -20,6 +20,7 @@ #include <string.h> #include <cthreads.h> /* For `struct mutex'. */ +#include <pthread.h> #include <mach.h> #include <mach/thread_switch.h> @@ -45,7 +46,6 @@ thread_t _hurd_msgport_thread; /* These are set up by _hurdsig_init. */ unsigned long int __hurd_sigthread_stack_base; unsigned long int __hurd_sigthread_stack_end; -unsigned long int *__hurd_sigthread_variables; /* Linked-list of per-thread signal state. */ struct hurd_sigstate *_hurd_sigstates; @@ -105,6 +105,8 @@ _hurd_thread_sigstate (thread_t thread) } else { + error_t err; + /* Use the global actions as a default for new threads. */ struct hurd_sigstate *s = _hurd_global_sigstate; if (s) @@ -118,6 +120,11 @@ _hurd_thread_sigstate (thread_t thread) ss->next = _hurd_sigstates; _hurd_sigstates = ss; + + err = __mach_port_mod_refs (__mach_task_self (), thread, + MACH_PORT_RIGHT_SEND, 1); + if (err) + __libc_fatal ("hurd: Can't add reference on Mach thread\n"); } } __mutex_unlock (&_hurd_siglock); @@ -125,8 +132,7 @@ _hurd_thread_sigstate (thread_t thread) } /* Destroy a sigstate structure. Called by libpthread just before the - * corresponding thread is terminated (the kernel thread port must remain valid - * until this function is called.) */ + * corresponding thread is terminated. */ void _hurd_sigstate_delete (thread_t thread) { @@ -143,7 +149,12 @@ _hurd_sigstate_delete (thread_t thread) __mutex_unlock (&_hurd_siglock); if (ss) - free (ss); + { + if (ss->thread != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), ss->thread); + + free (ss); + } } /* Make SS a global receiver, with pthread signal semantics. */ @@ -334,11 +345,11 @@ abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state, that this location can be set without faulting, or else return NULL. */ static mach_port_t * -interrupted_reply_port_location (struct machine_thread_all_state *thread_state, +interrupted_reply_port_location (thread_t thread, + struct machine_thread_all_state *thread_state, int sigthread) { - mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp - (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP); + mach_port_t *portloc = &THREAD_TCB(thread, thread_state)->reply_port; if (sigthread && _hurdsig_catch_memory_fault (portloc)) /* Faulted trying to read the stack. */ @@ -423,7 +434,8 @@ _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread, our nonzero return tells the trampoline code to finish the message receive operation before running the handler. */ - mach_port_t *reply = interrupted_reply_port_location (state, + mach_port_t *reply = interrupted_reply_port_location (ss->thread, + state, sigthread); error_t err = __interrupt_operation (intr_port, _hurdsig_interrupt_timeout); @@ -980,7 +992,8 @@ post_signal (struct hurd_sigstate *ss, if (! machine_get_basic_state (ss->thread, &thread_state)) goto sigbomb; - loc = interrupted_reply_port_location (&thread_state, 1); + loc = interrupted_reply_port_location (ss->thread, + &thread_state, 1); if (loc && *loc != MACH_PORT_NULL) /* This is the reply port for the context which called sigreturn. Since we are abandoning that context entirely @@ -1046,7 +1059,8 @@ post_signal (struct hurd_sigstate *ss, { /* Fetch the thread variable for the MiG reply port, and set it to MACH_PORT_NULL. */ - mach_port_t *loc = interrupted_reply_port_location (&thread_state, + mach_port_t *loc = interrupted_reply_port_location (ss->thread, + &thread_state, 1); if (loc) { @@ -1452,7 +1466,11 @@ _hurdsig_init (const int *intarray, size_t intarraysize) /* Start the signal thread listening on the message port. */ - if (__hurd_threadvar_stack_mask == 0) +#pragma weak cthread_fork +#pragma weak cthread_detach +#pragma weak pthread_getattr_np +#pragma weak pthread_attr_getstack + if (!cthread_fork) { err = __thread_create (__mach_task_self (), &_hurd_msgport_thread); assert_perror (err); @@ -1467,12 +1485,6 @@ _hurdsig_init (const int *intarray, size_t intarraysize) assert_perror (err); __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize; - __hurd_sigthread_variables = - malloc (__hurd_threadvar_max * sizeof (unsigned long int)); - if (__hurd_sigthread_variables == NULL) - __libc_fatal ("hurd: Can't allocate threadvars for signal thread\n"); - memset (__hurd_sigthread_variables, 0, - __hurd_threadvar_max * sizeof (unsigned long int)); /* Reinitialize the MiG support routines so they will use a per-thread variable for the cached reply port. */ @@ -1483,6 +1495,7 @@ _hurdsig_init (const int *intarray, size_t intarraysize) } else { + cthread_t thread; /* When cthreads is being used, we need to make the signal thread a proper cthread. Otherwise it cannot use mutex_lock et al, which will be the cthreads versions. Various of the message port RPC @@ -1492,9 +1505,20 @@ _hurdsig_init (const int *intarray, size_t intarraysize) we'll let the signal thread's per-thread variables be found as for any normal cthread, and just leave the magic __hurd_sigthread_* values all zero so they'll be ignored. */ -#pragma weak cthread_fork -#pragma weak cthread_detach - cthread_detach (cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0)); + cthread_detach (thread = cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0)); + + if (pthread_getattr_np) + { + /* Record stack layout for fork() */ + pthread_attr_t attr; + void *addr; + size_t size; + + pthread_getattr_np ((pthread_t) thread, &attr); + pthread_attr_getstack (&attr, &addr, &size); + __hurd_sigthread_stack_base = (uintptr_t) addr; + __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + size; + } /* XXX We need the thread port for the signal thread further on in this thread (see hurdfault.c:_hurdsigfault_init). |