mirror of
git://sourceware.org/git/glibc.git
synced 2025-01-18 12:16:13 +08:00
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;
|
||||
|
||||
_cthread_init_routine;
|
||||
|
||||
cthread_detach;
|
||||
cthread_fork;
|
||||
cthread_keycreate;
|
||||
@ -168,6 +166,8 @@ libpthread {
|
||||
}
|
||||
|
||||
GLIBC_PRIVATE {
|
||||
__pthread_initialize_minimal;
|
||||
|
||||
__shm_directory;
|
||||
__pthread_threads;
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user