From 52717da9a69695b42d053ec2787c24a636aa37e3 Mon Sep 17 00:00:00 2001 From: Lemaitre Date: Sun, 24 Oct 2021 21:28:53 +0200 Subject: [PATCH] Complete setup for TLS (including main thread) --- ape/ape.lds | 13 +++++++ examples/thread.c | 11 +++++- libc/runtime/cosmo.S | 1 + libc/runtime/cthread_init.c | 68 +++++++++++++++++++++++++++++++++++++ libc/stubs/ld.S | 15 ++++++++ libc/thread/create.c | 14 ++++++-- libc/thread/descriptor.h | 1 + 7 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 libc/runtime/cthread_init.c diff --git a/ape/ape.lds b/ape/ape.lds index b1ffd1383..ac41b1bc5 100644 --- a/ape/ape.lds +++ b/ape/ape.lds @@ -342,6 +342,19 @@ SECTIONS { /*END: Read Only Data (only needed for initialization) */ /*END: Read Only Data */ } :Rom + + .tdata . : { + _tdata_start = .; + *(SORT_BY_ALIGNMENT(.tdata)) + *(SORT_BY_ALIGNMENT(.tdata.*)) + _tdata_end = .; + } + .tbss . : { + _tbss_start = .; + *(SORT_BY_ALIGNMENT(.tbss)) + *(SORT_BY_ALIGNMENT(.tbss.*)) + _tbss_end = .; + } .data . : { /*BEGIN: Read/Write Data */ diff --git a/examples/thread.c b/examples/thread.c index 3c7783e6d..2f9c55523 100644 --- a/examples/thread.c +++ b/examples/thread.c @@ -7,6 +7,8 @@ │ • http://creativecommons.org/publicdomain/zero/1.0/ │ ╚─────────────────────────────────────────────────────────────────*/ #endif +#include "libc/calls/calls.h" +#include "libc/runtime/runtime.h" #include "libc/stdio/stdio.h" #include "libc/thread/create.h" #include "libc/thread/self.h" @@ -17,19 +19,26 @@ cthread_sem_t semaphore; +__thread int test_tls = 0x12345678; + int worker(void* arg) { + void* p; + arch_prctl(ARCH_GET_FS, &p); cthread_sem_signal(&semaphore); cthread_t self = cthread_self(); int tid = self->tid; sleep(1); //sleep(10000); - //printf("[%p] %d\n", self, tid); + printf("[%p] %d -> 0x%x\n", self, tid, test_tls); (void)arg; return 4; } int main() { + cthread_t self = cthread_self(); + int tid = self->tid; + printf("[%p] %d -> 0x%x\n", self, tid, test_tls); cthread_sem_init(&semaphore, 0); cthread_t thread; diff --git a/libc/runtime/cosmo.S b/libc/runtime/cosmo.S index 5760a93b0..a465e94a2 100644 --- a/libc/runtime/cosmo.S +++ b/libc/runtime/cosmo.S @@ -45,6 +45,7 @@ cosmo: push %rbp pop %rax #endif call _init + call _main_thread_init # FIXME: use .init.start macro ezlea __init_array_start,ax # static ctors in forward order .weak __init_array_start # could be called multiple times ezlea __init_array_end,cx # idempotency recommended diff --git a/libc/runtime/cthread_init.c b/libc/runtime/cthread_init.c new file mode 100644 index 000000000..20fbaa7bf --- /dev/null +++ b/libc/runtime/cthread_init.c @@ -0,0 +1,68 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/runtime/runtime.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/nr.h" +#include "libc/sysv/consts/prot.h" +#include "libc/thread/descriptor.h" + +// TLS boundaries +extern char _tbss_start, _tbss_end, _tdata_start, _tdata_end; + +void _main_thread_init(void) { + size_t tbsssize = &_tbss_end - &_tbss_start; + size_t tdatasize = &_tdata_end - &_tdata_start; + size_t tlssize = tbsssize + tdatasize; + size_t totalsize = tlssize + sizeof(struct cthread_descriptor_t); + totalsize = (totalsize + PAGESIZE - 1) & -PAGESIZE; + + uintptr_t mem = (uintptr_t)mmap(NULL, totalsize, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (mem == -1) { + abort(); + } + + void* bottom = (void*)mem; + void* top = (void*)(mem + totalsize); + + cthread_t td = (cthread_t)top - 1; + td->self = td; + td->stack.top = NULL; + td->stack.bottom = NULL; + td->tls.top = top; + td->tls.bottom = bottom; + td->alloc.top = top; + td->alloc.bottom = bottom; + td->state = cthread_main; + + // Initialize TLS with content of .tdata section + memmove((void*)((uintptr_t)td - tlssize), &_tdata_start, tdatasize); + + // Get TID of main thread + int gettid = __NR_gettid; + if (gettid == 0xfff) gettid = __NR_getpid; + td->tid = syscall(gettid); + + // Set FS + if (arch_prctl(ARCH_SET_FS, td) != 0) { + abort(); + } +} diff --git a/libc/stubs/ld.S b/libc/stubs/ld.S index 583768fa5..23d78e6db 100644 --- a/libc/stubs/ld.S +++ b/libc/stubs/ld.S @@ -36,6 +36,13 @@ __relo_start = 0 __relo_end = 0 +// Thread local boundaries defined by linker script +// @see ape/ape.lds + _tbss_start = 0 + _tbss_end = 0 + _tdata_start = 0 + _tdata_end = 0 + .globl _base .globl ape_xlm .globl __relo_start @@ -48,6 +55,10 @@ .globl _end .globl _ereal .globl _etext + .globl _tbss_start + .globl _tbss_end + .globl _tdata_start + .globl _tdata_end .weak _base .weak ape_xlm @@ -61,3 +72,7 @@ .weak _end .weak _ereal .weak _etext + .weak _tbss_start + .weak _tbss_end + .weak _tdata_start + .weak _tdata_end diff --git a/libc/thread/create.c b/libc/thread/create.c index c5b5d0c42..45582ac4b 100644 --- a/libc/thread/create.c +++ b/libc/thread/create.c @@ -19,17 +19,25 @@ #include "libc/errno.h" #include "libc/linux/clone.h" #include "libc/runtime/runtime.h" +#include "libc/str/str.h" #include "libc/sysv/consts/clone.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/nr.h" #include "libc/sysv/consts/prot.h" #include "libc/thread/create.h" +// TLS boundaries +extern char _tbss_start, _tbss_end, _tdata_start, _tdata_end; + static cthread_t _thread_allocate(const cthread_attr_t* attr) { + //extern void _main_thread_init(void); + //void (*dummy)(void) = &_main_thread_init; + //asm(""::"r"(dummy)); size_t stacksize = attr->stacksize; size_t guardsize = attr->guardsize; - // FIXME: properly count TLS size - size_t tlssize = 0; + size_t tbsssize = &_tbss_end - &_tbss_start; + size_t tdatasize = &_tdata_end - &_tdata_start; + size_t tlssize = tbsssize + tdatasize; size_t totalsize = 3 * guardsize + stacksize + tlssize + sizeof(struct cthread_descriptor_t); @@ -64,6 +72,8 @@ static cthread_t _thread_allocate(const cthread_attr_t* attr) { td->alloc.bottom = alloc_bottom; td->state = (attr->mode & CTHREAD_CREATE_DETACHED) ? cthread_detached : cthread_started; + // Initialize TLS with content of .tdata section + memmove((void*)((uintptr_t)td - tlssize), &_tdata_start, tdatasize); return td; } diff --git a/libc/thread/descriptor.h b/libc/thread/descriptor.h index 587092d12..29e815563 100644 --- a/libc/thread/descriptor.h +++ b/libc/thread/descriptor.h @@ -12,6 +12,7 @@ enum cthread_state { cthread_joining = 1, cthread_finished = 2, cthread_detached = 4, + cthread_main = 127, }; struct cthread_descriptor_t {