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.
This commit is contained in:
Samuel Thibault 2018-03-17 23:27:34 +01:00
parent 34e6a8694d
commit dc33bef307
23 changed files with 188 additions and 263 deletions

View file

@ -3,6 +3,81 @@
* hurd/hurdsig.c: Include <pthread.h>.
(_hurdsig_init): Call pthread_getattr_np and pthread_attr_getstack to
get the signal thread stack layout.
* 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.
2018-03-16 Samuel Thibault <samuel.thibault@ens-lyon.org>

View file

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

View file

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

View file

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

View file

@ -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 */

View file

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

View file

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

View file

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

View file

@ -6,6 +6,7 @@ libc {
GLIBC_PRIVATE {
# Functions shared with the dynamic linker
__libc_read; __libc_write; __libc_lseek64;
__libc_lock_self0;
_dl_init_first;
}
@ -14,8 +15,6 @@ libc {
ld {
GLIBC_2.0 {
# variables that must be shared with libc
__hurd_sigthread_stack_base; __hurd_sigthread_stack_end;
__hurd_sigthread_variables;
__hurd_threadvar_stack_mask; __hurd_threadvar_stack_offset;
# functions that must be shared with libc
@ -33,5 +32,6 @@ ld {
# functions that must be shared with libc
__libc_read; __libc_write; __libc_lseek64;
__libc_lock_self0;
}
}

View file

@ -19,6 +19,10 @@
#include <errno.h>
#include <stdlib.h>
/* This serves as stub "self" pointer for libc locks when TLS is not initialized
yet. */
char __libc_lock_self0[0];
/* Placeholder for key creation routine from Hurd cthreads library. */
int
weak_function

View file

@ -70,25 +70,6 @@ void *_dl_random attribute_relro = NULL;
struct hurd_startup_data *_dl_hurd_data;
/* This is used only within ld.so, via dl-minimal.c's __errno_location. */
#undef errno
int errno attribute_hidden;
/* Defining these variables here avoids the inclusion of hurdsig.c. */
unsigned long int __hurd_sigthread_stack_base;
unsigned long int __hurd_sigthread_stack_end;
unsigned long int *__hurd_sigthread_variables;
/* Defining these variables here avoids the inclusion of init-first.c.
We need to provide temporary storage for the per-thread variables
of the main user thread here, since it is used for storing the
`errno' variable. Note that this information is lost once we
relocate the dynamic linker. */
static unsigned long int threadvars[_HURD_THREADVAR_MAX];
unsigned long int __hurd_threadvar_stack_offset
= (unsigned long int) &threadvars;
unsigned long int __hurd_threadvar_stack_mask;
#define FMH defined(__i386__)
#if ! FMH
# define fmh() ((void)0)

View file

@ -16,13 +16,21 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <hurd/threadvar.h>
int *
#if IS_IN (rtld)
/*
* rtld can not access TLS too early, thus rtld_errno.
*
* Instead of making __open/__close pass errno from TLS to rtld_errno, simply
* use a weak __errno_location using rtld_errno, which will be overriden by the
* libc definition.
*/
static int rtld_errno;
int * weak_function
__errno_location (void)
{
return (int *) __hurd_threadvar_location (_HURD_THREADVAR_ERRNO);
return &rtld_errno;
}
strong_alias (__errno_location, __hurd_errno_location)
libc_hidden_def (__errno_location)
libc_hidden_weak (__errno_location)
#else
#include "../../../csu/errno-loc.c"
#endif

View file

@ -1 +0,0 @@
/* No definition of `errno' variable on the Hurd. */

View file

@ -19,6 +19,7 @@
#include <unistd.h>
#include <hurd.h>
#include <hurd/signal.h>
#include <hurd/threadvar.h>
#include <setjmp.h>
#include <thread_state.h>
#include <sysdep.h> /* For stack growth direction. */
@ -483,19 +484,17 @@ __fork (void)
(natural_t *) &state, &statecount))
LOSE;
#ifdef STACK_GROWTH_UP
#define THREADVAR_SPACE (__hurd_threadvar_max \
* sizeof *__hurd_sightread_variables)
if (__hurd_sigthread_stack_base == 0)
{
state.SP &= __hurd_threadvar_stack_mask;
state.SP += __hurd_threadvar_stack_offset + THREADVAR_SPACE;
state.SP += __hurd_threadvar_stack_offset;
}
else
state.SP = __hurd_sigthread_stack_base;
#else
if (__hurd_sigthread_stack_end == 0)
{
/* The signal thread has a normal stack assigned by cthreads.
/* The signal thread has a stack assigned by cthreads.
The threadvar_stack variables conveniently tell us how
to get to the highest address in the stack, just below
the per-thread variables. */

View file

@ -35,7 +35,6 @@ extern void __mach_init (void);
extern void __init_misc (int, char **, char **);
extern void __libc_global_ctors (void);
unsigned int __hurd_threadvar_max;
unsigned long int __hurd_threadvar_stack_offset;
unsigned long int __hurd_threadvar_stack_mask;
@ -169,15 +168,6 @@ init (int *data)
char **argv = (void *) (data + 1);
char **envp = &argv[argc + 1];
struct hurd_startup_data *d;
unsigned long int threadvars[_HURD_THREADVAR_MAX];
/* Provide temporary storage for thread-specific variables on the
startup stack so the cthreads initialization code can use them
for malloc et al, or so we can use malloc below for the real
threadvars array. */
memset (threadvars, 0, sizeof threadvars);
threadvars[_HURD_THREADVAR_LOCALE] = (unsigned long int) &_nl_global_locale;
__hurd_threadvar_stack_offset = (unsigned long int) threadvars;
/* Since the cthreads initialization code uses malloc, and the
malloc initialization code needs to get at the environment, make
@ -190,13 +180,6 @@ init (int *data)
++envp;
d = (void *) ++envp;
/* The user might have defined a value for this, to get more variables.
Otherwise it will be zero on startup. We must make sure it is set
properly before before cthreads initialization, so cthreads can know
how much space to leave for thread variables. */
if (__hurd_threadvar_max < _HURD_THREADVAR_MAX)
__hurd_threadvar_max = _HURD_THREADVAR_MAX;
/* After possibly switching stacks, call `init1' (above) with the user
code as the return address, and the argument data immediately above
@ -212,11 +195,6 @@ init (int *data)
__libc_stack_end = newsp;
/* Copy per-thread variables from that temporary
area onto the new cthread stack. */
memcpy (__hurd_threadvar_location_from_sp (0, newsp),
threadvars, sizeof threadvars);
/* Copy the argdata from the old stack to the new one. */
newsp = memcpy (newsp - ((char *) &d[1] - (char *) data), data,
(char *) d - (char *) data);
@ -257,25 +235,10 @@ init (int *data)
}
else
{
/* We are not using cthreads, so we will have just a single allocated
area for the per-thread variables of the main user thread. */
unsigned long int *array;
unsigned int i;
int usercode;
void call_init1 (void);
array = malloc (__hurd_threadvar_max * sizeof (unsigned long int));
if (array == NULL)
__libc_fatal ("Can't allocate single-threaded thread variables.");
/* Copy per-thread variables from the temporary array into the
newly malloc'd space. */
memcpy (array, threadvars, sizeof threadvars);
__hurd_threadvar_stack_offset = (unsigned long int) array;
for (i = _HURD_THREADVAR_MAX; i < __hurd_threadvar_max; ++i)
array[i] = 0;
/* The argument data is just above the stack frame we will unwind by
returning. Mutate our own return address to run the code below. */
/* The following expression would typically be written as

View file

@ -285,7 +285,6 @@ GLIBC_2.2.6 __gettimeofday F
GLIBC_2.2.6 __gmtime_r F
GLIBC_2.2.6 __h_errno_location F
GLIBC_2.2.6 __hurd_fail F
GLIBC_2.2.6 __hurd_threadvar_max D 0x4
GLIBC_2.2.6 __hurd_threadvar_stack_mask D 0x4
GLIBC_2.2.6 __hurd_threadvar_stack_offset D 0x4
GLIBC_2.2.6 __isalnum_l F

View file

@ -68,7 +68,7 @@ __sigreturn (struct sigcontext *scp)
if (scp->sc_onstack)
{
ss->sigaltstack.ss_flags &= ~SS_ONSTACK; /* XXX threadvars */
ss->sigaltstack.ss_flags &= ~SS_ONSTACK;
/* XXX cannot unlock until off sigstack */
abort ();
}
@ -77,8 +77,7 @@ __sigreturn (struct sigcontext *scp)
/* Destroy the MiG reply port used by the signal handler, and restore the
reply port in use by the thread when interrupted. */
reply_port =
(mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY);
reply_port = &__hurd_local_reply_port;
if (*reply_port)
{
mach_port_t port = *reply_port;

View file

@ -43,9 +43,27 @@ typedef struct
void *__private_tm[4];
/* GCC split stack support. */
void *__private_ss;
/* Keep this field last, so fields above can continue being compatible with
the Linux version. */
mach_port_t reply_port; /* This thread's reply port. */
struct hurd_sigstate *_hurd_sigstate;
} tcbhead_t;
#endif
/* Return tcbhead_t from a TLS segment descriptor. */
# define HURD_DESC_TLS(desc) \
({ \
(tcbhead_t *) ( (desc->low_word >> 16) \
| ((desc->high_word & 0xff) << 16) \
| (desc->high_word & 0xff000000)); \
})
/* Return 1 if TLS is not initialized yet. */
#define __LIBC_NO_TLS() \
({ unsigned short ds, gs; \
asm ("movw %%ds,%w0; movw %%gs,%w1" : "=q" (ds), "=q" (gs)); \
__builtin_expect(ds == gs, 0); })
/* The TCB can have any size and the memory following the address the
thread pointer points to is unspecified. Allocate the TCB there. */
@ -138,6 +156,21 @@ _hurd_tls_init (tcbhead_t *tcb)
: "i" (offsetof (tcbhead_t, tcb))); \
__tcb;})
/* Return the TCB address of a thread given its state.
Note: this is expensive. */
# define THREAD_TCB(thread, thread_state) \
({ int __sel = (thread_state)->basic.gs; \
struct descriptor __desc, *___desc = &__desc; \
unsigned int __count = 1; \
kern_return_t __err; \
if (HURD_SEL_LDT(__sel)) \
__err = __i386_get_ldt ((thread), __sel, 1, &___desc, &__count); \
else \
__err = __i386_get_gdt ((thread), __sel, &__desc); \
assert_perror (__err); \
assert (__count == 1); \
HURD_DESC_TLS(___desc);})
/* Install new dtv for current thread. */
# define INSTALL_NEW_DTV(dtvp) \
({ asm volatile ("movl %0,%%gs:%P1" \

View file

@ -79,8 +79,6 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
{
sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size;
ss->sigaltstack.ss_flags |= SS_ONSTACK;
/* XXX need to set up base of new stack for
per-thread variables, cthreads. */
}
/* This code has intimate knowledge of the special mach_msg system call
done in intr-msg.c; that code does (see intr-msg.h):

View file

@ -21,7 +21,6 @@
#if (_LIBC - 0) || (_CTHREADS_ - 0)
#include <cthreads.h>
#include <hurd/threadvar.h>
/* The locking here is very inexpensive, even for inlining. */
#define _IO_lock_inexpensive 1
@ -35,7 +34,8 @@ typedef struct
} __libc_lock_recursive_t;
typedef __libc_lock_recursive_t __rtld_lock_recursive_t;
#define __libc_lock_owner_self() ((void *) __hurd_threadvar_location (0))
extern char __libc_lock_self0[0];
#define __libc_lock_owner_self() (__LIBC_NO_TLS() ? &__libc_lock_self0 : THREAD_SELF)
#else
typedef struct __libc_lock_opaque__ __libc_lock_t;

View file

@ -1,34 +0,0 @@
/* libc-internal interface for thread-specific data. Hurd version.
Copyright (C) 1998-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _LIBC_TSD_H
#define _LIBC_TSD_H 1
#include <hurd/threadvar.h>
#define __libc_tsd_define(CLASS, TYPE, KEY) /* nothing, always have threadvars */
#define __libc_tsd_address(TYPE, KEY) \
((TYPE *) __hurd_threadvar_location (_HURD_THREADVAR_##KEY))
#define __libc_tsd_get(TYPE, KEY) \
(*__libc_tsd_address (TYPE, KEY))
#define __libc_tsd_set(TYPE, KEY, VALUE) \
(*__libc_tsd_address (TYPE, KEY) = (VALUE))
#endif /* libc-tsd.h */

View file

@ -18,26 +18,20 @@
#include <mach.h>
#include <hurd/threadvar.h>
#define GETPORT \
mach_port_t *portloc = \
(mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY)
#define reply_port (*(use_threadvar ? portloc : &global_reply_port))
static int use_threadvar;
static mach_port_t global_reply_port;
/* These functions are called by MiG-generated code. */
mach_port_t __hurd_reply_port0;
/* Called by MiG to get a reply port. */
mach_port_t
__mig_get_reply_port (void)
{
GETPORT;
if (__hurd_local_reply_port == MACH_PORT_NULL ||
(&__hurd_local_reply_port != &__hurd_reply_port0
&& __hurd_local_reply_port == __hurd_reply_port0))
__hurd_local_reply_port = __mach_reply_port ();
if (reply_port == MACH_PORT_NULL)
reply_port = __mach_reply_port ();
return reply_port;
return __hurd_local_reply_port;
}
weak_alias (__mig_get_reply_port, mig_get_reply_port)
@ -45,12 +39,8 @@ weak_alias (__mig_get_reply_port, mig_get_reply_port)
void
__mig_dealloc_reply_port (mach_port_t arg)
{
mach_port_t port;
GETPORT;
port = reply_port;
reply_port = MACH_PORT_NULL; /* So the mod_refs RPC won't use it. */
mach_port_t port = __hurd_local_reply_port;
__hurd_local_reply_port = MACH_PORT_NULL; /* So the mod_refs RPC won't use it. */
if (MACH_PORT_VALID (port))
__mach_port_mod_refs (__mach_task_self (), port,
@ -73,15 +63,6 @@ weak_alias (__mig_put_reply_port, mig_put_reply_port)
void
__mig_init (void *stack)
{
use_threadvar = stack != 0;
if (use_threadvar)
{
/* Recycle the reply port used before multithreading was enabled. */
mach_port_t *portloc = (mach_port_t *)
__hurd_threadvar_location_from_sp (_HURD_THREADVAR_MIG_REPLY, stack);
*portloc = global_reply_port;
global_reply_port = MACH_PORT_NULL;
}
/* Do nothing. */
}
weak_alias (__mig_init, mig_init)

View file

@ -141,7 +141,7 @@ weak_alias (__profil, profil)
static volatile error_t special_profil_failure;
/* Fetch PC samples. This function must be very careful not to depend
on Hurd threadvar variables. We arrange that by using a special
on Hurd TLS variables. We arrange that by using a special
stub arranged for at the end of this file. */
static void
fetch_samples (void)
@ -176,7 +176,7 @@ fetch_samples (void)
}
/* This function must be very careful not to depend on Hurd threadvar
/* This function must be very careful not to depend on Hurd TLS
variables. We arrange that by using special stubs arranged for at the
end of this file. */
static void
@ -267,7 +267,7 @@ text_set_element (_hurd_fork_child_hook, fork_profil_child);
are fatal in profile_waiter anyhow. */
#define __mig_put_reply_port(foo)
/* Use our static variable instead of the usual threadvar mechanism for
/* Use our static variable instead of the usual TLS mechanism for
this. */
#define __mig_get_reply_port() profil_reply_port