aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2002-02-14 07:57:19 +0000
committerUlrich Drepper <drepper@redhat.com>2002-02-14 07:57:19 +0000
commitfc093be16082b406ee160762d773a791a5b3b965 (patch)
tree6649027f3fc3c8e9ca1950ded8278175a2ff5fe7 /elf
parentbb4cb25213ce21326236d72e8633844e4a777a8b (diff)
downloadglibc-fc093be16082b406ee160762d773a791a5b3b965.tar
glibc-fc093be16082b406ee160762d773a791a5b3b965.tar.gz
glibc-fc093be16082b406ee160762d773a791a5b3b965.tar.bz2
glibc-fc093be16082b406ee160762d773a791a5b3b965.zip
Update.
* 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.
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile8
-rw-r--r--elf/dl-close.c73
-rw-r--r--elf/tst-tls7.c61
-rw-r--r--elf/tst-tlsmod1.c3
-rw-r--r--elf/tst-tlsmod2.c3
-rw-r--r--elf/tst-tlsmod3.c34
6 files changed, 161 insertions, 21 deletions
diff --git a/elf/Makefile b/elf/Makefile
index 1a0338a600..b22f3afae3 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -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
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 7e7547de99..a5941268b9 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -32,6 +32,58 @@
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
index 0000000000..4f785fe78e
--- /dev/null
+++ b/elf/tst-tls7.c
@@ -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"
diff --git a/elf/tst-tlsmod1.c b/elf/tst-tlsmod1.c
index cca8df6549..7e768a6593 100644
--- a/elf/tst-tlsmod1.c
+++ b/elf/tst-tlsmod1.c
@@ -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);
diff --git a/elf/tst-tlsmod2.c b/elf/tst-tlsmod2.c
index 30ed67163d..6aec8120c0 100644
--- a/elf/tst-tlsmod2.c
+++ b/elf/tst-tlsmod2.c
@@ -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
index 0000000000..ff4a4460b9
--- /dev/null
+++ b/elf/tst-tlsmod3.c
@@ -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