mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
* elf/dl-close.c (_dl_close_worker): When removing object from
global scope, wait for all lookups to finish afterwards. * elf/dl-open.c (add_to_global): When global scope array must grow, allocate a new one and free old array only after all lookups finish. * elf/dl-runtime.c (_dl_fixup): Protect using global scope. (_dl_lookup_symbol_x): Likewise. * elf/dl-support.c: Define _dl_wait_lookup_done. * sysdeps/generic/ldsodefs.h (struct rtld_global): Add _dl_wait_lookup_done.
This commit is contained in:
11
ChangeLog
11
ChangeLog
@ -1,5 +1,16 @@
|
|||||||
2007-05-18 Ulrich Drepper <drepper@redhat.com>
|
2007-05-18 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* elf/dl-close.c (_dl_close_worker): When removing object from
|
||||||
|
global scope, wait for all lookups to finish afterwards.
|
||||||
|
* elf/dl-open.c (add_to_global): When global scope array must
|
||||||
|
grow, allocate a new one and free old array only after all
|
||||||
|
lookups finish.
|
||||||
|
* elf/dl-runtime.c (_dl_fixup): Protect using global scope.
|
||||||
|
(_dl_lookup_symbol_x): Likewise.
|
||||||
|
* elf/dl-support.c: Define _dl_wait_lookup_done.
|
||||||
|
* sysdeps/generic/ldsodefs.h (struct rtld_global): Add
|
||||||
|
_dl_wait_lookup_done.
|
||||||
|
|
||||||
* malloc/malloc.c (do_check_chunk): Correct check for mmaped block
|
* malloc/malloc.c (do_check_chunk): Correct check for mmaped block
|
||||||
not overlapping with arena.
|
not overlapping with arena.
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sysdep-cancel.h>
|
#include <sysdep-cancel.h>
|
||||||
|
#include <tls.h>
|
||||||
|
|
||||||
|
|
||||||
/* Type of the constructor functions. */
|
/* Type of the constructor functions. */
|
||||||
@ -487,6 +488,9 @@ _dl_close_worker (struct link_map *map)
|
|||||||
ns_msl->r_list[cnt - 1] = ns_msl->r_list[cnt];
|
ns_msl->r_list[cnt - 1] = ns_msl->r_list[cnt];
|
||||||
|
|
||||||
--ns_msl->r_nlist;
|
--ns_msl->r_nlist;
|
||||||
|
|
||||||
|
if (!RTLD_SINGLE_THREAD_P)
|
||||||
|
THREAD_GSCOPE_WAIT ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove the object from the dtv slotinfo array if it uses TLS. */
|
/* Remove the object from the dtv slotinfo array if it uses TLS. */
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <bp-sym.h>
|
#include <bp-sym.h>
|
||||||
#include <caller.h>
|
#include <caller.h>
|
||||||
#include <sysdep-cancel.h>
|
#include <sysdep-cancel.h>
|
||||||
|
#include <tls.h>
|
||||||
|
|
||||||
#include <dl-dst.h>
|
#include <dl-dst.h>
|
||||||
|
|
||||||
@ -125,15 +126,25 @@ add_to_global (struct link_map *new)
|
|||||||
{
|
{
|
||||||
/* We have to extend the existing array of link maps in the
|
/* We have to extend the existing array of link maps in the
|
||||||
main map. */
|
main map. */
|
||||||
|
struct link_map **old_global
|
||||||
|
= GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list;
|
||||||
|
size_t new_nalloc = ((ns->_ns_global_scope_alloc + to_add) * 2);
|
||||||
|
|
||||||
new_global = (struct link_map **)
|
new_global = (struct link_map **)
|
||||||
realloc (ns->_ns_main_searchlist->r_list,
|
malloc (new_nalloc * sizeof (struct link_map *));
|
||||||
((ns->_ns_global_scope_alloc + to_add + 8)
|
|
||||||
* sizeof (struct link_map *)));
|
|
||||||
if (new_global == NULL)
|
if (new_global == NULL)
|
||||||
goto nomem;
|
goto nomem;
|
||||||
|
|
||||||
ns->_ns_global_scope_alloc += to_add + 8;
|
memcpy (new_global, old_global,
|
||||||
|
ns->_ns_global_scope_alloc * sizeof (struct link_map *));
|
||||||
|
|
||||||
|
ns->_ns_global_scope_alloc = new_nalloc;
|
||||||
ns->_ns_main_searchlist->r_list = new_global;
|
ns->_ns_main_searchlist->r_list = new_global;
|
||||||
|
|
||||||
|
if (!RTLD_SINGLE_THREAD_P)
|
||||||
|
THREAD_GSCOPE_WAIT ();
|
||||||
|
|
||||||
|
free (old_global);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now add the new entries. */
|
/* Now add the new entries. */
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
#include <ldsodefs.h>
|
#include <ldsodefs.h>
|
||||||
#include <sysdep-cancel.h>
|
#include <sysdep-cancel.h>
|
||||||
#include "dynamic-link.h"
|
#include "dynamic-link.h"
|
||||||
|
#include <tls.h>
|
||||||
|
|
||||||
|
|
||||||
#if (!defined ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
|
#if (!defined ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
|
||||||
|| ELF_MACHINE_NO_REL
|
|| ELF_MACHINE_NO_REL
|
||||||
@ -97,11 +99,16 @@ _dl_fixup (
|
|||||||
not necessary for objects which cannot be unloaded or when
|
not necessary for objects which cannot be unloaded or when
|
||||||
we are not using any threads (yet). */
|
we are not using any threads (yet). */
|
||||||
int flags = DL_LOOKUP_ADD_DEPENDENCY;
|
int flags = DL_LOOKUP_ADD_DEPENDENCY;
|
||||||
if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
|
if (!RTLD_SINGLE_THREAD_P)
|
||||||
|
{
|
||||||
|
THREAD_GSCOPE_SET_FLAG ();
|
||||||
|
|
||||||
|
if (l->l_type == lt_loaded)
|
||||||
{
|
{
|
||||||
__rtld_mrlock_lock (l->l_scope_lock);
|
__rtld_mrlock_lock (l->l_scope_lock);
|
||||||
flags |= DL_LOOKUP_SCOPE_LOCK;
|
flags |= DL_LOOKUP_SCOPE_LOCK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope,
|
result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope,
|
||||||
version, ELF_RTYPE_CLASS_PLT, flags, NULL);
|
version, ELF_RTYPE_CLASS_PLT, flags, NULL);
|
||||||
@ -109,6 +116,10 @@ _dl_fixup (
|
|||||||
if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0)
|
if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0)
|
||||||
__rtld_mrlock_unlock (l->l_scope_lock);
|
__rtld_mrlock_unlock (l->l_scope_lock);
|
||||||
|
|
||||||
|
/* We are done with the global scope. */
|
||||||
|
if (!RTLD_SINGLE_THREAD_P)
|
||||||
|
THREAD_GSCOPE_RESET_FLAG ();
|
||||||
|
|
||||||
/* Currently result contains the base load address (or link map)
|
/* Currently result contains the base load address (or link map)
|
||||||
of the object that defines sym. Now add in the symbol
|
of the object that defines sym. Now add in the symbol
|
||||||
offset. */
|
offset. */
|
||||||
@ -191,11 +202,16 @@ _dl_profile_fixup (
|
|||||||
not necessary for objects which cannot be unloaded or when
|
not necessary for objects which cannot be unloaded or when
|
||||||
we are not using any threads (yet). */
|
we are not using any threads (yet). */
|
||||||
int flags = DL_LOOKUP_ADD_DEPENDENCY;
|
int flags = DL_LOOKUP_ADD_DEPENDENCY;
|
||||||
if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P)
|
if (!RTLD_SINGLE_THREAD_P)
|
||||||
|
{
|
||||||
|
THREAD_GSCOPE_SET_FLAG ();
|
||||||
|
|
||||||
|
if (l->l_type == lt_loaded)
|
||||||
{
|
{
|
||||||
__rtld_mrlock_lock (l->l_scope_lock);
|
__rtld_mrlock_lock (l->l_scope_lock);
|
||||||
flags |= DL_LOOKUP_SCOPE_LOCK;
|
flags |= DL_LOOKUP_SCOPE_LOCK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result = _dl_lookup_symbol_x (strtab + refsym->st_name, l,
|
result = _dl_lookup_symbol_x (strtab + refsym->st_name, l,
|
||||||
&defsym, l->l_scope, version,
|
&defsym, l->l_scope, version,
|
||||||
@ -204,6 +220,10 @@ _dl_profile_fixup (
|
|||||||
if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0)
|
if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0)
|
||||||
__rtld_mrlock_unlock (l->l_scope_lock);
|
__rtld_mrlock_unlock (l->l_scope_lock);
|
||||||
|
|
||||||
|
/* We are done with the global scope. */
|
||||||
|
if (!RTLD_SINGLE_THREAD_P)
|
||||||
|
THREAD_GSCOPE_RESET_FLAG ();
|
||||||
|
|
||||||
/* Currently result contains the base load address (or link map)
|
/* Currently result contains the base load address (or link map)
|
||||||
of the object that defines sym. Now add in the symbol
|
of the object that defines sym. Now add in the symbol
|
||||||
offset. */
|
offset. */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Support for dynamic linking code in static libc.
|
/* Support for dynamic linking code in static libc.
|
||||||
Copyright (C) 1996-2005, 2006 Free Software Foundation, Inc.
|
Copyright (C) 1996-2005, 2006, 2007 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -132,6 +132,9 @@ int (*_dl_make_stack_executable_hook) (void **) internal_function
|
|||||||
= _dl_make_stack_executable;
|
= _dl_make_stack_executable;
|
||||||
|
|
||||||
|
|
||||||
|
/* Function in libpthread to wait for termination of lookups. */
|
||||||
|
void (*_dl_wait_lookup_done) (void);
|
||||||
|
|
||||||
#ifdef NEED_DL_SYSINFO
|
#ifdef NEED_DL_SYSINFO
|
||||||
/* Needed for improved syscall handling on at least x86/Linux. */
|
/* Needed for improved syscall handling on at least x86/Linux. */
|
||||||
uintptr_t _dl_sysinfo = DL_SYSINFO_DEFAULT;
|
uintptr_t _dl_sysinfo = DL_SYSINFO_DEFAULT;
|
||||||
|
@ -1,3 +1,16 @@
|
|||||||
|
2007-05-19 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* allocatestack.c (__wait_lookup_done): New function.
|
||||||
|
* sysdeps/pthread/pthread-functions.h (struct pthread_functions):
|
||||||
|
Add ptr_wait_lookup_done.
|
||||||
|
* init.c (pthread_functions): Initialize .ptr_wait_lookup_done.
|
||||||
|
* pthreadP.h: Declare __wait_lookup_done.
|
||||||
|
* sysdeps/i386/tls.h (tcbhead_t): Add gscope_flag.
|
||||||
|
Define macros to implement reference handling of global scope.
|
||||||
|
* sysdeps/x86_64/tls.h: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init):
|
||||||
|
Initialize GL(dl_wait_lookup_done).
|
||||||
|
|
||||||
2007-05-17 Ulrich Drepper <drepper@redhat.com>
|
2007-05-17 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
[BZ #4512]
|
[BZ #4512]
|
||||||
|
@ -996,3 +996,60 @@ __pthread_init_static_tls (struct link_map *map)
|
|||||||
|
|
||||||
lll_unlock (stack_cache_lock);
|
lll_unlock (stack_cache_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
attribute_hidden
|
||||||
|
__wait_lookup_done (void)
|
||||||
|
{
|
||||||
|
lll_lock (stack_cache_lock);
|
||||||
|
|
||||||
|
struct pthread *self = THREAD_SELF;
|
||||||
|
|
||||||
|
/* Iterate over the list with system-allocated threads first. */
|
||||||
|
list_t *runp;
|
||||||
|
list_for_each (runp, &stack_used)
|
||||||
|
{
|
||||||
|
struct pthread *t = list_entry (runp, struct pthread, list);
|
||||||
|
if (t == self || t->header.gscope_flag == THREAD_GSCOPE_FLAG_UNUSED)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int *const gscope_flagp = &t->header.gscope_flag;
|
||||||
|
|
||||||
|
/* We have to wait until this thread is done with the global
|
||||||
|
scope. First tell the thread that we are waiting and
|
||||||
|
possibly have to be woken. */
|
||||||
|
if (atomic_compare_and_exchange_bool_acq (gscope_flagp,
|
||||||
|
THREAD_GSCOPE_FLAG_WAIT,
|
||||||
|
THREAD_GSCOPE_FLAG_USED))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
do
|
||||||
|
lll_futex_wait (gscope_flagp, THREAD_GSCOPE_FLAG_WAIT);
|
||||||
|
while (*gscope_flagp == THREAD_GSCOPE_FLAG_WAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now the list with threads using user-allocated stacks. */
|
||||||
|
list_for_each (runp, &__stack_user)
|
||||||
|
{
|
||||||
|
struct pthread *t = list_entry (runp, struct pthread, list);
|
||||||
|
if (t == self || t->header.gscope_flag == THREAD_GSCOPE_FLAG_UNUSED)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int *const gscope_flagp = &t->header.gscope_flag;
|
||||||
|
|
||||||
|
/* We have to wait until this thread is done with the global
|
||||||
|
scope. First tell the thread that we are waiting and
|
||||||
|
possibly have to be woken. */
|
||||||
|
if (atomic_compare_and_exchange_bool_acq (gscope_flagp,
|
||||||
|
THREAD_GSCOPE_FLAG_WAIT,
|
||||||
|
THREAD_GSCOPE_FLAG_USED))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
do
|
||||||
|
lll_futex_wait (gscope_flagp, THREAD_GSCOPE_FLAG_WAIT);
|
||||||
|
while (*gscope_flagp == THREAD_GSCOPE_FLAG_WAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
lll_unlock (stack_cache_lock);
|
||||||
|
}
|
||||||
|
26
nptl/init.c
26
nptl/init.c
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||||
|
|
||||||
@ -35,27 +35,6 @@
|
|||||||
#include <lowlevellock.h>
|
#include <lowlevellock.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef __NR_set_tid_address
|
|
||||||
/* XXX For the time being... Once we can rely on the kernel headers
|
|
||||||
having the definition remove these lines. */
|
|
||||||
#if defined __s390__
|
|
||||||
# define __NR_set_tid_address 252
|
|
||||||
#elif defined __ia64__
|
|
||||||
# define __NR_set_tid_address 1233
|
|
||||||
#elif defined __i386__
|
|
||||||
# define __NR_set_tid_address 258
|
|
||||||
#elif defined __x86_64__
|
|
||||||
# define __NR_set_tid_address 218
|
|
||||||
#elif defined __powerpc__
|
|
||||||
# define __NR_set_tid_address 232
|
|
||||||
#elif defined __sparc__
|
|
||||||
# define __NR_set_tid_address 166
|
|
||||||
#else
|
|
||||||
# error "define __NR_set_tid_address"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Size and alignment of static TLS block. */
|
/* Size and alignment of static TLS block. */
|
||||||
size_t __static_tls_size;
|
size_t __static_tls_size;
|
||||||
size_t __static_tls_align_m1;
|
size_t __static_tls_align_m1;
|
||||||
@ -138,7 +117,8 @@ static const struct pthread_functions pthread_functions =
|
|||||||
.ptr__nptl_deallocate_tsd = __nptl_deallocate_tsd,
|
.ptr__nptl_deallocate_tsd = __nptl_deallocate_tsd,
|
||||||
.ptr__nptl_setxid = __nptl_setxid,
|
.ptr__nptl_setxid = __nptl_setxid,
|
||||||
/* For now only the stack cache needs to be freed. */
|
/* For now only the stack cache needs to be freed. */
|
||||||
.ptr_freeres = __free_stack_cache
|
.ptr_freeres = __free_stack_cache,
|
||||||
|
.ptr_wait_lookup_done = __wait_lookup_done
|
||||||
};
|
};
|
||||||
# define ptr_pthread_functions &pthread_functions
|
# define ptr_pthread_functions &pthread_functions
|
||||||
#else
|
#else
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||||
|
|
||||||
@ -545,6 +545,8 @@ extern int __nptl_setxid (struct xid_command *cmdp) attribute_hidden;
|
|||||||
|
|
||||||
extern void __free_stack_cache (void) attribute_hidden;
|
extern void __free_stack_cache (void) attribute_hidden;
|
||||||
|
|
||||||
|
extern void __wait_lookup_done (void) attribute_hidden;
|
||||||
|
|
||||||
#ifdef SHARED
|
#ifdef SHARED
|
||||||
# define PTHREAD_STATIC_FN_REQUIRE(name)
|
# define PTHREAD_STATIC_FN_REQUIRE(name)
|
||||||
#else
|
#else
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Definition for thread-local data handling. nptl/i386 version.
|
/* Definition for thread-local data handling. nptl/i386 version.
|
||||||
Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -27,6 +27,7 @@
|
|||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <list.h>
|
# include <list.h>
|
||||||
|
# include <sysdep.h>
|
||||||
|
|
||||||
|
|
||||||
/* Type for the dtv. */
|
/* Type for the dtv. */
|
||||||
@ -51,6 +52,7 @@ typedef struct
|
|||||||
uintptr_t sysinfo;
|
uintptr_t sysinfo;
|
||||||
uintptr_t stack_guard;
|
uintptr_t stack_guard;
|
||||||
uintptr_t pointer_guard;
|
uintptr_t pointer_guard;
|
||||||
|
int gscope_flag;
|
||||||
} tcbhead_t;
|
} tcbhead_t;
|
||||||
|
|
||||||
# define TLS_MULTIPLE_THREADS_IN_TCB 1
|
# define TLS_MULTIPLE_THREADS_IN_TCB 1
|
||||||
@ -431,6 +433,35 @@ union user_desc_init
|
|||||||
= THREAD_GETMEM (THREAD_SELF, header.pointer_guard))
|
= THREAD_GETMEM (THREAD_SELF, header.pointer_guard))
|
||||||
|
|
||||||
|
|
||||||
|
/* Get and set the global scope generation counter in the TCB head. */
|
||||||
|
#define THREAD_GSCOPE_FLAG_UNUSED 0
|
||||||
|
#define THREAD_GSCOPE_FLAG_USED 1
|
||||||
|
#define THREAD_GSCOPE_FLAG_WAIT 2
|
||||||
|
#define THREAD_GSCOPE_RESET_FLAG() \
|
||||||
|
do \
|
||||||
|
{ int __res; \
|
||||||
|
asm volatile ("xchg %0, %%gs:%P1" \
|
||||||
|
: "=r" (__res) \
|
||||||
|
: "i" (offsetof (struct pthread, header.gscope_flag)), \
|
||||||
|
"0" (THREAD_GSCOPE_FLAG_UNUSED)); \
|
||||||
|
if (__res == THREAD_GSCOPE_FLAG_WAIT) \
|
||||||
|
lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
#define THREAD_GSCOPE_SET_FLAG() \
|
||||||
|
THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED)
|
||||||
|
#ifdef PTR_DEMANGLE
|
||||||
|
# define THREAD_GSCOPE_WAIT() \
|
||||||
|
do { void (*ptr) (void) = GL(dl_wait_lookup_done); \
|
||||||
|
PTR_DEMANGLE (ptr); \
|
||||||
|
ptr (); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
# define THREAD_GSCOPE_WAIT() \
|
||||||
|
GL(dl_wait_lookup_done) ()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* __ASSEMBLER__ */
|
#endif /* __ASSEMBLER__ */
|
||||||
|
|
||||||
#endif /* tls.h */
|
#endif /* tls.h */
|
||||||
|
@ -97,7 +97,7 @@ struct pthread_functions
|
|||||||
void (*ptr__nptl_deallocate_tsd) (void);
|
void (*ptr__nptl_deallocate_tsd) (void);
|
||||||
int (*ptr__nptl_setxid) (struct xid_command *);
|
int (*ptr__nptl_setxid) (struct xid_command *);
|
||||||
void (*ptr_freeres) (void);
|
void (*ptr_freeres) (void);
|
||||||
void (*ptr_wait_lookup_done) (int);
|
void (*ptr_wait_lookup_done) (void);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Variable in libc.so. */
|
/* Variable in libc.so. */
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <pthreadP.h>
|
#include <pthreadP.h>
|
||||||
#include <bits/libc-lock.h>
|
#include <bits/libc-lock.h>
|
||||||
#include <sysdep.h>
|
#include <sysdep.h>
|
||||||
|
#include <ldsodefs.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef TLS_MULTIPLE_THREADS_IN_TCB
|
#ifdef TLS_MULTIPLE_THREADS_IN_TCB
|
||||||
@ -70,6 +71,12 @@ __libc_pthread_init (ptr, reclaim, functions)
|
|||||||
dest->parr[cnt] = p;
|
dest->parr[cnt] = p;
|
||||||
}
|
}
|
||||||
__libc_pthread_functions_init = 1;
|
__libc_pthread_functions_init = 1;
|
||||||
|
|
||||||
|
# ifdef RTLD_NOT_MANGLED
|
||||||
|
GL(dl_wait_lookup_done) = functions->ptr_wait_lookup_done;
|
||||||
|
# else
|
||||||
|
GL(dl_wait_lookup_done) = __libc_pthread_functions.ptr_wait_lookup_done;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TLS_MULTIPLE_THREADS_IN_TCB
|
#ifndef TLS_MULTIPLE_THREADS_IN_TCB
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
# include <stddef.h>
|
# include <stddef.h>
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
|
# include <sysdep.h>
|
||||||
|
|
||||||
|
|
||||||
/* Type for the dtv. */
|
/* Type for the dtv. */
|
||||||
@ -47,6 +48,7 @@ typedef struct
|
|||||||
dtv_t *dtv;
|
dtv_t *dtv;
|
||||||
void *self; /* Pointer to the thread descriptor. */
|
void *self; /* Pointer to the thread descriptor. */
|
||||||
int multiple_threads;
|
int multiple_threads;
|
||||||
|
int gscope_flag;
|
||||||
uintptr_t sysinfo;
|
uintptr_t sysinfo;
|
||||||
uintptr_t stack_guard;
|
uintptr_t stack_guard;
|
||||||
uintptr_t pointer_guard;
|
uintptr_t pointer_guard;
|
||||||
@ -337,6 +339,30 @@ typedef struct
|
|||||||
= THREAD_GETMEM (THREAD_SELF, header.pointer_guard))
|
= THREAD_GETMEM (THREAD_SELF, header.pointer_guard))
|
||||||
|
|
||||||
|
|
||||||
|
/* Get and set the global scope generation counter in the TCB head. */
|
||||||
|
#define THREAD_GSCOPE_FLAG_UNUSED 0
|
||||||
|
#define THREAD_GSCOPE_FLAG_USED 1
|
||||||
|
#define THREAD_GSCOPE_FLAG_WAIT 2
|
||||||
|
#define THREAD_GSCOPE_RESET_FLAG() \
|
||||||
|
do \
|
||||||
|
{ int __res; \
|
||||||
|
asm volatile ("xchgl %0, %%fs:%P1" \
|
||||||
|
: "=r" (__res) \
|
||||||
|
: "i" (offsetof (struct pthread, header.gscope_flag)), \
|
||||||
|
"0" (THREAD_GSCOPE_FLAG_UNUSED)); \
|
||||||
|
if (__res == THREAD_GSCOPE_FLAG_WAIT) \
|
||||||
|
lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
#define THREAD_GSCOPE_SET_FLAG() \
|
||||||
|
THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED)
|
||||||
|
#define THREAD_GSCOPE_WAIT() \
|
||||||
|
do { void (*ptr) (void) = GL(dl_wait_lookup_done); \
|
||||||
|
PTR_DEMANGLE (ptr); \
|
||||||
|
ptr (); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
#endif /* __ASSEMBLER__ */
|
#endif /* __ASSEMBLER__ */
|
||||||
|
|
||||||
#endif /* tls.h */
|
#endif /* tls.h */
|
||||||
|
@ -486,6 +486,8 @@ struct rtld_global
|
|||||||
|
|
||||||
EXTERN void (*_dl_init_static_tls) (struct link_map *);
|
EXTERN void (*_dl_init_static_tls) (struct link_map *);
|
||||||
|
|
||||||
|
EXTERN void (*_dl_wait_lookup_done) (void);
|
||||||
|
|
||||||
#ifdef SHARED
|
#ifdef SHARED
|
||||||
};
|
};
|
||||||
# define __rtld_global_attribute__
|
# define __rtld_global_attribute__
|
||||||
|
Reference in New Issue
Block a user