mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
* elf/dl-close.c (free_mem): Free _dl_scope_free_list.
2007-06-13 Jakub Jelinek <jakub@redhat.com> * include/link.h: Don't include rtld-lowlevel.h. (struct link_map): Remove l_scope_lock. * sysdeps/generic/ldsodefs.h: Don't include rtld-lowlevel.h. (_dl_scope_free_list): New field (variable) in _rtld_global. (DL_LOOKUP_SCOPE_LOCK): Remove. (_dl_scope_free): New prototype. * elf/dl-runtime.c (_dl_fixup): Don't use __rtld_mrlock_*lock. Don't pass DL_LOOKUP_SCOPE_LOCK to _dl_lookup_symbol_x. (_dl_profile_fixup): Likewise. * elf/dl-sym.c (do_sym): Likewise. Use wrapped _dl_lookup_symbol_x whenever !RTLD_SINGLE_THREAD_P, use THREAD_GSCOPE_SET_FLAG and THREAD_GSCOPE_RESET_FLAG around it. * elf/dl-close.c (_dl_close_worker): Don't use __rtld_mrlock_{change,done}. Call _dl_scope_free on the old scope. Make sure THREAD_GSCOPE_WAIT () happens if any old scopes were queued or if l_scope_mem has been abandoned. * elf/dl-open.c (_dl_scope_free): New function. (dl_open_worker): Use it. Don't use __rtld_mrlock_{change,done}. * elf/dl-support.c (_dl_scope_free_list): New variable. * elf/dl-lookup.c (add_dependency): Remove flags argument. Remove DL_LOOKUP_SCOPE_LOCK handling. (_dl_lookup_symbol_x): Adjust caller. Remove DL_LOOKUP_SCOPE_LOCK handling. * elf/dl-object.c (_dl_new_object): Don't use __rtld_mrlock_initialize. 2007-06-19 Ulrich Drepper <drepper@redhat.com>
This commit is contained in:
32
ChangeLog
32
ChangeLog
@ -1,3 +1,35 @@
|
|||||||
|
2007-06-19 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* elf/dl-close.c (free_mem): Free _dl_scope_free_list.
|
||||||
|
|
||||||
|
2007-06-13 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
* include/link.h: Don't include rtld-lowlevel.h.
|
||||||
|
(struct link_map): Remove l_scope_lock.
|
||||||
|
* sysdeps/generic/ldsodefs.h: Don't include rtld-lowlevel.h.
|
||||||
|
(_dl_scope_free_list): New field (variable) in _rtld_global.
|
||||||
|
(DL_LOOKUP_SCOPE_LOCK): Remove.
|
||||||
|
(_dl_scope_free): New prototype.
|
||||||
|
* elf/dl-runtime.c (_dl_fixup): Don't use __rtld_mrlock_*lock.
|
||||||
|
Don't pass DL_LOOKUP_SCOPE_LOCK to _dl_lookup_symbol_x.
|
||||||
|
(_dl_profile_fixup): Likewise.
|
||||||
|
* elf/dl-sym.c (do_sym): Likewise. Use wrapped _dl_lookup_symbol_x
|
||||||
|
whenever !RTLD_SINGLE_THREAD_P, use THREAD_GSCOPE_SET_FLAG and
|
||||||
|
THREAD_GSCOPE_RESET_FLAG around it.
|
||||||
|
* elf/dl-close.c (_dl_close_worker): Don't use
|
||||||
|
__rtld_mrlock_{change,done}. Call _dl_scope_free on the old
|
||||||
|
scope. Make sure THREAD_GSCOPE_WAIT () happens if any old
|
||||||
|
scopes were queued or if l_scope_mem has been abandoned.
|
||||||
|
* elf/dl-open.c (_dl_scope_free): New function.
|
||||||
|
(dl_open_worker): Use it. Don't use __rtld_mrlock_{change,done}.
|
||||||
|
* elf/dl-support.c (_dl_scope_free_list): New variable.
|
||||||
|
* elf/dl-lookup.c (add_dependency): Remove flags argument.
|
||||||
|
Remove DL_LOOKUP_SCOPE_LOCK handling.
|
||||||
|
(_dl_lookup_symbol_x): Adjust caller. Remove DL_LOOKUP_SCOPE_LOCK
|
||||||
|
handling.
|
||||||
|
* elf/dl-object.c (_dl_new_object): Don't use
|
||||||
|
__rtld_mrlock_initialize.
|
||||||
|
|
||||||
2007-06-19 Ulrich Drepper <drepper@redhat.com>
|
2007-06-19 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
* sysdeps/generic/ldsodefs.h (rtld_global): Reorder some elements
|
* sysdeps/generic/ldsodefs.h (rtld_global): Reorder some elements
|
||||||
|
@ -229,6 +229,7 @@ _dl_close_worker (struct link_map *map)
|
|||||||
bool do_audit = GLRO(dl_naudit) > 0 && !ns->_ns_loaded->l_auditing;
|
bool do_audit = GLRO(dl_naudit) > 0 && !ns->_ns_loaded->l_auditing;
|
||||||
#endif
|
#endif
|
||||||
bool unload_any = false;
|
bool unload_any = false;
|
||||||
|
bool scope_mem_left = false;
|
||||||
unsigned int unload_global = 0;
|
unsigned int unload_global = 0;
|
||||||
unsigned int first_loaded = ~0;
|
unsigned int first_loaded = ~0;
|
||||||
for (unsigned int i = 0; i < nloaded; ++i)
|
for (unsigned int i = 0; i < nloaded; ++i)
|
||||||
@ -405,18 +406,18 @@ _dl_close_worker (struct link_map *map)
|
|||||||
|
|
||||||
struct r_scope_elem **old = imap->l_scope;
|
struct r_scope_elem **old = imap->l_scope;
|
||||||
|
|
||||||
if (RTLD_SINGLE_THREAD_P)
|
|
||||||
imap->l_scope = newp;
|
imap->l_scope = newp;
|
||||||
else
|
|
||||||
{
|
|
||||||
__rtld_mrlock_change (imap->l_scope_lock);
|
|
||||||
imap->l_scope = newp;
|
|
||||||
__rtld_mrlock_done (imap->l_scope_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No user anymore, we can free it now. */
|
/* No user anymore, we can free it now. */
|
||||||
if (old != imap->l_scope_mem)
|
if (old != imap->l_scope_mem)
|
||||||
free (old);
|
{
|
||||||
|
if (_dl_scope_free (old))
|
||||||
|
/* If _dl_scope_free used THREAD_GSCOPE_WAIT (),
|
||||||
|
no need to repeat it. */
|
||||||
|
scope_mem_left = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
scope_mem_left = true;
|
||||||
|
|
||||||
imap->l_scope_max = new_size;
|
imap->l_scope_max = new_size;
|
||||||
}
|
}
|
||||||
@ -485,9 +486,21 @@ _dl_close_worker (struct link_map *map)
|
|||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
ns_msl->r_nlist = j;
|
ns_msl->r_nlist = j;
|
||||||
|
}
|
||||||
|
|
||||||
if (!RTLD_SINGLE_THREAD_P)
|
if (!RTLD_SINGLE_THREAD_P
|
||||||
|
&& (unload_global
|
||||||
|
|| scope_mem_left
|
||||||
|
|| (GL(dl_scope_free_list) != NULL
|
||||||
|
&& GL(dl_scope_free_list)->count)))
|
||||||
|
{
|
||||||
THREAD_GSCOPE_WAIT ();
|
THREAD_GSCOPE_WAIT ();
|
||||||
|
|
||||||
|
/* Now we can free any queued old scopes. */
|
||||||
|
struct dl_scope_free_list *fsl = GL(dl_scope_free_list);
|
||||||
|
if (fsl != NULL)
|
||||||
|
while (fsl->count > 0)
|
||||||
|
free (fsl->list[--fsl->count]);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t tls_free_start;
|
size_t tls_free_start;
|
||||||
@ -786,4 +799,8 @@ libc_freeres_fn (free_mem)
|
|||||||
malloc), and in the static library it's in .bss space. */
|
malloc), and in the static library it's in .bss space. */
|
||||||
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next);
|
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *scope_free_list = GL(dl_scope_free_list);
|
||||||
|
GL(dl_scope_free_list) = NULL;
|
||||||
|
free (scope_free_list);
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ dl_new_hash (const char *s)
|
|||||||
/* Add extra dependency on MAP to UNDEF_MAP. */
|
/* Add extra dependency on MAP to UNDEF_MAP. */
|
||||||
static int
|
static int
|
||||||
internal_function
|
internal_function
|
||||||
add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
|
add_dependency (struct link_map *undef_map, struct link_map *map)
|
||||||
{
|
{
|
||||||
struct link_map **list;
|
struct link_map **list;
|
||||||
struct link_map *runp;
|
struct link_map *runp;
|
||||||
@ -99,17 +99,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags)
|
|||||||
if (undef_map == map)
|
if (undef_map == map)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Make sure nobody can unload the object while we are at it.
|
/* Make sure nobody can unload the object while we are at it. */
|
||||||
If we hold a scope lock drop it now to avoid ABBA locking problems. */
|
|
||||||
if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0 && !RTLD_SINGLE_THREAD_P)
|
|
||||||
{
|
|
||||||
__rtld_mrlock_unlock (undef_map->l_scope_lock);
|
|
||||||
|
|
||||||
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
|
||||||
|
|
||||||
__rtld_mrlock_lock (undef_map->l_scope_lock);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||||
|
|
||||||
/* Avoid references to objects which cannot be unloaded anyway. */
|
/* Avoid references to objects which cannot be unloaded anyway. */
|
||||||
@ -237,10 +227,9 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
|
|||||||
|
|
||||||
bump_num_relocations ();
|
bump_num_relocations ();
|
||||||
|
|
||||||
/* No other flag than DL_LOOKUP_ADD_DEPENDENCY and DL_LOOKUP_SCOPE_LOCK
|
/* No other flag than DL_LOOKUP_ADD_DEPENDENCY is allowed if we look
|
||||||
is allowed if we look up a versioned symbol. */
|
up a versioned symbol. */
|
||||||
assert (version == NULL || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY
|
assert (version == NULL || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY)) == 0);
|
||||||
| DL_LOOKUP_SCOPE_LOCK)) == 0);
|
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
if (__builtin_expect (skip_map != NULL, 0))
|
if (__builtin_expect (skip_map != NULL, 0))
|
||||||
@ -346,13 +335,11 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
|
|||||||
runtime lookups. */
|
runtime lookups. */
|
||||||
&& (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
|
&& (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
|
||||||
/* Add UNDEF_MAP to the dependencies. */
|
/* Add UNDEF_MAP to the dependencies. */
|
||||||
&& add_dependency (undef_map, current_value.m, flags) < 0)
|
&& add_dependency (undef_map, current_value.m) < 0)
|
||||||
/* Something went wrong. Perhaps the object we tried to reference
|
/* Something went wrong. Perhaps the object we tried to reference
|
||||||
was just removed. Try finding another definition. */
|
was just removed. Try finding another definition. */
|
||||||
return _dl_lookup_symbol_x (undef_name, undef_map, ref,
|
return _dl_lookup_symbol_x (undef_name, undef_map, ref, symbol_scope,
|
||||||
(flags & DL_LOOKUP_SCOPE_LOCK) == 0
|
version, type_class, flags, skip_map);
|
||||||
? symbol_scope : undef_map->l_scope, version,
|
|
||||||
type_class, flags, skip_map);
|
|
||||||
|
|
||||||
/* The object is used. */
|
/* The object is used. */
|
||||||
current_value.m->l_used = 1;
|
current_value.m->l_used = 1;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Storage management for the chain of loaded shared objects.
|
/* Storage management for the chain of loaded shared objects.
|
||||||
Copyright (C) 1995-2002, 2004, 2006 Free Software Foundation, Inc.
|
Copyright (C) 1995-2002, 2004, 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
|
||||||
@ -85,11 +85,6 @@ _dl_new_object (char *realname, const char *libname, int type,
|
|||||||
new->l_scope = new->l_scope_mem;
|
new->l_scope = new->l_scope_mem;
|
||||||
new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]);
|
new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]);
|
||||||
|
|
||||||
/* No need to initialize the scope lock if the initializer is zero. */
|
|
||||||
#if _RTLD_MRLOCK_INITIALIZER != 0
|
|
||||||
__rtld_mrlock_initialize (new->l_scope_lock);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Counter for the scopes we have to handle. */
|
/* Counter for the scopes we have to handle. */
|
||||||
idx = 0;
|
idx = 0;
|
||||||
|
|
||||||
|
@ -165,6 +165,40 @@ add_to_global (struct link_map *new)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_dl_scope_free (struct r_scope_elem **old)
|
||||||
|
{
|
||||||
|
struct dl_scope_free_list *fsl;
|
||||||
|
#define DL_SCOPE_FREE_LIST_SIZE (sizeof (fsl->list) / sizeof (fsl->list[0]))
|
||||||
|
|
||||||
|
if (RTLD_SINGLE_THREAD_P)
|
||||||
|
free (old);
|
||||||
|
else if ((fsl = GL(dl_scope_free_list)) == NULL)
|
||||||
|
{
|
||||||
|
GL(dl_scope_free_list) = fsl = malloc (sizeof (*fsl));
|
||||||
|
if (fsl == NULL)
|
||||||
|
{
|
||||||
|
THREAD_GSCOPE_WAIT ();
|
||||||
|
free (old);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fsl->list[0] = old;
|
||||||
|
fsl->count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (fsl->count < DL_SCOPE_FREE_LIST_SIZE)
|
||||||
|
fsl->list[fsl->count++] = old;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
THREAD_GSCOPE_WAIT ();
|
||||||
|
while (fsl->count > 0)
|
||||||
|
free (fsl->list[--fsl->count]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dl_open_worker (void *a)
|
dl_open_worker (void *a)
|
||||||
@ -429,17 +463,10 @@ dl_open_worker (void *a)
|
|||||||
memcpy (newp, imap->l_scope, cnt * sizeof (imap->l_scope[0]));
|
memcpy (newp, imap->l_scope, cnt * sizeof (imap->l_scope[0]));
|
||||||
struct r_scope_elem **old = imap->l_scope;
|
struct r_scope_elem **old = imap->l_scope;
|
||||||
|
|
||||||
if (RTLD_SINGLE_THREAD_P)
|
|
||||||
imap->l_scope = newp;
|
imap->l_scope = newp;
|
||||||
else
|
|
||||||
{
|
|
||||||
__rtld_mrlock_change (imap->l_scope_lock);
|
|
||||||
imap->l_scope = newp;
|
|
||||||
__rtld_mrlock_done (imap->l_scope_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (old != imap->l_scope_mem)
|
if (old != imap->l_scope_mem)
|
||||||
free (old);
|
_dl_scope_free (old);
|
||||||
|
|
||||||
imap->l_scope_max = new_size;
|
imap->l_scope_max = new_size;
|
||||||
}
|
}
|
||||||
|
@ -100,22 +100,11 @@ _dl_fixup (
|
|||||||
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 (!RTLD_SINGLE_THREAD_P)
|
if (!RTLD_SINGLE_THREAD_P)
|
||||||
{
|
|
||||||
THREAD_GSCOPE_SET_FLAG ();
|
THREAD_GSCOPE_SET_FLAG ();
|
||||||
|
|
||||||
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,
|
||||||
version, ELF_RTYPE_CLASS_PLT, flags, NULL);
|
version, ELF_RTYPE_CLASS_PLT, flags, NULL);
|
||||||
|
|
||||||
if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0)
|
|
||||||
__rtld_mrlock_unlock (l->l_scope_lock);
|
|
||||||
|
|
||||||
/* We are done with the global scope. */
|
/* We are done with the global scope. */
|
||||||
if (!RTLD_SINGLE_THREAD_P)
|
if (!RTLD_SINGLE_THREAD_P)
|
||||||
THREAD_GSCOPE_RESET_FLAG ();
|
THREAD_GSCOPE_RESET_FLAG ();
|
||||||
@ -203,23 +192,12 @@ _dl_profile_fixup (
|
|||||||
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 (!RTLD_SINGLE_THREAD_P)
|
if (!RTLD_SINGLE_THREAD_P)
|
||||||
{
|
|
||||||
THREAD_GSCOPE_SET_FLAG ();
|
THREAD_GSCOPE_SET_FLAG ();
|
||||||
|
|
||||||
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,
|
||||||
&defsym, l->l_scope, version,
|
&defsym, l->l_scope, version,
|
||||||
ELF_RTYPE_CLASS_PLT, flags, NULL);
|
ELF_RTYPE_CLASS_PLT, flags, NULL);
|
||||||
|
|
||||||
if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0)
|
|
||||||
__rtld_mrlock_unlock (l->l_scope_lock);
|
|
||||||
|
|
||||||
/* We are done with the global scope. */
|
/* We are done with the global scope. */
|
||||||
if (!RTLD_SINGLE_THREAD_P)
|
if (!RTLD_SINGLE_THREAD_P)
|
||||||
THREAD_GSCOPE_RESET_FLAG ();
|
THREAD_GSCOPE_RESET_FLAG ();
|
||||||
|
@ -135,6 +135,8 @@ int (*_dl_make_stack_executable_hook) (void **) internal_function
|
|||||||
/* Function in libpthread to wait for termination of lookups. */
|
/* Function in libpthread to wait for termination of lookups. */
|
||||||
void (*_dl_wait_lookup_done) (void);
|
void (*_dl_wait_lookup_done) (void);
|
||||||
|
|
||||||
|
struct dl_scope_free_list *_dl_scope_free_list;
|
||||||
|
|
||||||
#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;
|
||||||
|
10
elf/dl-sym.c
10
elf/dl-sym.c
@ -112,29 +112,29 @@ do_sym (void *handle, const char *name, void *who,
|
|||||||
the initial binary. And then the more complex part
|
the initial binary. And then the more complex part
|
||||||
where the object is dynamically loaded and the scope
|
where the object is dynamically loaded and the scope
|
||||||
array can change. */
|
array can change. */
|
||||||
if (match->l_type != lt_loaded || RTLD_SINGLE_THREAD_P)
|
if (RTLD_SINGLE_THREAD_P)
|
||||||
result = GLRO(dl_lookup_symbol_x) (name, match, &ref,
|
result = GLRO(dl_lookup_symbol_x) (name, match, &ref,
|
||||||
match->l_scope, vers, 0,
|
match->l_scope, vers, 0,
|
||||||
flags | DL_LOOKUP_ADD_DEPENDENCY,
|
flags | DL_LOOKUP_ADD_DEPENDENCY,
|
||||||
NULL);
|
NULL);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
__rtld_mrlock_lock (match->l_scope_lock);
|
|
||||||
|
|
||||||
struct call_dl_lookup_args args;
|
struct call_dl_lookup_args args;
|
||||||
args.name = name;
|
args.name = name;
|
||||||
args.map = match;
|
args.map = match;
|
||||||
args.vers = vers;
|
args.vers = vers;
|
||||||
args.flags = flags | DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_SCOPE_LOCK;
|
args.flags = flags | DL_LOOKUP_ADD_DEPENDENCY;
|
||||||
args.refp = &ref;
|
args.refp = &ref;
|
||||||
|
|
||||||
|
THREAD_GSCOPE_SET_FLAG ();
|
||||||
|
|
||||||
const char *objname;
|
const char *objname;
|
||||||
const char *errstring = NULL;
|
const char *errstring = NULL;
|
||||||
bool malloced;
|
bool malloced;
|
||||||
int err = GLRO(dl_catch_error) (&objname, &errstring, &malloced,
|
int err = GLRO(dl_catch_error) (&objname, &errstring, &malloced,
|
||||||
call_dl_lookup, &args);
|
call_dl_lookup, &args);
|
||||||
|
|
||||||
__rtld_mrlock_unlock (match->l_scope_lock);
|
THREAD_GSCOPE_RESET_FLAG ();
|
||||||
|
|
||||||
if (__builtin_expect (errstring != NULL, 0))
|
if (__builtin_expect (errstring != NULL, 0))
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,6 @@ extern unsigned int la_objopen (struct link_map *__map, Lmid_t __lmid,
|
|||||||
#include <dl-lookupcfg.h>
|
#include <dl-lookupcfg.h>
|
||||||
#include <tls.h>
|
#include <tls.h>
|
||||||
#include <bits/libc-lock.h>
|
#include <bits/libc-lock.h>
|
||||||
#include <rtld-lowlevel.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* Some internal data structures of the dynamic linker used in the
|
/* Some internal data structures of the dynamic linker used in the
|
||||||
@ -223,8 +222,6 @@ struct link_map
|
|||||||
/* This is an array defining the lookup scope for this link map.
|
/* This is an array defining the lookup scope for this link map.
|
||||||
There are initially at most three different scope lists. */
|
There are initially at most three different scope lists. */
|
||||||
struct r_scope_elem **l_scope;
|
struct r_scope_elem **l_scope;
|
||||||
/* We need to protect using the SCOPEREC. */
|
|
||||||
__rtld_mrlock_define (, l_scope_lock)
|
|
||||||
|
|
||||||
/* A similar array, this time only with the local scope. This is
|
/* A similar array, this time only with the local scope. This is
|
||||||
used occasionally. */
|
used occasionally. */
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2007-06-19 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* sysdeps/unix/sysv/linux/rtld-lowlevel.h: Remove mrlock
|
||||||
|
implementation.
|
||||||
|
|
||||||
2007-06-18 Ulrich Drepper <drepper@redhat.com>
|
2007-06-18 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
* pthreadP.h: Define PTHREAD_MUTEX_TYPE.
|
* pthreadP.h: Define PTHREAD_MUTEX_TYPE.
|
||||||
|
@ -24,115 +24,6 @@
|
|||||||
#include <lowlevellock.h>
|
#include <lowlevellock.h>
|
||||||
|
|
||||||
|
|
||||||
/* Special multi-reader lock used in ld.so. */
|
|
||||||
#define __RTLD_MRLOCK_WRITER 1
|
|
||||||
#define __RTLD_MRLOCK_RWAIT 2
|
|
||||||
#define __RTLD_MRLOCK_WWAIT 4
|
|
||||||
#define __RTLD_MRLOCK_RBITS \
|
|
||||||
~(__RTLD_MRLOCK_WRITER | __RTLD_MRLOCK_RWAIT | __RTLD_MRLOCK_WWAIT)
|
|
||||||
#define __RTLD_MRLOCK_INC 8
|
|
||||||
#define __RTLD_MRLOCK_TRIES 5
|
|
||||||
|
|
||||||
|
|
||||||
typedef int __rtld_mrlock_t;
|
|
||||||
|
|
||||||
|
|
||||||
#define __rtld_mrlock_define(CLASS,NAME) \
|
|
||||||
CLASS __rtld_mrlock_t NAME;
|
|
||||||
|
|
||||||
|
|
||||||
#define _RTLD_MRLOCK_INITIALIZER 0
|
|
||||||
#define __rtld_mrlock_initialize(NAME) \
|
|
||||||
(void) ((NAME) = 0)
|
|
||||||
|
|
||||||
|
|
||||||
#define __rtld_mrlock_lock(lock) \
|
|
||||||
do { \
|
|
||||||
__label__ out; \
|
|
||||||
while (1) \
|
|
||||||
{ \
|
|
||||||
int oldval; \
|
|
||||||
for (int tries = 0; tries < __RTLD_MRLOCK_TRIES; ++tries) \
|
|
||||||
{ \
|
|
||||||
oldval = lock; \
|
|
||||||
while (__builtin_expect ((oldval \
|
|
||||||
& (__RTLD_MRLOCK_WRITER \
|
|
||||||
| __RTLD_MRLOCK_WWAIT)) \
|
|
||||||
== 0, 1)) \
|
|
||||||
{ \
|
|
||||||
int newval = ((oldval & __RTLD_MRLOCK_RBITS) \
|
|
||||||
+ __RTLD_MRLOCK_INC); \
|
|
||||||
int ret = atomic_compare_and_exchange_val_acq (&(lock), \
|
|
||||||
newval, \
|
|
||||||
oldval); \
|
|
||||||
if (__builtin_expect (ret == oldval, 1)) \
|
|
||||||
goto out; \
|
|
||||||
oldval = ret; \
|
|
||||||
} \
|
|
||||||
atomic_delay (); \
|
|
||||||
} \
|
|
||||||
if ((oldval & __RTLD_MRLOCK_RWAIT) == 0) \
|
|
||||||
{ \
|
|
||||||
atomic_or (&(lock), __RTLD_MRLOCK_RWAIT); \
|
|
||||||
oldval |= __RTLD_MRLOCK_RWAIT; \
|
|
||||||
} \
|
|
||||||
lll_private_futex_wait (lock, oldval); \
|
|
||||||
} \
|
|
||||||
out:; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
#define __rtld_mrlock_unlock(lock) \
|
|
||||||
do { \
|
|
||||||
int oldval = atomic_exchange_and_add (&(lock), -__RTLD_MRLOCK_INC); \
|
|
||||||
if (__builtin_expect ((oldval \
|
|
||||||
& (__RTLD_MRLOCK_RBITS | __RTLD_MRLOCK_WWAIT)) \
|
|
||||||
== (__RTLD_MRLOCK_INC | __RTLD_MRLOCK_WWAIT), 0)) \
|
|
||||||
/* We have to wake all threads since there might be some queued \
|
|
||||||
readers already. */ \
|
|
||||||
lll_private_futex_wake (&(lock), 0x7fffffff); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
/* There can only ever be one thread trying to get the exclusive lock. */
|
|
||||||
#define __rtld_mrlock_change(lock) \
|
|
||||||
do { \
|
|
||||||
__label__ out; \
|
|
||||||
while (1) \
|
|
||||||
{ \
|
|
||||||
int oldval; \
|
|
||||||
for (int tries = 0; tries < __RTLD_MRLOCK_TRIES; ++tries) \
|
|
||||||
{ \
|
|
||||||
oldval = lock; \
|
|
||||||
while (__builtin_expect ((oldval & __RTLD_MRLOCK_RBITS) == 0, 1)) \
|
|
||||||
{ \
|
|
||||||
int newval = ((oldval & __RTLD_MRLOCK_RWAIT) \
|
|
||||||
+ __RTLD_MRLOCK_WRITER); \
|
|
||||||
int ret = atomic_compare_and_exchange_val_acq (&(lock), \
|
|
||||||
newval, \
|
|
||||||
oldval); \
|
|
||||||
if (__builtin_expect (ret == oldval, 1)) \
|
|
||||||
goto out; \
|
|
||||||
oldval = ret; \
|
|
||||||
} \
|
|
||||||
atomic_delay (); \
|
|
||||||
} \
|
|
||||||
atomic_or (&(lock), __RTLD_MRLOCK_WWAIT); \
|
|
||||||
oldval |= __RTLD_MRLOCK_WWAIT; \
|
|
||||||
lll_private_futex_wait (lock, oldval); \
|
|
||||||
} \
|
|
||||||
out:; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
#define __rtld_mrlock_done(lock) \
|
|
||||||
do { \
|
|
||||||
int oldval = atomic_exchange_and_add (&(lock), -__RTLD_MRLOCK_WRITER); \
|
|
||||||
if (__builtin_expect ((oldval & __RTLD_MRLOCK_RWAIT) != 0, 0)) \
|
|
||||||
lll_private_futex_wake (&(lock), 0x7fffffff); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
/* Function to wait for variable become zero. Used in ld.so for
|
/* Function to wait for variable become zero. Used in ld.so for
|
||||||
reference counters. */
|
reference counters. */
|
||||||
#define __rtld_waitzero(word) \
|
#define __rtld_waitzero(word) \
|
||||||
|
@ -38,7 +38,6 @@
|
|||||||
#include <bits/libc-lock.h>
|
#include <bits/libc-lock.h>
|
||||||
#include <hp-timing.h>
|
#include <hp-timing.h>
|
||||||
#include <tls.h>
|
#include <tls.h>
|
||||||
#include <rtld-lowlevel.h>
|
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
@ -488,6 +487,12 @@ struct rtld_global
|
|||||||
|
|
||||||
EXTERN void (*_dl_wait_lookup_done) (void);
|
EXTERN void (*_dl_wait_lookup_done) (void);
|
||||||
|
|
||||||
|
/* Scopes to free after next THREAD_GSCOPE_WAIT (). */
|
||||||
|
EXTERN struct dl_scope_free_list
|
||||||
|
{
|
||||||
|
size_t count;
|
||||||
|
struct r_scope_elem **list[50];
|
||||||
|
} *_dl_scope_free_list;
|
||||||
#ifdef SHARED
|
#ifdef SHARED
|
||||||
};
|
};
|
||||||
# define __rtld_global_attribute__
|
# define __rtld_global_attribute__
|
||||||
@ -840,9 +845,7 @@ enum
|
|||||||
DL_LOOKUP_ADD_DEPENDENCY = 1,
|
DL_LOOKUP_ADD_DEPENDENCY = 1,
|
||||||
/* Return most recent version instead of default version for
|
/* Return most recent version instead of default version for
|
||||||
unversioned lookup. */
|
unversioned lookup. */
|
||||||
DL_LOOKUP_RETURN_NEWEST = 2,
|
DL_LOOKUP_RETURN_NEWEST = 2
|
||||||
/* Set if the scopr lock in the UNDEF_MAP is taken. */
|
|
||||||
DL_LOOKUP_SCOPE_LOCK = 4
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Lookup versioned symbol. */
|
/* Lookup versioned symbol. */
|
||||||
@ -1050,6 +1053,11 @@ extern void *_dl_open (const char *name, int mode, const void *caller,
|
|||||||
Lmid_t nsid, int argc, char *argv[], char *env[])
|
Lmid_t nsid, int argc, char *argv[], char *env[])
|
||||||
attribute_hidden;
|
attribute_hidden;
|
||||||
|
|
||||||
|
/* Free or queue for freeing scope OLD. If other threads might be
|
||||||
|
in the middle of _dl_fixup, _dl_profile_fixup or dl*sym using the
|
||||||
|
old scope, OLD can't be freed until no thread is using it. */
|
||||||
|
extern int _dl_scope_free (struct r_scope_elem **old) attribute_hidden;
|
||||||
|
|
||||||
/* Add module to slot information data. */
|
/* Add module to slot information data. */
|
||||||
extern void _dl_add_to_slotinfo (struct link_map *l) attribute_hidden;
|
extern void _dl_add_to_slotinfo (struct link_map *l) attribute_hidden;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user