Update.
authorUlrich Drepper <drepper@redhat.com>
Thu, 14 Feb 2002 07:57:19 +0000 (07:57 +0000)
committerUlrich Drepper <drepper@redhat.com>
Thu, 14 Feb 2002 07:57:19 +0000 (07:57 +0000)
* elf/dl-close.c (remove_slotinfo): New function.  Handles everything
for removing reference of module in slotinfo list.
(_dl_close): Use remove_slotinfo.
* sysdeps/generic/dl-tls.c: General pretty printing.
(oom): Define only if SHARED.
(_dl_next_tls_modid): Correct starting point for the case we assume
there is a gap.  Add missing instruction grouping (doh!).  Correct
tests for reaching maximum index.
* elf/Makefile: Add rules to build and run tst-tls7.
* elf/tst-tls7.c: New file.
* elf/tst-tlsmod3.c: New file.

* elf/tst-tlsmod1.c: Move #include "tls-macros.h" instead #ifdef
USE_TLS.
* elf/tst-tlsmod2.c: Likewise.

ChangeLog
elf/Makefile
elf/dl-close.c
elf/tst-tls7.c [new file with mode: 0644]
elf/tst-tlsmod1.c
elf/tst-tlsmod2.c
elf/tst-tlsmod3.c [new file with mode: 0644]
sysdeps/generic/dl-tls.c

index cb746f6..42bf191 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2002-02-13  Ulrich Drepper  <drepper@redhat.com>
 
+       * elf/dl-close.c (remove_slotinfo): New function.  Handles everything
+       for removing reference of module in slotinfo list.
+       (_dl_close): Use remove_slotinfo.
+       * sysdeps/generic/dl-tls.c: General pretty printing.
+       (oom): Define only if SHARED.
+       (_dl_next_tls_modid): Correct starting point for the case we assume
+       there is a gap.  Add missing instruction grouping (doh!).  Correct
+       tests for reaching maximum index.
+       * elf/Makefile: Add rules to build and run tst-tls7.
+       * elf/tst-tls7.c: New file.
+       * elf/tst-tlsmod3.c: New file.
+
+       * elf/tst-tlsmod1.c: Move #include "tls-macros.h" instead #ifdef
+       USE_TLS.
+       * elf/tst-tlsmod2.c: Likewise.
+
        * elf/dl-close.c (_dl_close): When closing an object using TLS
        either decrement dl_tls_max_dtv_idx or set dl_tls_dtv_gaps to
        true.  Increment dl_tls_generation only if we closed any TLS-using
index 1a0338a..b22f3af 100644 (file)
@@ -119,7 +119,7 @@ tests = loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
        $(tests-nodlopen-$(have-z-nodlopen)) neededtest neededtest2 \
        neededtest3 neededtest4 unload2 lateglobal initfirst global \
        restest2 next dblload dblunload reldep5 reldep6 tst-tls1 tst-tls2 \
-       tst-tls3 tst-tls4 tst-tls5 tst-tls6
+       tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7
 test-srcs = tst-pathopt
 tests-vis-yes = vismain
 tests-nodelete-yes = nodelete
@@ -137,7 +137,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
                unload2mod unload2dep ltglobmod1 ltglobmod2 pathoptobj \
                dblloadmod1 dblloadmod2 dblloadmod3 reldepmod5 reldepmod6 \
                reldep6mod0 reldep6mod1 reldep6mod2 reldep6mod3 reldep6mod4 \
-               tst-tlsmod1 tst-tlsmod2
+               tst-tlsmod1 tst-tlsmod2 tst-tlsmod3
 modules-vis-yes = vismod1 vismod2 vismod3
 modules-nodelete-yes = nodelmod1 nodelmod2 nodelmod3 nodelmod4
 modules-nodlopen-yes = nodlopenmod nodlopenmod2
@@ -292,6 +292,7 @@ $(objpfx)reldep6mod1.so: $(objpfx)reldep6mod0.so
 $(objpfx)reldep6mod2.so: $(objpfx)reldep6mod1.so
 $(objpfx)reldep6mod3.so: $(objpfx)reldep6mod2.so
 $(objpfx)reldep6mod4.so: $(objpfx)reldep6mod1.so
+$(objpfx)tst-tlsmod3.so: $(objpfx)tst-tlsmod2.so
 
 # filtmod1.so has a special rule
 $(filter-out $(objpfx)filtmod1.so, $(test-modules)): $(objpfx)%.so: $(objpfx)%.os
@@ -451,3 +452,6 @@ $(objpfx)tst-tls5.out: $(objpfx)tst-tlsmod2.so
 
 $(objpfx)tst-tls6: $(libdl)
 $(objpfx)tst-tls6.out: $(objpfx)tst-tlsmod2.so
+
+$(objpfx)tst-tls7: $(libdl)
+$(objpfx)tst-tls7.out: $(objpfx)tst-tlsmod3.so
index 7e7547d..a594126 100644 (file)
 typedef void (*fini_t) (void);
 
 
+#ifdef USE_TLS
+/* Returns true we an non-empty was found.  */
+static bool
+remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp)
+{
+  if (idx - disp >= listp->len)
+    {
+      /* There must be a next entry.  Otherwise would the index be wrong.  */
+      assert (listp->next != NULL);
+
+      if (remove_slotinfo (idx, listp->next, disp + listp->len))
+       return true;
+
+      /* No non-empty entry.  Search from the end of this elements
+        slotinfo array.  */
+      idx = disp + listp->len;
+    }
+  else
+    {
+      struct link_map *old_map = listp->slotinfo[idx - disp].map;
+      assert (old_map != NULL);
+
+      /* Mark the entry as unused.  */
+      listp->slotinfo[idx - disp].gen = GL(dl_tls_generation) + 1;
+      listp->slotinfo[idx - disp].map = NULL;
+
+      /* If this is not the last currently used entry no need to look
+        further.  */
+      if (old_map->l_tls_modid != GL(dl_tls_max_dtv_idx))
+       return true;
+
+      assert (old_map->l_tls_modid == GL(dl_tls_max_dtv_idx));
+    }
+
+  while (idx - disp > disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0)
+    {
+      --idx;
+
+      if (listp->slotinfo[idx - disp].map != NULL)
+       {
+         /* Found a new last used index.  */
+         GL(dl_tls_max_dtv_idx) = idx;
+         return true;
+       }
+    }
+
+  /* No non-entry in this list element.  */
+  return false;
+}
+#endif
+
+
 void
 internal_function
 _dl_close (void *_map)
@@ -214,25 +266,12 @@ _dl_close (void *_map)
             TLS.  */
          if (__builtin_expect (imap->l_tls_blocksize > 0, 0))
            {
-             /* Locate the entry in the slotinfo array.  */
-             size_t idx = imap->l_tls_modid;
-             struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
-
-             while (idx >= listp->len)
-               {
-                 idx -= listp->len;
-                 listp = listp->next;
-               }
-
-             listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
-             listp->slotinfo[idx].map = NULL;
-
              any_tls = true;
 
-             if (imap->l_tls_modid == GL(dl_tls_max_dtv_idx))
-               --GL(dl_tls_max_dtv_idx);
-             else
-               GL(dl_tls_dtv_gaps) = true;
+             if (! remove_slotinfo (imap->l_tls_modid,
+                                    GL(dl_tls_dtv_slotinfo_list), 0))
+               /* All dynamically loaded modules with TLS are unloaded.  */
+               GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem);
            }
 #endif
 
diff --git a/elf/tst-tls7.c b/elf/tst-tls7.c
new file mode 100644 (file)
index 0000000..4f785fe
--- /dev/null
@@ -0,0 +1,61 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <link.h>
+#include <tls.h>
+
+
+#define TEST_FUNCTION do_test ()
+static int
+do_test (void)
+{
+#ifdef USE_TLS
+  static const char modname[] = "tst-tlsmod3.so";
+  int result = 0;
+  int (*fp) (void);
+  void *h;
+  int i;
+  int modid = -1;
+
+  for (i = 0; i < 10; ++i)
+    {
+      h = dlopen (modname, RTLD_LAZY);
+      if (h == NULL)
+       {
+         printf ("cannot open '%s': %s\n", modname, dlerror ());
+         exit (1);
+       }
+
+      /* Dirty test code here: we peek into a private data structure.
+        We make sure that the module gets assigned the same ID every
+        time.  The value of the first round is used.  */
+      if (modid == -1)
+       modid = ((struct link_map *) h)->l_tls_modid;
+      else if (((struct link_map *) h)->l_tls_modid != modid)
+       {
+         printf ("round %d: modid now %d, initially %d\n",
+                 i, ((struct link_map *) h)->l_tls_modid, modid);
+         result = 1;
+       }
+
+      fp = dlsym (h, "in_dso2");
+      if (fp == NULL)
+       {
+         printf ("cannot get symbol 'in_dso2': %s\n", dlerror ());
+         exit (1);
+       }
+
+      result |= fp ();
+
+      dlclose (h);
+    }
+
+  return result;
+#else
+  return 0;
+#endif
+}
+
+
+#include "../test-skeleton.c"
index cca8df6..7e768a6 100644 (file)
@@ -1,10 +1,11 @@
 #include <stdio.h>
 
 #include <tls.h>
+
+#ifdef USE_TLS
 #include "tls-macros.h"
 
 
-#ifdef USE_TLS
 /* One define int variable, two externs.  */
 COMMON_INT_DEF(foo);
 VAR_INT_DEF(bar);
index 30ed671..6aec812 100644 (file)
@@ -1,9 +1,10 @@
 #include <stdio.h>
 
 #include <tls.h>
-#include "tls-macros.h"
 
 #ifdef USE_TLS
+#include "tls-macros.h"
+
 
 COMMON_INT_DEF(foo);
 
diff --git a/elf/tst-tlsmod3.c b/elf/tst-tlsmod3.c
new file mode 100644 (file)
index 0000000..ff4a446
--- /dev/null
@@ -0,0 +1,34 @@
+#include <stdio.h>
+
+#include <tls.h>
+#include "tls-macros.h"
+
+#ifdef USE_TLS
+extern int in_dso (int n, int *caller_foop);
+
+COMMON_INT_DEF(comm_n);
+
+
+
+
+int
+in_dso2 (void)
+{
+  int *foop = TLS_GD (foo);
+  int result = 0;
+  static int n;
+  int *np = TLS_GD (comm_n);
+
+  if (n != *np)
+    {
+      printf ("n = %d != comm_n = %d\n", n, *np);
+      result = 1;
+    }
+
+  result |= in_dso (*foop = 42 + n++, foop);
+
+  *foop = 16;
+
+  return result;
+}
+#endif
index d13b0f9..7e45850 100644 (file)
 /* We don't need any of this if TLS is not supported.  */
 #ifdef USE_TLS
 
-#include <dl-tls.h>
-#include <ldsodefs.h>
+# include <dl-tls.h>
+# include <ldsodefs.h>
 
 /* Value used for dtv entries for which the allocation is delayed.  */
 # define TLS_DTV_UNALLOCATED   ((void *) -1l)
 
 
 /* Out-of-memory handler.  */
+# ifdef SHARED
 static void
 __attribute__ ((__noreturn__))
 oom (void)
@@ -52,11 +53,12 @@ cannot allocate memory for thread-local data: ABORT\n";
   /* Just in case something goes wrong with the kill.  */
   while (1)
     {
-# ifdef ABORT_INSTRUCTION
+#  ifdef ABORT_INSTRUCTION
       ABORT_INSTRUCTION;
-# endif
+#  endif
     }
 }
+# endif
 
 
 
@@ -75,16 +77,20 @@ _dl_next_tls_modid (void)
         start since there are no gaps at that time.  Therefore it
         does not matter that the dl_tls_dtv_slotinfo is not allocated
         yet when the function is called for the first times.  */
-      result = GL(dl_tls_static_nelem);
-      assert (result < GL(dl_tls_max_dtv_idx));
+      result = GL(dl_tls_static_nelem) + 1;
+      /* If the following would not be true we mustn't have assumed
+        there is a gap.  */
+      assert (result <= GL(dl_tls_max_dtv_idx));
       do
        {
          while (result - disp < runp->len)
-           if (runp->slotinfo[result - disp].map == NULL)
-             break;
+           {
+             if (runp->slotinfo[result - disp].map == NULL)
+               break;
 
-         ++result;
-         assert (result <= GL(dl_tls_max_dtv_idx) + 1);
+             ++result;
+             assert (result <= GL(dl_tls_max_dtv_idx) + 1);
+           }
 
          if (result - disp < runp->len)
            break;
@@ -93,11 +99,11 @@ _dl_next_tls_modid (void)
        }
       while ((runp = runp->next) != NULL);
 
-      if (result >= GL(dl_tls_max_dtv_idx) + 1)
+      if (result >= GL(dl_tls_max_dtv_idx))
        {
          /* The new index must indeed be exactly one higher than the
             previous high.  */
-         assert (result == GL(dl_tls_max_dtv_idx) + 1);
+         assert (result == GL(dl_tls_max_dtv_idx));
 
          /* There is no gap anymore.  */
          GL(dl_tls_dtv_gaps) = false;