summaryrefslogtreecommitdiff
path: root/elf/dl-close.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-close.c')
-rw-r--r--elf/dl-close.c51
1 files changed, 48 insertions, 3 deletions
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 78b143f8ec..b482e89f13 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -321,8 +321,9 @@ _dl_close (void *_map)
_dl_debug_state ();
#ifdef USE_TLS
- size_t tls_free_start, tls_free_end;
- tls_free_start = tls_free_end = GL(dl_tls_static_used);
+ size_t tls_free_start;
+ size_t tls_free_end;
+ tls_free_start = tls_free_end = NO_TLS_OFFSET;
#endif
/* Check each element of the search list to see if all references to
@@ -371,9 +372,50 @@ _dl_close (void *_map)
this search list, going in either direction. When the
whole chunk is at the end of the used area then we can
reclaim it. */
+# if TLS_TCB_AT_TP
+ if (tls_free_start == NO_TLS_OFFSET
+ || (size_t) imap->l_tls_offset == tls_free_start)
+ {
+ /* Extend the contiguous chunk being reclaimed. */
+ tls_free_start
+ = imap->l_tls_offset - imap->l_tls_blocksize;
+
+ if (tls_free_end == NO_TLS_OFFSET)
+ tls_free_end = imap->l_tls_offset;
+ }
+ else if (imap->l_tls_offset - imap->l_tls_blocksize
+ == tls_free_end)
+ /* Extend the chunk backwards. */
+ tls_free_end = imap->l_tls_offset;
+ else
+ {
+ /* This isn't contiguous with the last chunk freed.
+ One of them will be leaked unless we can free
+ one block right away. */
+ if (tls_free_end == GL(dl_tls_static_used))
+ {
+ GL(dl_tls_static_used) = tls_free_start;
+ tls_free_end = imap->l_tls_offset;
+ tls_free_start
+ = tls_free_end - imap->l_tls_blocksize;
+ }
+ else if ((size_t) imap->l_tls_offset
+ == GL(dl_tls_static_used))
+ GL(dl_tls_static_used)
+ = imap->l_tls_offset - imap->l_tls_blocksize;
+ else if (tls_free_end < (size_t) imap->l_tls_offset)
+ {
+ /* We pick the later block. It has a chance to
+ be freed. */
+ tls_free_end = imap->l_tls_offset;
+ tls_free_start
+ = tls_free_end - imap->l_tls_blocksize;
+ }
+ }
+# elif TLS_DTV_AT_TP
if ((size_t) imap->l_tls_offset == tls_free_end)
/* Extend the contiguous chunk being reclaimed. */
- tls_free_end += imap->l_tls_blocksize;
+ tls_free_end -= imap->l_tls_blocksize;
else if (imap->l_tls_offset + imap->l_tls_blocksize
== tls_free_start)
/* Extend the chunk backwards. */
@@ -387,6 +429,9 @@ _dl_close (void *_map)
tls_free_start = imap->l_tls_offset;
tls_free_end = tls_free_start + imap->l_tls_blocksize;
}
+# else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
}
}
#endif