Skip to content

Commit

Permalink
[WIP] Threading phase 2 (#301)
Browse files Browse the repository at this point in the history
* Exponential back-off
* Removed "native" specifier
* Abstract away Futex for cthread
* Complete setup for TLS (including main thread)
  • Loading branch information
lemaitre authored Oct 25, 2021
1 parent 660ff56 commit 45a7435
Show file tree
Hide file tree
Showing 11 changed files with 249 additions and 78 deletions.
13 changes: 13 additions & 0 deletions ape/ape.lds
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
25 changes: 17 additions & 8 deletions examples/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,44 @@
│ • 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"
#include "libc/thread/detach.h"
#include "libc/thread/join.h"
#include "libc/thread/nativesem.h"
#include "libc/thread/sem.h"
#include "libc/time/time.h"

cthread_native_sem_t semaphore;
cthread_sem_t semaphore;

__thread int test_tls = 0x12345678;

int worker(void* arg) {
cthread_native_sem_signal(&semaphore);
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_native_sem_init(&semaphore, 0);
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;
int rc = cthread_create(&thread, NULL, &worker, NULL);
if (rc == 0) {
cthread_native_sem_wait(&semaphore, 0, 0, NULL);
cthread_sem_wait(&semaphore, 0, NULL);
//printf("thread created: %p\n", thread);
sleep(1);
#if 1
Expand All @@ -44,8 +53,8 @@ int main() {
rc = cthread_detach(thread);
sleep(2);
#endif
cthread_native_sem_signal(&semaphore);
cthread_native_sem_wait(&semaphore, 0, 0, NULL);
cthread_sem_signal(&semaphore);
cthread_sem_wait(&semaphore, 0, NULL);
//printf("thread joined: %p -> %d\n", thread, rc);
} else {
printf("ERROR: thread could not be started: %d\n", rc);
Expand Down
1 change: 1 addition & 0 deletions libc/runtime/cosmo.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
68 changes: 68 additions & 0 deletions libc/runtime/cthread_init.c
Original file line number Diff line number Diff line change
@@ -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();
}
}
15 changes: 15 additions & 0 deletions libc/stubs/ld.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -61,3 +72,7 @@
.weak _end
.weak _ereal
.weak _etext
.weak _tbss_start
.weak _tbss_end
.weak _tdata_start
.weak _tdata_end
14 changes: 12 additions & 2 deletions libc/thread/create.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions libc/thread/descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ enum cthread_state {
cthread_joining = 1,
cthread_finished = 2,
cthread_detached = 4,
cthread_main = 127,
};

struct cthread_descriptor_t {
Expand Down
Loading

0 comments on commit 45a7435

Please sign in to comment.