1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-28 00:21:52 +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:
Ulrich Drepper
2007-05-19 07:08:23 +00:00
parent 2acd01acb1
commit df94b6412e
14 changed files with 204 additions and 37 deletions

View File

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

View File

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

View File

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

View File

@ -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,10 +99,15 @@ _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)
{ {
__rtld_mrlock_lock (l->l_scope_lock); THREAD_GSCOPE_SET_FLAG ();
flags |= DL_LOOKUP_SCOPE_LOCK;
if (l->l_type == lt_loaded)
{
__rtld_mrlock_lock (l->l_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,
@ -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,10 +202,15 @@ _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)
{ {
__rtld_mrlock_lock (l->l_scope_lock); THREAD_GSCOPE_SET_FLAG ();
flags |= DL_LOOKUP_SCOPE_LOCK;
if (l->l_type == lt_loaded)
{
__rtld_mrlock_lock (l->l_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,
@ -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. */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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