Changeset 40abf56 in mainline
- Timestamp:
- 2018-07-18T19:42:28Z (7 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)
- Location:
- uspace
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/elf/elf_load.c
r0b05082 r40abf56 68 68 } 69 69 70 if (info->finfo. interp== NULL) {70 if (info->finfo.dynamic == NULL) { 71 71 /* Statically linked program */ 72 72 DPRINTF("Binary is statically linked.\n"); -
uspace/lib/c/generic/fibril.c
r0b05082 r40abf56 50 50 #include "private/thread.h" 51 51 #include "private/fibril.h" 52 52 #include "private/libc.h" 53 53 54 54 /** … … 85 85 } 86 86 87 /** Setup fibril information into TCB structure 88 * 89 */ 90 fibril_t *fibril_setup(void) 91 { 92 tcb_t *tcb = tls_make(); 87 /** Allocate a fibril structure and TCB, but don't do anything else with it. */ 88 fibril_t *fibril_alloc(void) 89 { 90 tcb_t *tcb = tls_make(__progsymbols.elfstart); 93 91 if (!tcb) 94 92 return NULL; … … 102 100 tcb->fibril_data = fibril; 103 101 fibril->tcb = tcb; 104 105 /* 106 * We are called before __tcb_set(), so we need to use 107 * futex_down/up() instead of futex_lock/unlock() that 108 * may attempt to access TLS. 109 */ 110 futex_down(&fibril_futex); 111 list_append(&fibril->all_link, &fibril_list); 112 futex_up(&fibril_futex); 113 102 fibril->is_freeable = true; 103 104 fibril_setup(fibril); 114 105 return fibril; 106 } 107 108 /** 109 * Put the fibril into fibril_list. 110 */ 111 void fibril_setup(fibril_t *f) 112 { 113 futex_lock(&fibril_futex); 114 list_append(&f->all_link, &fibril_list); 115 futex_unlock(&fibril_futex); 115 116 } 116 117 … … 122 123 if (!locked) 123 124 futex_unlock(&fibril_futex); 124 tls_free(fibril->tcb); 125 free(fibril); 125 126 if (fibril->is_freeable) { 127 tls_free(fibril->tcb); 128 free(fibril); 129 } 126 130 } 127 131 … … 239 243 fibril_t *fibril; 240 244 241 fibril = fibril_ setup();245 fibril = fibril_alloc(); 242 246 if (fibril == NULL) 243 247 return 0; … … 248 252 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE | AS_AREA_GUARD | 249 253 AS_AREA_LATE_RESERVE, AS_AREA_UNPAGED); 250 if (fibril->stack == (void *) -1) {254 if (fibril->stack == AS_MAP_FAILED) { 251 255 fibril_teardown(fibril, false); 252 256 return 0; … … 324 328 fibril_t *fibril_self(void) 325 329 { 326 return __tcb_get()->fibril_data; 330 assert(__tcb_is_set()); 331 tcb_t *tcb = __tcb_get(); 332 assert(tcb->fibril_data); 333 return tcb->fibril_data; 327 334 } 328 335 -
uspace/lib/c/generic/io/kio.c
r0b05082 r40abf56 56 56 errno_t kio_write(const void *buf, size_t size, size_t *nwritten) 57 57 { 58 futex_lock(&kio_buffer.futex); 58 /* Using down/up instead of lock/unlock so we can print very early. */ 59 futex_down(&kio_buffer.futex); 59 60 60 61 const char *s = buf; … … 82 83 } 83 84 84 futex_u nlock(&kio_buffer.futex);85 futex_up(&kio_buffer.futex); 85 86 if (nwritten) 86 87 *nwritten = size; -
uspace/lib/c/generic/libc.c
r0b05082 r40abf56 63 63 progsymbols_t __progsymbols; 64 64 65 static bool env_setup = false; 65 static bool env_setup; 66 static fibril_t main_fibril; 66 67 67 68 void __libc_main(void *pcb_ptr) 68 69 { 70 assert(!__tcb_is_set()); 71 72 __pcb = (pcb_t *) pcb_ptr; 73 74 if (__pcb) { 75 main_fibril.tcb = __pcb->tcb; 76 } else { 77 /* 78 * Loaded by kernel, not the loader. 79 * Kernel only supports loading fully static binaries, 80 * so we can do basic initialization without worrying about 81 * dynamic libraries. 82 */ 83 84 main_fibril.tcb = tls_make_initial(__progsymbols.elfstart); 85 } 86 87 assert(main_fibril.tcb); 88 89 /* Initialize the fibril. */ 90 main_fibril.tcb->fibril_data = &main_fibril; 91 __tcb_set(main_fibril.tcb); 92 fibril_setup(&main_fibril); 93 69 94 /* Initialize user task run-time environment */ 70 95 __malloc_init(); 71 72 /* Save the PCB pointer */73 __pcb = (pcb_t *) pcb_ptr;74 96 75 97 #ifdef CONFIG_RTLD … … 81 103 } 82 104 #endif 83 84 fibril_t *fibril = fibril_setup();85 if (fibril == NULL)86 abort();87 88 __tcb_set(fibril->tcb);89 105 90 106 __async_server_init(); … … 151 167 __stdio_done(); 152 168 task_retval(status); 153 fibril_teardown(__tcb_get()->fibril_data, false);154 169 } 155 170 -
uspace/lib/c/generic/private/fibril.h
r0b05082 r40abf56 55 55 atomic_t futex_locks; 56 56 bool is_writer : 1; 57 /* In some places, we use fibril structs that can't be freed. */ 58 bool is_freeable : 1; 57 59 }; 58 60 … … 64 66 } fibril_switch_type_t; 65 67 66 extern fibril_t *fibril_setup(void); 68 extern fibril_t *fibril_alloc(void); 69 extern void fibril_setup(fibril_t *); 67 70 extern void fibril_teardown(fibril_t *f, bool locked); 68 71 extern int fibril_switch(fibril_switch_type_t stype); -
uspace/lib/c/generic/rtld/module.c
r0b05082 r40abf56 368 368 * be correct, "zero" offset (i.e. the total size) must be aligned 369 369 * to the strictest alignment present. 370 * Note that the padding is actually in front of the TLS data, 371 * not after it. 370 372 */ 371 373 rtld->tls_size = ALIGN_UP(rtld->tls_size, rtld->tls_align); -
uspace/lib/c/generic/thread.c
r0b05082 r40abf56 58 58 void __thread_main(uspace_arg_t *uarg) 59 59 { 60 fibril_t *fibril = fibril_setup(); 61 if (fibril == NULL) 62 thread_exit(0); 60 assert(!__tcb_is_set()); 61 62 fibril_t *fibril = uarg->uspace_thread_arg; 63 assert(fibril); 63 64 64 65 __tcb_set(fibril->tcb); 65 66 66 uarg->uspace_thread_function( uarg->uspace_thread_arg);67 uarg->uspace_thread_function(fibril->arg); 67 68 /* 68 69 * XXX: we cannot free the userspace stack while running on it … … 95 96 thread_id_t *tid) 96 97 { 97 uspace_arg_t *uarg = 98 (uspace_arg_t *) malloc(sizeof(uspace_arg_t)); 98 uspace_arg_t *uarg = calloc(1, sizeof(uspace_arg_t)); 99 99 if (!uarg) 100 100 return ENOMEM; 101 102 fibril_t *fibril = fibril_alloc(); 103 if (!fibril) { 104 free(uarg); 105 return ENOMEM; 106 } 101 107 102 108 size_t stack_size = stack_size_get(); … … 105 111 AS_AREA_LATE_RESERVE, AS_AREA_UNPAGED); 106 112 if (stack == AS_MAP_FAILED) { 113 fibril_teardown(fibril, false); 107 114 free(uarg); 108 115 return ENOMEM; … … 112 119 malloc_enable_multithreaded(); 113 120 121 fibril->arg = arg; 114 122 uarg->uspace_entry = (void *) FADDR(__thread_entry); 115 123 uarg->uspace_stack = stack; 116 124 uarg->uspace_stack_size = stack_size; 117 125 uarg->uspace_thread_function = function; 118 uarg->uspace_thread_arg = arg;126 uarg->uspace_thread_arg = fibril; 119 127 uarg->uspace_uarg = uarg; 120 128 -
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 -
uspace/lib/c/include/loader/pcb.h
r0b05082 r40abf56 37 37 #define LIBC_PCB_H_ 38 38 39 #include <tls.h> 39 40 40 41 typedef void (*entry_point_t)(void); … … 76 77 /** Pointer to dynamic linker state structure (rtld_t). */ 77 78 void *rtld_runtime; 79 80 /** Thread local storage for the main thread. */ 81 tcb_t *tcb; 78 82 } pcb_t; 79 83 -
uspace/lib/c/include/tls.h
r0b05082 r40abf56 69 69 #define DTV_GN(dtv) (((uintptr_t *)(dtv))[0]) 70 70 71 extern tcb_t *tls_make(void); 71 extern tcb_t *tls_make(const void *); 72 extern tcb_t *tls_make_initial(const void *); 72 73 extern tcb_t *tls_alloc_arch(size_t, size_t); 73 74 extern void tls_free(tcb_t *); -
uspace/srv/loader/main.c
r0b05082 r40abf56 62 62 #include <vfs/inbox.h> 63 63 64 #ifdef CONFIG_RTLD 65 #include <rtld/rtld.h> 66 #endif 67 64 68 #define DPRINTF(...) ((void) 0) 65 69 … … 296 300 DPRINTF("Loaded.\n"); 297 301 302 #ifdef CONFIG_RTLD 303 if (prog_info.env) { 304 pcb.tcb = rtld_tls_make(prog_info.env); 305 } else { 306 pcb.tcb = tls_make(prog_info.finfo.base); 307 } 308 #else 309 pcb.tcb = tls_make(prog_info.finfo.base); 310 #endif 311 298 312 elf_set_pcb(&prog_info, &pcb); 299 313 … … 328 342 DPRINTF("Reply OK\n"); 329 343 async_answer_0(req, EOK); 344 330 345 DPRINTF("Jump to entry point at %p\n", pcb.entry); 346 347 __tcb_reset(); 331 348 entry_point_jmp(prog_info.finfo.entry, &pcb); 332 349
Note:
See TracChangeset
for help on using the changeset viewer.