Changeset 4f205248 in mainline for uspace/lib/c/generic/tls.c


Ignore:
Timestamp:
2018-04-23T18:50:40Z (6 years ago)
Author:
Jiří Zárevúcky <jiri.zarevucky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a2eb85d
Parents:
8d58fca
git-author:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-04-23 17:47:09)
git-committer:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-04-23 18:50:40)
Message:

Honor TLS alignment.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/tls.c

    r8d58fca r4f205248  
    3636 */
    3737
     38#include <assert.h>
    3839#include <stddef.h>
    3940#include <align.h>
     
    4142#include <stdlib.h>
    4243#include <str.h>
     44#include <macros.h>
    4345#include <elf/elf.h>
    4446
     
    4749#endif
    4850
    49 size_t tls_get_size(void)
    50 {
    51 #ifdef CONFIG_RTLD
    52         if (runtime_env != NULL)
    53                 return runtime_env->tls_size;
     51#if !defined(CONFIG_TLS_VARIANT_1) && !defined(CONFIG_TLS_VARIANT_2)
     52#error Unknown TLS variant.
     53#endif
     54
     55/** Get address of static TLS block */
     56void *tls_get(void)
     57{
     58#ifdef CONFIG_RTLD
     59        assert(runtime_env == NULL);
    5460#endif
    5561
    5662        const elf_segment_header_t *tls =
    5763            elf_get_phdr(__executable_start, PT_TLS);
    58         return tls->p_memsz;
    59 }
    60 
    61 /** Get address of static TLS block */
    62 void *tls_get(void)
    63 {
     64
     65        if (tls == NULL)
     66                return NULL;
     67
    6468#ifdef CONFIG_TLS_VARIANT_1
    65         return (uint8_t *)__tcb_get() + sizeof(tcb_t);
     69        return (uint8_t *)__tcb_get() + ALIGN_UP(sizeof(tcb_t), tls->p_align);
    6670#else /* CONFIG_TLS_VARIANT_2 */
    67         return (uint8_t *)__tcb_get() - tls_get_size();
     71        return (uint8_t *)__tcb_get() - ALIGN_UP(tls->p_memsz, tls->p_align);
    6872#endif
    6973}
     
    8993
    9094        uintptr_t bias = elf_get_bias(__executable_start);
    91 
    92         tcb = tls_alloc_arch(&data, tls->p_memsz);
     95        size_t align = max(tls->p_align, _Alignof(tcb_t));
     96
     97#ifdef CONFIG_TLS_VARIANT_1
     98        tcb = tls_alloc_arch(
     99            ALIGN_UP(sizeof(tcb_t), align) + tls->p_memsz, align);
     100        data = (void *) tcb + ALIGN_UP(sizeof(tcb_t), align);
     101#else
     102        tcb = tls_alloc_arch(
     103            ALIGN_UP(tls->p_memsz, align) + sizeof(tcb_t), align);
     104        data = (void *) tcb - ALIGN_UP(tls->p_memsz, tls->p_align);
     105#endif
    93106
    94107        /*
     
    108121#ifdef CONFIG_RTLD
    109122        free(tcb->dtv);
    110 #endif
    111         tls_free_arch(tcb, tls_get_size());
     123
     124        if (runtime_env != NULL) {
     125                tls_free_arch(tcb, runtime_env->tls_size, runtime_env->tls_align);
     126                return;
     127        }
     128#endif
     129        const elf_segment_header_t *tls =
     130            elf_get_phdr(__executable_start, PT_TLS);
     131
     132        assert(tls != NULL);
     133        tls_free_arch(tcb,
     134            ALIGN_UP(tls->p_memsz, tls->p_align) + sizeof(tcb_t),
     135            max(tls->p_align, _Alignof(tcb_t)));
    112136}
    113137
     
    119143 * @return              Pointer to tcb_t structure.
    120144 */
    121 tcb_t *tls_alloc_variant_1(void **data, size_t size)
    122 {
    123         tcb_t *tcb;
    124 
    125         tcb = malloc(sizeof(tcb_t) + size);
     145tcb_t *tls_alloc_variant_1(size_t size, size_t align)
     146{
     147        tcb_t *tcb = memalign(align, size);
    126148        if (!tcb)
    127149                return NULL;
    128 
    129         *data = ((void *) tcb) + sizeof(tcb_t);
    130 #ifdef CONFIG_RTLD
    131         tcb->dtv = NULL;
    132 #endif
    133 
     150        memset(tcb, 0, sizeof(tcb_t));
    134151        return tcb;
    135152}
     
    140157 * @param size          This argument is ignored.
    141158 */
    142 void tls_free_variant_1(tcb_t *tcb, size_t size)
     159void tls_free_variant_1(tcb_t *tcb, size_t size, size_t align)
    143160{
    144161        free(tcb);
     
    152169 *                      actually an output argument.
    153170 * @param size          Size of thread local data.
     171 * @param align         Alignment of thread local data.
    154172 * @return              Pointer to TCB structure.
    155173 */
    156 tcb_t *tls_alloc_variant_2(void **data, size_t size)
    157 {
    158         tcb_t *tcb;
    159 
    160         uintptr_t align = elf_get_phdr(__executable_start, PT_TLS)->p_align;
    161 
    162         size = ALIGN_UP(size, align);
    163         *data = memalign(align, sizeof(tcb_t) + size);
    164         if (*data == NULL)
    165                 return NULL;
    166         tcb = (tcb_t *) (*data + size);
     174tcb_t *tls_alloc_variant_2(size_t size, size_t align)
     175{
     176        void *data = memalign(align, size);
     177        if (data == NULL)
     178                return NULL;
     179
     180        tcb_t *tcb = (tcb_t *) (data + size - sizeof(tcb_t));
     181        memset(tcb, 0, sizeof(tcb_t));
    167182        tcb->self = tcb;
    168 #ifdef CONFIG_RTLD
    169         tcb->dtv = NULL;
    170 #endif
    171 
    172183        return tcb;
    173184}
     
    177188 * @param tcb           Pointer to TCB structure.
    178189 * @param size          Size of thread local data.
    179  */
    180 void tls_free_variant_2(tcb_t *tcb, size_t size)
    181 {
    182         uintptr_t align = elf_get_phdr(__executable_start, PT_TLS)->p_align;
    183         size = ALIGN_UP(size, align);
    184         void *start = ((void *) tcb) - size;
    185         free(start);
     190 * @param align         Alignment of thread local data.
     191 */
     192void tls_free_variant_2(tcb_t *tcb, size_t size, size_t align)
     193{
     194        if (tcb != NULL) {
     195                void *start = ((void *) tcb) + sizeof(tcb_t) - size;
     196                free(start);
     197        }
    186198}
    187199#endif
Note: See TracChangeset for help on using the changeset viewer.