* elf/dl-close.c (_dl_close_worker): Remove all to be removed

libraries from the global scope at once and call THREAD_GSCOPE_WAIT
	at most once per _dl_close_worker.
This commit is contained in:
Ulrich Drepper 2007-06-09 02:13:06 +00:00
parent 755db8c5bd
commit e8b6b64d3c
2 changed files with 38 additions and 19 deletions

View File

@ -1,3 +1,9 @@
2007-06-08 Jakub Jelinek <jakub@redhat.com>
* elf/dl-close.c (_dl_close_worker): Remove all to be removed
libraries from the global scope at once and call THREAD_GSCOPE_WAIT
at most once per _dl_close_worker.
2007-06-08 Ulrich Drepper <drepper@redhat.com> 2007-06-08 Ulrich Drepper <drepper@redhat.com>
* sysdeps/unix/sysv/linux/bits/sched.h: Make second parameter of * sysdeps/unix/sysv/linux/bits/sched.h: Make second parameter of

View File

@ -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;
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)
{ {
@ -293,6 +294,9 @@ _dl_close_worker (struct link_map *map)
/* We indeed have an object to remove. */ /* We indeed have an object to remove. */
unload_any = true; unload_any = true;
if (imap->l_global)
++unload_global;
/* Remember where the first dynamically loaded object is. */ /* Remember where the first dynamically loaded object is. */
if (i < first_loaded) if (i < first_loaded)
first_loaded = i; first_loaded = i;
@ -458,6 +462,34 @@ _dl_close_worker (struct link_map *map)
r->r_state = RT_DELETE; r->r_state = RT_DELETE;
_dl_debug_state (); _dl_debug_state ();
if (unload_global)
{
/* Some objects are in the global scope list. Remove them. */
struct r_scope_elem *ns_msl = ns->_ns_main_searchlist;
unsigned int i;
unsigned int j = 0;
unsigned int cnt = ns_msl->r_nlist;
while (cnt > 0 && ns_msl->r_list[cnt - 1]->l_removed)
--cnt;
if (cnt + unload_global == ns_msl->r_nlist)
/* Speed up removing most recently added objects. */
j = cnt;
else
for (i = 0; i < cnt; i++)
if (ns_msl->r_list[i]->l_removed == 0)
{
if (i != j)
ns_msl->r_list[j] = ns_msl->r_list[i];
j++;
}
ns_msl->r_nlist = j;
if (!RTLD_SINGLE_THREAD_P)
THREAD_GSCOPE_WAIT ();
}
size_t tls_free_start; size_t tls_free_start;
size_t tls_free_end; size_t tls_free_end;
tls_free_start = tls_free_end = NO_TLS_OFFSET; tls_free_start = tls_free_end = NO_TLS_OFFSET;
@ -473,25 +505,6 @@ _dl_close_worker (struct link_map *map)
/* That was the last reference, and this was a dlopen-loaded /* That was the last reference, and this was a dlopen-loaded
object. We can unmap it. */ object. We can unmap it. */
if (__builtin_expect (imap->l_global, 0))
{
/* This object is in the global scope list. Remove it. */
struct r_scope_elem *ns_msl = ns->_ns_main_searchlist;
unsigned int cnt = ns_msl->r_nlist;
do
--cnt;
while (ns_msl->r_list[cnt] != imap);
/* The object was already correctly registered. */
while (++cnt < ns_msl->r_nlist)
ns_msl->r_list[cnt - 1] = ns_msl->r_list[cnt];
--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. */
if (__builtin_expect (imap->l_tls_blocksize > 0, 0)) if (__builtin_expect (imap->l_tls_blocksize > 0, 0))