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:
@ -996,3 +996,60 @@ __pthread_init_static_tls (struct link_map *map)
|
||||
|
||||
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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user