Changeset 40abf56 in mainline for uspace/lib/c/generic/tls.c
- Timestamp:
- 2018-07-18T19:42:28Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9bde0d5
- Parents:
- 0b05082
- git-author:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-07-18 19:05:08)
- git-committer:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-07-18 19:42:28)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/tls.c
r0b05082 r40abf56 44 44 #include <macros.h> 45 45 #include <elf/elf.h> 46 #include <as.h> 47 48 #include <libarch/config.h> 49 50 #ifdef CONFIG_RTLD 51 #include <rtld/rtld.h> 52 #endif 46 53 47 54 #include "private/libc.h" 48 49 #ifdef CONFIG_RTLD50 #include <rtld/rtld.h>51 #endif52 55 53 56 #if !defined(CONFIG_TLS_VARIANT_1) && !defined(CONFIG_TLS_VARIANT_2) … … 55 58 #endif 56 59 60 static ptrdiff_t _tcb_data_offset(void) 61 { 62 const elf_segment_header_t *tls = 63 elf_get_phdr(__progsymbols.elfstart, PT_TLS); 64 65 size_t tls_align = tls ? tls->p_align : 1; 66 67 #ifdef CONFIG_TLS_VARIANT_1 68 return ALIGN_UP((ptrdiff_t) sizeof(tcb_t), tls_align); 69 #else 70 size_t tls_size = tls ? tls->p_memsz : 0; 71 return -ALIGN_UP((ptrdiff_t) tls_size, max(tls_align, _Alignof(tcb_t))); 72 #endif 73 } 74 57 75 /** Get address of static TLS block */ 58 76 void *tls_get(void) … … 61 79 assert(runtime_env == NULL); 62 80 #endif 63 64 const elf_segment_header_t *tls = 65 elf_get_phdr(__progsymbols.elfstart, PT_TLS); 66 67 if (tls == NULL) 68 return NULL; 69 70 #ifdef CONFIG_TLS_VARIANT_1 71 return (uint8_t *)__tcb_get() + ALIGN_UP(sizeof(tcb_t), tls->p_align); 72 #else /* CONFIG_TLS_VARIANT_2 */ 73 return (uint8_t *)__tcb_get() - ALIGN_UP(tls->p_memsz, tls->p_align); 74 #endif 81 return (uint8_t *)__tcb_get() + _tcb_data_offset(); 82 } 83 84 static tcb_t *tls_make_generic(const void *elf, void *(*alloc)(size_t, size_t)) 85 { 86 assert(!elf_get_phdr(elf, PT_DYNAMIC)); 87 #ifdef CONFIG_RTLD 88 assert(runtime_env == NULL); 89 #endif 90 91 const elf_segment_header_t *tls = elf_get_phdr(elf, PT_TLS); 92 size_t tls_size = tls ? tls->p_memsz : 0; 93 size_t tls_align = tls ? tls->p_align : 1; 94 95 /* 96 * We don't currently support alignment this big, 97 * and neither should we need to. 98 */ 99 assert(tls_align <= PAGE_SIZE); 100 101 #ifdef CONFIG_TLS_VARIANT_1 102 size_t alloc_size = 103 ALIGN_UP(sizeof(tcb_t), tls_align) + tls_size; 104 #else 105 size_t alloc_size = 106 ALIGN_UP(tls_size, max(tls_align, _Alignof(tcb_t))) + sizeof(tcb_t); 107 #endif 108 109 void *area = alloc(max(tls_align, _Alignof(tcb_t)), alloc_size); 110 if (!area) 111 return NULL; 112 113 #ifdef CONFIG_TLS_VARIANT_1 114 tcb_t *tcb = area; 115 uint8_t *data = (uint8_t *)tcb + _tcb_data_offset(); 116 memset(tcb, 0, sizeof(*tcb)); 117 #else 118 uint8_t *data = area; 119 tcb_t *tcb = (tcb_t *) (data - _tcb_data_offset()); 120 memset(tcb, 0, sizeof(tcb_t)); 121 tcb->self = tcb; 122 #endif 123 124 if (!tls) 125 return tcb; 126 127 uintptr_t bias = elf_get_bias(elf); 128 129 /* Copy thread local data from the initialization image. */ 130 memcpy(data, (void *)(tls->p_vaddr + bias), tls->p_filesz); 131 /* Zero out the thread local uninitialized data. */ 132 memset(data + tls->p_filesz, 0, tls->p_memsz - tls->p_filesz); 133 134 return tcb; 135 } 136 137 static void *early_alloc(size_t align, size_t alloc_size) 138 { 139 assert(align <= PAGE_SIZE); 140 alloc_size = ALIGN_UP(alloc_size, PAGE_SIZE); 141 142 void *area = as_area_create(AS_AREA_ANY, alloc_size, 143 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, AS_AREA_UNPAGED); 144 if (area == AS_MAP_FAILED) 145 return NULL; 146 return area; 147 } 148 149 /** Same as tls_make(), but uses as_area_create() instead of memalign(). 150 * Only used in __libc_main() if the program was created by the kernel. 151 */ 152 tcb_t *tls_make_initial(const void *elf) 153 { 154 return tls_make_generic(elf, early_alloc); 75 155 } 76 156 … … 79 159 * @return Pointer to TCB. 80 160 */ 81 tcb_t *tls_make(void) 82 { 83 void *data; 84 tcb_t *tcb; 161 tcb_t *tls_make(const void *elf) 162 { 163 // TODO: Always use rtld. 85 164 86 165 #ifdef CONFIG_RTLD … … 89 168 #endif 90 169 91 const elf_segment_header_t *tls = 92 elf_get_phdr(__progsymbols.elfstart, PT_TLS); 93 if (tls == NULL) 94 return NULL; 95 96 uintptr_t bias = elf_get_bias(__progsymbols.elfstart); 97 size_t align = max(tls->p_align, _Alignof(tcb_t)); 98 99 #ifdef CONFIG_TLS_VARIANT_1 100 tcb = tls_alloc_arch( 101 ALIGN_UP(sizeof(tcb_t), align) + tls->p_memsz, align); 102 data = (void *) tcb + ALIGN_UP(sizeof(tcb_t), align); 103 #else 104 tcb = tls_alloc_arch( 105 ALIGN_UP(tls->p_memsz, align) + sizeof(tcb_t), align); 106 data = (void *) tcb - ALIGN_UP(tls->p_memsz, tls->p_align); 107 #endif 108 109 /* 110 * Copy thread local data from the initialization image. 111 */ 112 memcpy(data, (void *)(tls->p_vaddr + bias), tls->p_filesz); 113 /* 114 * Zero out the thread local uninitialized data. 115 */ 116 memset(data + tls->p_filesz, 0, tls->p_memsz - tls->p_filesz); 117 118 return tcb; 170 return tls_make_generic(elf, memalign); 119 171 } 120 172
Note:
See TracChangeset
for help on using the changeset viewer.