htl: Initialize later

Since htl does not actually need a stack switch, we can initialize it
like nptl is, avoiding all sorts of startup issues with ifunc.

More precisely, htl defines __pthread_initialize_minimal instead of the
elder _cthread_init_routine. We can then drop the stack switching dances.
This commit is contained in:
Samuel Thibault 2020-11-11 10:35:10 +00:00
parent d482ebfa67
commit 9cec82de71
9 changed files with 29 additions and 119 deletions

View file

@ -43,8 +43,6 @@ libpthread {
__pthread_mutex_transfer_np;
_cthread_init_routine;
cthread_detach;
cthread_fork;
cthread_keycreate;
@ -168,6 +166,8 @@ libpthread {
}
GLIBC_PRIVATE {
__pthread_initialize_minimal;
__shm_directory;
__pthread_threads;

View file

@ -1,6 +1,6 @@
/* pthread initializer is weak in glibc. It must be included if glibc
is to start threading. */
EXTERN(_cthread_init_routine)
EXTERN(__pthread_initialize_minimal)
/* Weak references in glibc that must be filled if glibc is to be
thread safe. */

View file

@ -143,9 +143,6 @@ libc {
__cthread_fork; __cthread_detach;
__pthread_getattr_np; __pthread_attr_getstack;
# variables used for detecting cthreads
_cthread_exit_routine; _cthread_init_routine;
# cthreads functions with stubs in libc
__cthread_keycreate; __cthread_getspecific; __cthread_setspecific;
}

View file

@ -28,13 +28,6 @@
__thread struct __pthread *___pthread_self;
/* Forward. */
static void *init_routine (void);
/* OK, the name of this variable isn't really appropriate, but I don't
want to change it yet. */
void *(*_cthread_init_routine) (void) = &init_routine;
static void
reset_pthread_total (void)
{
@ -45,7 +38,7 @@ reset_pthread_total (void)
/* This function is called from the Hurd-specific startup code. It
should return a new stack pointer for the main thread. The caller
will switch to this new stack before doing anything serious. */
static void *
static void
_init_routine (void *stack)
{
struct __pthread *thread;
@ -54,7 +47,7 @@ _init_routine (void *stack)
if (__pthread_threads != NULL)
/* Already initialized */
return 0;
return;
/* Initialize the library. */
___pthread_init ();
@ -96,14 +89,12 @@ _init_routine (void *stack)
/* Make MiG code thread aware. */
__mig_init (thread->stackaddr);
return thread->mcontext.sp;
}
static void *
init_routine (void)
void
__pthread_initialize_minimal (void)
{
return _init_routine (0);
_init_routine (__libc_stack_end);
}
#ifdef SHARED

View file

@ -46,9 +46,6 @@ extern int __libc_argc attribute_hidden;
extern char **__libc_argv attribute_hidden;
extern char **_dl_argv;
extern void *(*_cthread_init_routine) (void) __attribute__ ((weak));
void (*_cthread_exit_routine) (int status) __attribute__ ((__noreturn__));
/* Things that want to be run before _hurd_init or much anything else.
Importantly, these are called before anything tries to use malloc. */
DEFINE_HOOK (_hurd_preinit_hook, (void));
@ -96,10 +93,6 @@ init1 (int argc, char *arg0, ...)
++envp;
d = (void *) ++envp;
/* Initialize libpthread if linked in. */
if (__pthread_initialize_minimal != NULL)
__pthread_initialize_minimal ();
if ((void *) d == argv[0])
/* No Hurd data block to process. */
return;
@ -145,7 +138,6 @@ init (int *data)
int argc = *data;
char **argv = (void *) (data + 1);
char **envp = &argv[argc + 1];
struct hurd_startup_data *d;
/* Since the cthreads initialization code uses malloc, and the
malloc initialization code needs to get at the environment, make
@ -154,11 +146,13 @@ init (int *data)
stored. */
__environ = envp;
#ifndef SHARED
struct hurd_startup_data *d;
while (*envp)
++envp;
d = (void *) ++envp;
#ifndef SHARED
/* If we are the bootstrap task started by the kernel,
then after the environment pointers there is no Hurd
data block; the argument strings start there. */
@ -190,79 +184,27 @@ init (int *data)
__libc_setup_tls ();
#endif
/* After possibly switching stacks, call `init1' (above) with the user
code as the return address, and the argument data immediately above
that on the stack. */
/* Call `init1' (above) with the user code as the return address, and the
argument data immediately above that on the stack. */
if (&_cthread_init_routine && _cthread_init_routine)
{
/* Initialize cthreads, which will allocate us a new stack to run on. */
int *newsp = (*_cthread_init_routine) ();
struct hurd_startup_data *od;
int usercode;
void switch_stacks (void);
void call_init1 (void);
__libc_stack_end = newsp;
/* Copy the argdata from the old stack to the new one. */
newsp = memcpy (newsp - ((char *) &d[1] - (char *) data), data,
(char *) d - (char *) data);
#ifdef SHARED
/* And readjust the dynamic linker's idea of where the argument
vector lives. */
assert (_dl_argv == argv);
_dl_argv = (void *) (newsp + 1);
#endif
/* Set up the Hurd startup data block immediately following
the argument and environment pointers on the new stack. */
od = ((void *) newsp + ((char *) d - (char *) data));
if ((void *) argv[0] == d)
/* We were started up by the kernel with arguments on the stack.
There is no Hurd startup data, so zero the block. */
memset (od, 0, sizeof *od);
else
/* Copy the Hurd startup data block to the new stack. */
*od = *d;
/* Push the user code address on the top of the new stack. It will
be the return address for `init1'; we will jump there with NEWSP
as the stack pointer. */
/* The following expression would typically be written as
``__builtin_return_address (0)''. But, for example, GCC 4.4.6 doesn't
recognize that this read operation may alias the following write
operation, and thus is free to reorder the two, clobbering the
original return address. */
*--newsp = *((int *) __builtin_frame_address (0) + 1);
/* GCC 4.4.6 also wants us to force loading *NEWSP already here. */
asm volatile ("# %0" : : "X" (*newsp));
*((void **) __builtin_frame_address (0) + 1) = &switch_stacks;
/* Force NEWSP into %eax and &init1 into %ecx, which are not restored
by function return. */
asm volatile ("# a %0 c %1" : : "a" (newsp), "c" (&init1));
}
else
{
int usercode;
void call_init1 (void);
/* 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
``__builtin_return_address (0)''. But, for example, GCC 4.4.6 doesn't
recognize that this read operation may alias the following write
operation, and thus is free to reorder the two, clobbering the
original return address. */
usercode = *((int *) __builtin_frame_address (0) + 1);
/* GCC 4.4.6 also wants us to force loading USERCODE already here. */
asm volatile ("# %0" : : "X" (usercode));
*((void **) __builtin_frame_address (0) + 1) = &call_init1;
/* Force USERCODE into %eax and &init1 into %ecx, which are not
restored by function return. */
asm volatile ("# a %0 c %1" : : "a" (usercode), "c" (&init1));
}
/* 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
``__builtin_return_address (0)''. But, for example, GCC 4.4.6 doesn't
recognize that this read operation may alias the following write
operation, and thus is free to reorder the two, clobbering the
original return address. */
usercode = *((int *) __builtin_frame_address (0) + 1);
/* GCC 4.4.6 also wants us to force loading USERCODE already here. */
asm volatile ("# %0" : : "X" (usercode));
*((void **) __builtin_frame_address (0) + 1) = &call_init1;
/* Force USERCODE into %eax and &init1 into %ecx, which are not
restored by function return. */
asm volatile ("# a %0 c %1" : : "a" (usercode), "c" (&init1));
DIAG_POP_NEEDS_COMMENT; /* -Warray-bounds. */
}

View file

@ -2333,4 +2333,3 @@ HURD_CTHREADS_0.3 __spin_lock_init F
HURD_CTHREADS_0.3 __spin_lock_solid F
HURD_CTHREADS_0.3 __spin_try_lock F
HURD_CTHREADS_0.3 __spin_unlock F
HURD_CTHREADS_0.3 _cthread_exit_routine D 0x4

View file

@ -10,7 +10,6 @@ GLIBC_2.12 __pthread_spin_init F
GLIBC_2.12 __pthread_spin_lock F
GLIBC_2.12 __pthread_spin_trylock F
GLIBC_2.12 __pthread_spin_unlock F
GLIBC_2.12 _cthread_init_routine D 0x4
GLIBC_2.12 _cthreads_flockfile F
GLIBC_2.12 _cthreads_ftrylockfile F
GLIBC_2.12 _cthreads_funlockfile F

View file

@ -39,16 +39,6 @@
envp = p; \
} while (0)
#define CALL_WITH_SP(fn, info, sp) \
do { \
void **ptr = (void **) sp; \
*--(__typeof (info) *) ptr = info; \
ptr[-1] = ptr; \
--ptr; \
asm volatile ("movl %0, %%esp; call %1" : : \
"g" (ptr), "m" (*(long int *) (fn)) : "%esp"); \
} while (0)
#define RETURN_TO(sp, pc, retval) \
asm volatile ("movl %0, %%esp; jmp %*%1 # %2" \
: : "g" (sp), "r" (pc), "a" (retval))

View file

@ -62,14 +62,6 @@
#error SNARF_ARGS not defined by sysdeps/mach/MACHINE/sysdep.h
#endif
/* Call the C function FN with no arguments,
on a stack starting at SP (as returned by *_cthread_init_routine).
You don't need to deal with FN returning; it shouldn't. */
#ifndef CALL_WITH_SP
#define CALL_WITH_SP(fn, sp)
#error CALL_WITH_SP not defined by sysdeps/mach/MACHINE/sysdep.h
#endif
/* LOSE can be defined as the `halt' instruction or something
similar which will cause the process to die in a characteristic
way suggesting a bug. */