diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2018-03-17 23:27:34 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2018-03-17 23:29:57 +0100 |
commit | dc33bef307ad6eeb1cc4e4e230b69c6058890388 (patch) | |
tree | 94b8499e652a04871c4cb48225d85e9c5af455c9 /hurd | |
parent | 34e6a8694d9dd80558150f8542359b93c6c57e44 (diff) | |
download | glibc-dc33bef307ad6eeb1cc4e4e230b69c6058890388.tar.gz |
hurd: Replace threadvars with TLS
This gets rid of a lot of kludge and gets closer to other ports.
* hurd/Makefile (headers): Remove threadvar.h.
(inline-headers): Remove threadvar.h.
* hurd/Versions (GLIBC_2.0: Remove __hurd_sigthread_stack_base,
__hurd_sigthread_stack_end, __hurd_sigthread_variables,
__hurd_threadvar_max, __hurd_errno_location.
(HURD_CTHREADS_0.3): Add pthread_getattr_np, pthread_attr_getstack.
* hurd/hurd/signal.h: Do not include <hurd/threadvar.h>.
(_hurd_self_sigstate): Use THREAD_SELF to get _hurd_sigstate.
(_HURD_SIGNAL_H_EXTERN_INLINE): Use THREAD_SELF to get _hurd_sigstate,
unless TLS is not initialized yet, in which case we do not need a
critical section yet anyway.
* hurd/hurd/threadvar.h: Include <tls.h>, do not include
<machine-sp.h>.
(__hurd_sigthread_variables, __hurd_threadvar_max): Remove variables
declarations.
(__hurd_threadvar_index): Remove enum.
(_HURD_THREADVAR_H_EXTERN_INLINE): Remove macro.
(__hurd_threadvar_location_from_sp,__hurd_threadvar_location): Remove
inlines.
(__hurd_reply_port0): New variable declaration.
(__hurd_local_reply_port): New macro.
* hurd/hurdsig.c (__hurd_sigthread_variables): Remove variable.
(interrupted_reply_port_location): Add thread_t parameter. Use it
with THREAD_TCB to access thread-local variables.
(_hurdsig_abort_rpcs): Pass ss->thread to
interrupted_reply_port_location.
(_hurd_internal_post_signal): Likewise.
(_hurdsig_init): Use presence of cthread_fork instead of
__hurd_threadvar_stack_mask to start signal thread by hand.
Remove signal thread threadvar initialization.
* hurd/hurdstartup.c: Do not include <hurd/threadvar.h>
* hurd/sigunwind.c: Include <hurd/threadvar.h>
(_hurdsig_longjmp_from_handler): Use __hurd_local_reply_port instead
of threadvar.
* sysdeps/mach/hurd/Versions (libc.GLIBC_PRIVATE): Add
__libc_lock_self0.
(ld.GLIBC_2.0): Remove __hurd_sigthread_stack_base,
__hurd_sigthread_stack_end, __hurd_sigthread_variables.
(ld.GLIBC_PRIVATE): Add __libc_lock_self0.
* sysdeps/mach/hurd/cthreads.c: Add __libc_lock_self0.
* sysdeps/mach/hurd/dl-sysdep.c (errno, __hurd_sigthread_stack_base,
__hurd_sigthread_stack_end, __hurd_sigthread_variables, threadvars,
__hurd_threadvar_stack_offset, __hurd_threadvar_stack_mask): Do not
define variables.
* sysdeps/mach/hurd/errno-loc.c: Do not include <errno.h> and
<hurd/threadvar.h>.
[IS_IN(rtld)] (rtld_errno): New variable.
[IS_IN(rtld)] (__errno_location): New weak function.
[!IS_IN(rtld)]: Include "../../../csu/errno-loc.c".
* sysdeps/mach/hurd/errno.c: Remove file.
* sysdeps/mach/hurd/fork.c: Include <hurd/threadvar.h>
(__fork): Remove THREADVAR_SPACE macro and its use.
* sysdeps/mach/hurd/i386/init-first.c (__hurd_threadvar_max): Remove
variable.
(init): Do not initialize threadvar.
* sysdeps/mach/hurd/i386/libc.abilist (__hurd_threadvar_max): Remove
symbol.
* sysdeps/mach/hurd/i386/sigreturn.c (__sigreturn): Use
__hurd_local_reply_port instead of threadvar.
* sysdeps/mach/hurd/i386/tls.h (tcbhead_t): Add reply_port and
_hurd_sigstate fields.
(HURD_DESC_TLS, __LIBC_NO_TLS, THREAD_TCB): New macro.
* sysdeps/mach/hurd/i386/trampoline.c: Remove outdated comment.
* sysdeps/mach/hurd/libc-lock.h: Do not include <hurd/threadvar.h>.
(__libc_lock_owner_self): Use &__libc_lock_self0 and THREAD_SELF
instead of threadvar.
* sysdeps/mach/hurd/libc-tsd.h: Remove file.
* sysdeps/mach/hurd/mig-reply.c (GETPORT, reply_port): Remove macros.
(use_threadvar, global_reply_port): Remove variables.
(__hurd_reply_port0): New variable.
(__mig_get_reply_port): Use __hurd_local_reply_port and
__hurd_reply_port0 instead of threadvar.
(__mig_dealloc_reply_port): Likewise.
(__mig_init): Do not initialize threadvar.
* sysdeps/mach/hurd/profil.c: Fix comment.
Diffstat (limited to 'hurd')
-rw-r--r-- | hurd/Makefile | 4 | ||||
-rw-r--r-- | hurd/Versions | 7 | ||||
-rw-r--r-- | hurd/hurd/signal.h | 23 | ||||
-rw-r--r-- | hurd/hurd/threadvar.h | 89 | ||||
-rw-r--r-- | hurd/hurdsig.c | 30 | ||||
-rw-r--r-- | hurd/hurdstartup.c | 1 | ||||
-rw-r--r-- | hurd/sigunwind.c | 4 |
7 files changed, 39 insertions, 119 deletions
diff --git a/hurd/Makefile b/hurd/Makefile index cca08a175a..2b318c9ca0 100644 --- a/hurd/Makefile +++ b/hurd/Makefile @@ -21,10 +21,10 @@ include ../Makeconfig headers = hurd.h $(interface-headers) \ $(addprefix hurd/,fd.h id.h port.h signal.h sigpreempt.h ioctl.h\ - userlink.h resource.h threadvar.h lookup.h) + userlink.h resource.h lookup.h) inline-headers = hurd.h $(addprefix hurd/,fd.h signal.h \ - userlink.h threadvar.h port.h) + userlink.h port.h) # The RPC interfaces go in a separate library. interface-library := libhurduser diff --git a/hurd/Versions b/hurd/Versions index b1253e653e..164aa64400 100644 --- a/hurd/Versions +++ b/hurd/Versions @@ -4,14 +4,8 @@ libc { _end; # variables used in macros & inline functions - __hurd_sigthread_stack_base; __hurd_sigthread_stack_end; - __hurd_sigthread_variables; - __hurd_threadvar_max; __hurd_threadvar_stack_mask; __hurd_threadvar_stack_offset; - # functions used in macros & inline functions - __hurd_errno_location; - # functions used in libmachuser and libhurduser _S_catch_exception_raise; _S_catch_exception_raise_state; @@ -146,6 +140,7 @@ libc { HURD_CTHREADS_0.3 { # weak refs to libthreads functions that libc calls iff libthreads in use cthread_fork; cthread_detach; + pthread_getattr_np; pthread_attr_getstack; # variables used for detecting cthreads _cthread_exit_routine; _cthread_init_routine; diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h index 0e3315a6fe..eb9b0ca423 100644 --- a/hurd/hurd/signal.h +++ b/hurd/hurd/signal.h @@ -40,7 +40,6 @@ #include <cthreads.h> /* For `struct mutex'. */ #include <setjmp.h> /* For `jmp_buf'. */ #include <spin-lock.h> -#include <hurd/threadvar.h> /* We cache sigstate in a threadvar. */ struct hurd_signal_preemptor; /* <hurd/sigpreempt.h> */ #if defined __USE_EXTERN_INLINES && defined _LIBC # if IS_IN (libc) || IS_IN (libpthread) @@ -139,11 +138,9 @@ extern struct hurd_sigstate *_hurd_self_sigstate (void) _HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate * _hurd_self_sigstate (void) { - struct hurd_sigstate **location = (struct hurd_sigstate **) - (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE); - if (*location == NULL) - *location = _hurd_thread_sigstate (__mach_thread_self ()); - return *location; + if (THREAD_SELF->_hurd_sigstate == NULL) + THREAD_SELF->_hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ()); + return THREAD_SELF->_hurd_sigstate; } # endif #endif @@ -180,16 +177,22 @@ extern void *_hurd_critical_section_lock (void); _HURD_SIGNAL_H_EXTERN_INLINE void * _hurd_critical_section_lock (void) { - struct hurd_sigstate **location = (struct hurd_sigstate **) - (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE); - struct hurd_sigstate *ss = *location; + struct hurd_sigstate *ss; + +#ifdef __LIBC_NO_TLS + if (__LIBC_NO_TLS()) + /* TLS is currently initializing, no need to enter critical section. */ + return NULL; +#endif + + ss = THREAD_SELF->_hurd_sigstate; if (ss == NULL) { /* The thread variable is unset; this must be the first time we've asked for it. In this case, the critical section flag cannot possible already be set. Look up our sigstate structure the slow way. */ - ss = *location = _hurd_thread_sigstate (__mach_thread_self ()); + ss = THREAD_SELF->_hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ()); } if (! __spin_try_lock (&ss->critical_section_lock)) diff --git a/hurd/hurd/threadvar.h b/hurd/hurd/threadvar.h index 9b9b863dd6..89918e34c3 100644 --- a/hurd/hurd/threadvar.h +++ b/hurd/hurd/threadvar.h @@ -20,6 +20,7 @@ #define _HURD_THREADVAR_H #include <features.h> +#include <tls.h> /* The per-thread variables are found by ANDing this mask with the value of the stack pointer and then adding this offset. @@ -30,96 +31,24 @@ __hurd_threadvar_stack_offset to a small offset that skips the data cthreads itself maintains at the base of each thread's stack. - In the single-threaded case, __hurd_threadvar_stack_mask is zero, so the - stack pointer is ignored; and __hurd_threadvar_stack_offset gives the - address of a small allocated region which contains the variables for the - single thread. */ + In the single-threaded or libpthread case, __hurd_threadvar_stack_mask is + zero, so the stack pointer is ignored. */ extern unsigned long int __hurd_threadvar_stack_mask; extern unsigned long int __hurd_threadvar_stack_offset; -/* A special case must always be made for the signal thread. Even when there - is only one user thread and an allocated region can be used for the user - thread's variables, the signal thread needs to have its own location for - per-thread variables. The variables __hurd_sigthread_stack_base and +/* The variables __hurd_sigthread_stack_base and __hurd_sigthread_stack_end define the bounds of the stack used by the signal thread, so that thread can always be specifically identified. */ extern unsigned long int __hurd_sigthread_stack_base; extern unsigned long int __hurd_sigthread_stack_end; -extern unsigned long int *__hurd_sigthread_variables; +/* Store the MiG reply port reply port until we enable TLS. */ +extern mach_port_t __hurd_reply_port0; -/* At the location described by the two variables above, - there are __hurd_threadvar_max `unsigned long int's of per-thread data. */ -extern unsigned int __hurd_threadvar_max; - -/* These values are the indices for the standard per-thread variables. */ -enum __hurd_threadvar_index - { - _HURD_THREADVAR_MIG_REPLY, /* Reply port for MiG user stub functions. */ - _HURD_THREADVAR_ERRNO, /* `errno' value for this thread. */ - _HURD_THREADVAR_SIGSTATE, /* This thread's `struct hurd_sigstate'. */ - _HURD_THREADVAR_DYNAMIC_USER, /* Dynamically-assigned user variables. */ - _HURD_THREADVAR_MALLOC, /* For use of malloc. */ - _HURD_THREADVAR_DL_ERROR, /* For use of -ldl and dynamic linker. */ - _HURD_THREADVAR_RPC_VARS, /* For state of RPC functions. */ - _HURD_THREADVAR_LOCALE, /* For thread-local locale setting. */ - _HURD_THREADVAR_CTYPE_B, /* Cache of thread-local locale data. */ - _HURD_THREADVAR_CTYPE_TOLOWER, /* Cache of thread-local locale data. */ - _HURD_THREADVAR_CTYPE_TOUPPER, /* Cache of thread-local locale data. */ - _HURD_THREADVAR_MAX /* Default value for __hurd_threadvar_max. */ - }; - - -#ifndef _HURD_THREADVAR_H_EXTERN_INLINE -#define _HURD_THREADVAR_H_EXTERN_INLINE __extern_inline -#endif - -/* Return the location of the value for the per-thread variable with index - INDEX used by the thread whose stack pointer is SP. */ - -extern unsigned long int *__hurd_threadvar_location_from_sp - (enum __hurd_threadvar_index __index, void *__sp); - -#if defined __USE_EXTERN_INLINES && defined _LIBC -# if IS_IN (libc) -_HURD_THREADVAR_H_EXTERN_INLINE unsigned long int * -__hurd_threadvar_location_from_sp (enum __hurd_threadvar_index __index, - void *__sp) -{ - unsigned long int __stack = (unsigned long int) __sp; - return &((__stack >= __hurd_sigthread_stack_base && - __stack < __hurd_sigthread_stack_end) - ? __hurd_sigthread_variables - : (unsigned long int *) ((__stack & __hurd_threadvar_stack_mask) + - __hurd_threadvar_stack_offset))[__index]; -} -# endif -#endif - -#include <machine-sp.h> /* Define __thread_stack_pointer. */ - -/* Return the location of the current thread's value for the - per-thread variable with index INDEX. */ - -extern unsigned long int * -__hurd_threadvar_location (enum __hurd_threadvar_index __index) __THROW - /* This declaration tells the compiler that the value is constant - given the same argument. We assume this won't be called twice from - the same stack frame by different threads. */ - __attribute__ ((__const__)); - -#if defined __USE_EXTERN_INLINES && defined _LIBC -# if IS_IN (libc) -_HURD_THREADVAR_H_EXTERN_INLINE unsigned long int * -__hurd_threadvar_location (enum __hurd_threadvar_index __index) -{ - return __hurd_threadvar_location_from_sp (__index, - __thread_stack_pointer ()); -} -# endif -#endif - +/* This returns either the TLS reply port variable, or a single-thread variable + when TLS is not initialized yet. */ +#define __hurd_local_reply_port (*(__LIBC_NO_TLS() ? &__hurd_reply_port0 : &THREAD_SELF->reply_port)) #endif /* hurd/threadvar.h */ diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c index 198546fbb3..8069de391f 100644 --- a/hurd/hurdsig.c +++ b/hurd/hurdsig.c @@ -49,7 +49,6 @@ thread_t _hurd_sigthread; /* 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; @@ -235,14 +234,14 @@ 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. */ + /* Faulted trying to read the TCB. */ return NULL; /* Fault now if this pointer is bogus. */ @@ -324,7 +323,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); @@ -836,7 +836,8 @@ _hurd_internal_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 @@ -902,7 +903,8 @@ _hurd_internal_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) { @@ -1256,7 +1258,8 @@ _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 + if (!cthread_fork) { err = __thread_create (__mach_task_self (), &_hurd_msgport_thread); assert_perror (err); @@ -1269,14 +1272,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)); - __hurd_sigthread_variables[_HURD_THREADVAR_LOCALE] - = (unsigned long int) &_nl_global_locale; /* Reinitialize the MiG support routines so they will use a per-thread variable for the cached reply port. */ @@ -1296,7 +1291,6 @@ _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 #pragma weak pthread_getattr_np #pragma weak pthread_attr_getstack diff --git a/hurd/hurdstartup.c b/hurd/hurdstartup.c index bd9eca27b7..b148125c96 100644 --- a/hurd/hurdstartup.c +++ b/hurd/hurdstartup.c @@ -23,7 +23,6 @@ #include <hurd.h> #include <hurd/exec_startup.h> #include <sysdep.h> -#include <hurd/threadvar.h> #include <unistd.h> #include <elf.h> #include <set-hooks.h> diff --git a/hurd/sigunwind.c b/hurd/sigunwind.c index 4db9827d44..40e0f679f7 100644 --- a/hurd/sigunwind.c +++ b/hurd/sigunwind.c @@ -18,6 +18,7 @@ #include <hurd.h> #include <thread_state.h> +#include <hurd/threadvar.h> #include <jmpbuf-unwind.h> #include <assert.h> #include <stdint.h> @@ -38,8 +39,7 @@ _hurdsig_longjmp_from_handler (void *data, jmp_buf env, int val) { /* Destroy the MiG reply port used by the signal handler, and restore the reply port in use by the thread when interrupted. */ - mach_port_t *reply_port = - (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY); + mach_port_t *reply_port = &__hurd_local_reply_port; if (*reply_port) { mach_port_t port = *reply_port; |