* elf/dl-close.c (_dl_close_worker): Remove all to be removed
authorUlrich Drepper <drepper@redhat.com>
Sat, 9 Jun 2007 02:13:06 +0000 (02:13 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sat, 9 Jun 2007 02:13:06 +0000 (02:13 +0000)
libraries from the global scope at once and call THREAD_GSCOPE_WAIT
at most once per _dl_close_worker.

ChangeLog
elf/dl-close.c

index fc5436b..4abead5 100644 (file)
--- 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
index 8e5c9fc..2c2b3b6 100644 (file)
@@ -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))