mirror of git://sourceware.org/git/glibc.git
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:
parent
d482ebfa67
commit
9cec82de71
|
@ -43,8 +43,6 @@ libpthread {
|
||||||
|
|
||||||
__pthread_mutex_transfer_np;
|
__pthread_mutex_transfer_np;
|
||||||
|
|
||||||
_cthread_init_routine;
|
|
||||||
|
|
||||||
cthread_detach;
|
cthread_detach;
|
||||||
cthread_fork;
|
cthread_fork;
|
||||||
cthread_keycreate;
|
cthread_keycreate;
|
||||||
|
@ -168,6 +166,8 @@ libpthread {
|
||||||
}
|
}
|
||||||
|
|
||||||
GLIBC_PRIVATE {
|
GLIBC_PRIVATE {
|
||||||
|
__pthread_initialize_minimal;
|
||||||
|
|
||||||
__shm_directory;
|
__shm_directory;
|
||||||
__pthread_threads;
|
__pthread_threads;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pthread initializer is weak in glibc. It must be included if glibc
|
/* pthread initializer is weak in glibc. It must be included if glibc
|
||||||
is to start threading. */
|
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
|
/* Weak references in glibc that must be filled if glibc is to be
|
||||||
thread safe. */
|
thread safe. */
|
||||||
|
|
|
@ -143,9 +143,6 @@ libc {
|
||||||
__cthread_fork; __cthread_detach;
|
__cthread_fork; __cthread_detach;
|
||||||
__pthread_getattr_np; __pthread_attr_getstack;
|
__pthread_getattr_np; __pthread_attr_getstack;
|
||||||
|
|
||||||
# variables used for detecting cthreads
|
|
||||||
_cthread_exit_routine; _cthread_init_routine;
|
|
||||||
|
|
||||||
# cthreads functions with stubs in libc
|
# cthreads functions with stubs in libc
|
||||||
__cthread_keycreate; __cthread_getspecific; __cthread_setspecific;
|
__cthread_keycreate; __cthread_getspecific; __cthread_setspecific;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,13 +28,6 @@
|
||||||
|
|
||||||
__thread struct __pthread *___pthread_self;
|
__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
|
static void
|
||||||
reset_pthread_total (void)
|
reset_pthread_total (void)
|
||||||
{
|
{
|
||||||
|
@ -45,7 +38,7 @@ reset_pthread_total (void)
|
||||||
/* This function is called from the Hurd-specific startup code. It
|
/* This function is called from the Hurd-specific startup code. It
|
||||||
should return a new stack pointer for the main thread. The caller
|
should return a new stack pointer for the main thread. The caller
|
||||||
will switch to this new stack before doing anything serious. */
|
will switch to this new stack before doing anything serious. */
|
||||||
static void *
|
static void
|
||||||
_init_routine (void *stack)
|
_init_routine (void *stack)
|
||||||
{
|
{
|
||||||
struct __pthread *thread;
|
struct __pthread *thread;
|
||||||
|
@ -54,7 +47,7 @@ _init_routine (void *stack)
|
||||||
|
|
||||||
if (__pthread_threads != NULL)
|
if (__pthread_threads != NULL)
|
||||||
/* Already initialized */
|
/* Already initialized */
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
/* Initialize the library. */
|
/* Initialize the library. */
|
||||||
___pthread_init ();
|
___pthread_init ();
|
||||||
|
@ -96,14 +89,12 @@ _init_routine (void *stack)
|
||||||
|
|
||||||
/* Make MiG code thread aware. */
|
/* Make MiG code thread aware. */
|
||||||
__mig_init (thread->stackaddr);
|
__mig_init (thread->stackaddr);
|
||||||
|
|
||||||
return thread->mcontext.sp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
void
|
||||||
init_routine (void)
|
__pthread_initialize_minimal (void)
|
||||||
{
|
{
|
||||||
return _init_routine (0);
|
_init_routine (__libc_stack_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHARED
|
#ifdef SHARED
|
||||||
|
|
|
@ -46,9 +46,6 @@ extern int __libc_argc attribute_hidden;
|
||||||
extern char **__libc_argv attribute_hidden;
|
extern char **__libc_argv attribute_hidden;
|
||||||
extern char **_dl_argv;
|
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.
|
/* Things that want to be run before _hurd_init or much anything else.
|
||||||
Importantly, these are called before anything tries to use malloc. */
|
Importantly, these are called before anything tries to use malloc. */
|
||||||
DEFINE_HOOK (_hurd_preinit_hook, (void));
|
DEFINE_HOOK (_hurd_preinit_hook, (void));
|
||||||
|
@ -96,10 +93,6 @@ init1 (int argc, char *arg0, ...)
|
||||||
++envp;
|
++envp;
|
||||||
d = (void *) ++envp;
|
d = (void *) ++envp;
|
||||||
|
|
||||||
/* Initialize libpthread if linked in. */
|
|
||||||
if (__pthread_initialize_minimal != NULL)
|
|
||||||
__pthread_initialize_minimal ();
|
|
||||||
|
|
||||||
if ((void *) d == argv[0])
|
if ((void *) d == argv[0])
|
||||||
/* No Hurd data block to process. */
|
/* No Hurd data block to process. */
|
||||||
return;
|
return;
|
||||||
|
@ -145,7 +138,6 @@ init (int *data)
|
||||||
int argc = *data;
|
int argc = *data;
|
||||||
char **argv = (void *) (data + 1);
|
char **argv = (void *) (data + 1);
|
||||||
char **envp = &argv[argc + 1];
|
char **envp = &argv[argc + 1];
|
||||||
struct hurd_startup_data *d;
|
|
||||||
|
|
||||||
/* Since the cthreads initialization code uses malloc, and the
|
/* Since the cthreads initialization code uses malloc, and the
|
||||||
malloc initialization code needs to get at the environment, make
|
malloc initialization code needs to get at the environment, make
|
||||||
|
@ -154,11 +146,13 @@ init (int *data)
|
||||||
stored. */
|
stored. */
|
||||||
__environ = envp;
|
__environ = envp;
|
||||||
|
|
||||||
|
#ifndef SHARED
|
||||||
|
struct hurd_startup_data *d;
|
||||||
|
|
||||||
while (*envp)
|
while (*envp)
|
||||||
++envp;
|
++envp;
|
||||||
d = (void *) ++envp;
|
d = (void *) ++envp;
|
||||||
|
|
||||||
#ifndef SHARED
|
|
||||||
/* If we are the bootstrap task started by the kernel,
|
/* If we are the bootstrap task started by the kernel,
|
||||||
then after the environment pointers there is no Hurd
|
then after the environment pointers there is no Hurd
|
||||||
data block; the argument strings start there. */
|
data block; the argument strings start there. */
|
||||||
|
@ -190,79 +184,27 @@ init (int *data)
|
||||||
__libc_setup_tls ();
|
__libc_setup_tls ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* After possibly switching stacks, call `init1' (above) with the user
|
/* Call `init1' (above) with the user code as the return address, and the
|
||||||
code as the return address, and the argument data immediately above
|
argument data immediately above that on the stack. */
|
||||||
that on the stack. */
|
|
||||||
|
|
||||||
if (&_cthread_init_routine && _cthread_init_routine)
|
int usercode;
|
||||||
{
|
|
||||||
/* Initialize cthreads, which will allocate us a new stack to run on. */
|
|
||||||
int *newsp = (*_cthread_init_routine) ();
|
|
||||||
struct hurd_startup_data *od;
|
|
||||||
|
|
||||||
void switch_stacks (void);
|
void call_init1 (void);
|
||||||
|
|
||||||
__libc_stack_end = newsp;
|
/* The argument data is just above the stack frame we will unwind by
|
||||||
|
returning. Mutate our own return address to run the code below. */
|
||||||
/* Copy the argdata from the old stack to the new one. */
|
/* The following expression would typically be written as
|
||||||
newsp = memcpy (newsp - ((char *) &d[1] - (char *) data), data,
|
``__builtin_return_address (0)''. But, for example, GCC 4.4.6 doesn't
|
||||||
(char *) d - (char *) data);
|
recognize that this read operation may alias the following write
|
||||||
|
operation, and thus is free to reorder the two, clobbering the
|
||||||
#ifdef SHARED
|
original return address. */
|
||||||
/* And readjust the dynamic linker's idea of where the argument
|
usercode = *((int *) __builtin_frame_address (0) + 1);
|
||||||
vector lives. */
|
/* GCC 4.4.6 also wants us to force loading USERCODE already here. */
|
||||||
assert (_dl_argv == argv);
|
asm volatile ("# %0" : : "X" (usercode));
|
||||||
_dl_argv = (void *) (newsp + 1);
|
*((void **) __builtin_frame_address (0) + 1) = &call_init1;
|
||||||
#endif
|
/* Force USERCODE into %eax and &init1 into %ecx, which are not
|
||||||
|
restored by function return. */
|
||||||
/* Set up the Hurd startup data block immediately following
|
asm volatile ("# a %0 c %1" : : "a" (usercode), "c" (&init1));
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
DIAG_POP_NEEDS_COMMENT; /* -Warray-bounds. */
|
DIAG_POP_NEEDS_COMMENT; /* -Warray-bounds. */
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_lock_solid F
|
||||||
HURD_CTHREADS_0.3 __spin_try_lock F
|
HURD_CTHREADS_0.3 __spin_try_lock F
|
||||||
HURD_CTHREADS_0.3 __spin_unlock F
|
HURD_CTHREADS_0.3 __spin_unlock F
|
||||||
HURD_CTHREADS_0.3 _cthread_exit_routine D 0x4
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ GLIBC_2.12 __pthread_spin_init F
|
||||||
GLIBC_2.12 __pthread_spin_lock F
|
GLIBC_2.12 __pthread_spin_lock F
|
||||||
GLIBC_2.12 __pthread_spin_trylock F
|
GLIBC_2.12 __pthread_spin_trylock F
|
||||||
GLIBC_2.12 __pthread_spin_unlock 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_flockfile F
|
||||||
GLIBC_2.12 _cthreads_ftrylockfile F
|
GLIBC_2.12 _cthreads_ftrylockfile F
|
||||||
GLIBC_2.12 _cthreads_funlockfile F
|
GLIBC_2.12 _cthreads_funlockfile F
|
||||||
|
|
|
@ -39,16 +39,6 @@
|
||||||
envp = p; \
|
envp = p; \
|
||||||
} while (0)
|
} 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) \
|
#define RETURN_TO(sp, pc, retval) \
|
||||||
asm volatile ("movl %0, %%esp; jmp %*%1 # %2" \
|
asm volatile ("movl %0, %%esp; jmp %*%1 # %2" \
|
||||||
: : "g" (sp), "r" (pc), "a" (retval))
|
: : "g" (sp), "r" (pc), "a" (retval))
|
||||||
|
|
|
@ -62,14 +62,6 @@
|
||||||
#error SNARF_ARGS not defined by sysdeps/mach/MACHINE/sysdep.h
|
#error SNARF_ARGS not defined by sysdeps/mach/MACHINE/sysdep.h
|
||||||
#endif
|
#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
|
/* LOSE can be defined as the `halt' instruction or something
|
||||||
similar which will cause the process to die in a characteristic
|
similar which will cause the process to die in a characteristic
|
||||||
way suggesting a bug. */
|
way suggesting a bug. */
|
||||||
|
|
Loading…
Reference in New Issue