aboutsummaryrefslogtreecommitdiff
path: root/elf/dl-close.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-close.c')
-rw-r--r--elf/dl-close.c73
1 files changed, 56 insertions, 17 deletions
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