diff options
author | Roland McGrath <roland@gnu.org> | 2002-08-05 01:20:52 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2002-08-05 01:20:52 +0000 |
commit | 581dc54b74e8131acbb06f7ebb8887815f1914c8 (patch) | |
tree | 9ae79006a5e1f1ae1714d928ebbae4545b3d45ac | |
parent | 855efb5f6ff9bef07b6faee4294e65517c5f7866 (diff) | |
download | glibc-581dc54b74e8131acbb06f7ebb8887815f1914c8.tar glibc-581dc54b74e8131acbb06f7ebb8887815f1914c8.tar.gz glibc-581dc54b74e8131acbb06f7ebb8887815f1914c8.tar.bz2 glibc-581dc54b74e8131acbb06f7ebb8887815f1914c8.zip |
2002-08-04 Roland McGrath <roland@redhat.com>
* sysdeps/generic/dl-tls.c (_dl_allocate_tls_storage): New function,
split out of _dl_allocate_tls.
(_dl_allocate_tls_init): Likewise.
(_dl_allocate_tls): Call those.
* sysdeps/generic/ldsodefs.h: Declare them with attribute_hidden.
* elf/rtld.c (dl_main): Call them separately instead of calling
_dl_allocate_tls. Delay _dl_allocate_tls_init until after relocation
is finished, so that the initializer data has been relocated before we
copy it into the main thread's TLS block.
* sysdeps/generic/dl-tls.c (_dl_allocate_tls): Fix off-by-one error in
loop conditions, prevented the last used module from being initialized.
-rw-r--r-- | sysdeps/generic/dl-tls.c | 126 |
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 |