aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2007-06-09 02:13:06 +0000
committerUlrich Drepper <drepper@redhat.com>2007-06-09 02:13:06 +0000
commite8b6b64d3c24ce1667af7b60c447d21b1968af01 (patch)
tree7ebd4df1133f27c1b1f26984eb1ed8a546cfc8a2
parent755db8c5bd8d85c946efdaafac71591393f59c60 (diff)
downloadglibc-e8b6b64d3c24ce1667af7b60c447d21b1968af01.tar
glibc-e8b6b64d3c24ce1667af7b60c447d21b1968af01.tar.gz
glibc-e8b6b64d3c24ce1667af7b60c447d21b1968af01.tar.bz2
glibc-e8b6b64d3c24ce1667af7b60c447d21b1968af01.zip
* 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.
-rw-r--r--ChangeLog6
-rw-r--r--elf/dl-close.c51
2 files changed, 38 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index fc5436bda9..4abead59af 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
* sysdeps/unix/sysv/linux/bits/sched.h: Make second parameter of
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 8e5c9fc033..2c2b3b6163 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -229,6 +229,7 @@ _dl_close_worker (struct link_map *map)
bool do_audit = GLRO(dl_naudit) > 0 && !ns->_ns_loaded->l_auditing;
#endif
bool unload_any = false;
+ unsigned int unload_global = 0;
unsigned int first_loaded = ~0;
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. */
unload_any = true;
+ if (imap->l_global)
+ ++unload_global;
+
/* Remember where the first dynamically loaded object is. */
if (i < first_loaded)
first_loaded = i;
@@ -458,6 +462,34 @@ _dl_close_worker (struct link_map *map)
r->r_state = RT_DELETE;
_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_end;
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
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. */
if (__builtin_expect (imap->l_tls_blocksize > 0, 0))