aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sysdeps/generic/dl-tls.c126
1 files changed, 70 insertions, 56 deletions
diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c
index 8877023571..e4c36fb0ab 100644
--- a/sysdeps/generic/dl-tls.c
+++ b/sysdeps/generic/dl-tls.c
@@ -198,7 +198,7 @@ _dl_determine_tlsoffset (void)
void *
internal_function
-_dl_allocate_tls (void)
+_dl_allocate_tls_storage (void)
{
void *result;
dtv_t *dtv;
@@ -225,10 +225,6 @@ _dl_allocate_tls (void)
dtv = (dtv_t *) malloc ((dtv_length + 2) * sizeof (dtv_t));
if (result != MAP_FAILED && dtv != NULL)
{
- struct dtv_slotinfo_list *listp;
- bool first_block = true;
- size_t total = 0;
-
# if TLS_TCB_AT_TP
/* The TCB follows the TLS blocks. */
result = (char *) result + GL(dl_tls_static_size) - TLS_TCB_SIZE;
@@ -242,75 +238,93 @@ _dl_allocate_tls (void)
nothing there. */
memset (dtv + 2, '\0', dtv_length * sizeof (dtv_t));
- /* We have to look prepare the dtv for all currently loaded
- modules using TLS. For those which are dynamically loaded we
- add the values indicating deferred allocation. */
- listp = GL(dl_tls_dtv_slotinfo_list);
- while (1)
- {
- size_t cnt;
+ /* Add the dtv to the thread data structures. */
+ INSTALL_DTV (result, dtv);
+ }
+ else if (result != NULL)
+ {
+ free (result);
+ result = NULL;
+ }
- for (cnt = first_block ? 1 : 0; cnt < listp->len; ++cnt)
- {
- struct link_map *map;
- void *dest;
+ return result;
+}
+INTDEF(_dl_allocate_tls)
- /* Check for the total number of used slots. */
- if (total + cnt >= GL(dl_tls_max_dtv_idx))
- break;
+void *
+internal_function
+_dl_allocate_tls_init (void *result)
+{
+ dtv_t *dtv = GET_DTV (result);
+ struct dtv_slotinfo_list *listp;
+ bool first_block = true;
+ size_t total = 0;
+
+ /* We have to look prepare the dtv for all currently loaded
+ modules using TLS. For those which are dynamically loaded we
+ add the values indicating deferred allocation. */
+ listp = GL(dl_tls_dtv_slotinfo_list);
+ while (1)
+ {
+ size_t cnt;
- map = listp->slotinfo[cnt].map;
- if (map == NULL)
- /* Unused entry. */
- continue;
+ for (cnt = first_block ? 1 : 0; cnt < listp->len; ++cnt)
+ {
+ struct link_map *map;
+ void *dest;
- if (map->l_type == lt_loaded)
- {
- /* For dynamically loaded modules we simply store
- the value indicating deferred allocation. */
- dtv[1 + map->l_tls_modid].pointer = TLS_DTV_UNALLOCATED;
- continue;
- }
+ /* Check for the total number of used slots. */
+ if (total + cnt > GL(dl_tls_max_dtv_idx))
+ break;
+
+ map = listp->slotinfo[cnt].map;
+ if (map == NULL)
+ /* Unused entry. */
+ continue;
+
+ if (map->l_type == lt_loaded)
+ {
+ /* For dynamically loaded modules we simply store
+ the value indicating deferred allocation. */
+ dtv[map->l_tls_modid].pointer = TLS_DTV_UNALLOCATED;
+ continue;
+ }
- assert (map->l_tls_modid == cnt);
- assert (map->l_tls_blocksize >= map->l_tls_initimage_size);
+ assert (map->l_tls_modid == cnt);
+ assert (map->l_tls_blocksize >= map->l_tls_initimage_size);
# if TLS_TCB_AT_TP
- assert (map->l_tls_offset >= map->l_tls_blocksize);
- dest = (char *) result - map->l_tls_offset;
+ assert (map->l_tls_offset >= map->l_tls_blocksize);
+ dest = (char *) result - map->l_tls_offset;
# elif TLS_DTV_AT_TP
- dest = (char *) result + map->l_tls_offset;
+ dest = (char *) result + map->l_tls_offset;
# else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif
- /* We don't have to clear the BSS part of the TLS block
- since mmap is used to allocate the memory which
- guarantees it is initialized to zero. */
- dtv[1 + cnt].pointer = memcpy (dest, map->l_tls_initimage,
- map->l_tls_initimage_size);
- }
-
- total += cnt;
- if (total >= GL(dl_tls_max_dtv_idx))
- break;
-
- listp = listp->next;
- assert (listp != NULL);
+ /* We don't have to clear the BSS part of the TLS block
+ since mmap is used to allocate the memory which
+ guarantees it is initialized to zero. */
+ dtv[cnt].pointer = memcpy (dest, map->l_tls_initimage,
+ map->l_tls_initimage_size);
}
- /* Add the dtv to the thread data structures. */
- INSTALL_DTV (result, dtv);
- }
- else if (result != NULL)
- {
- free (result);
- result = NULL;
+ total += cnt;
+ if (total > GL(dl_tls_max_dtv_idx))
+ break;
+
+ listp = listp->next;
+ assert (listp != NULL);
}
return result;
}
-INTDEF(_dl_allocate_tls)
+void *
+internal_function
+_dl_allocate_tls (void)
+{
+ return _dl_allocate_tls_init (_dl_allocate_tls_storage ());
+}
void
internal_function