From 7568525a4c24f55326bd8dd1d3a8d3ad9563d2bf Mon Sep 17 00:00:00 2001 From: Alessandre Laguierce Date: Fri, 21 Mar 2025 08:43:57 +0100 Subject: [PATCH] feat: better passive waiting --- src/thread/thread.c | 54 +++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/thread/thread.c b/src/thread/thread.c index fa7ef59..4c9f740 100644 --- a/src/thread/thread.c +++ b/src/thread/thread.c @@ -12,16 +12,16 @@ #define FINISHED 0x1 #define ALLOCATED 0x2 +#define WAITING 0x4 #ifndef STACK_SIZE -#define STACK_SIZE 4096*4 +#define STACK_SIZE 4096 #endif struct context_entry { TAILQ_ENTRY(context_entry) link; ucontext_t context; thread_t id; - thread_t parent; void *retvalue; int valgrind_id; char status; @@ -32,10 +32,11 @@ static struct context_entry *running = 0; static unsigned long long counter = 0; int thread_yield(void) { + TRACE("thread_yield"); if (counter <= 1) { return 0; } - struct context_entry *first; + struct context_entry *first = NULL; int count = 0; do { if (count++ == counter) { @@ -50,7 +51,9 @@ int thread_yield(void) { if (first->id == running->id) { return 0; } - } while (first->status & FINISHED); + } while ((first->status & FINISHED) || + ((first->status & WAITING) && !(((struct context_entry *)first->retvalue)->status & FINISHED))); + TRACE("PICKING %p", first); struct context_entry *old_runner = running; running = first; swapcontext(&old_runner->context, &running->context); @@ -64,21 +67,25 @@ thread_t thread_self(void) { return running->id; } +void thread_function_wrapper(void *(*func)(void *), void *funcarg) { + TRACE("Wrapper for %p\n", func); + thread_exit(func(funcarg)); +} + int thread_create(thread_t *newthread, void *(*func)(void *), void *funcarg) { TRACE("Create a new thread that execute function %p", func); - if (counter == 0) { - struct context_entry *main = malloc(sizeof(*main)); - memset(main, 0, sizeof(*main)); - getcontext(&main->context); - main->id = 0; - main->parent = 0; - main->status = 0; - main->retvalue = 0; - TAILQ_INSERT_HEAD(&head, main, link); - running = main; - counter++; - } struct context_entry *new_entry = malloc(sizeof(*new_entry)); + if (counter == 0) { + memset(new_entry, 0, sizeof(*new_entry)); + getcontext(&new_entry->context); + new_entry->id = 0; + new_entry->status = 0; + new_entry->retvalue = 0; + TAILQ_INSERT_HEAD(&head, new_entry, link); + running = new_entry; + counter++; + new_entry = malloc(sizeof(*new_entry)); + } memset(new_entry, 0, sizeof(*new_entry)); getcontext(&new_entry->context); new_entry->context.uc_stack.ss_sp = malloc(STACK_SIZE); @@ -88,18 +95,17 @@ int thread_create(thread_t *newthread, void *(*func)(void *), void *funcarg) { new_entry->context.uc_stack.ss_sp + new_entry->context.uc_stack.ss_size ); new_entry->id = new_entry; - new_entry->parent = running->id; new_entry->status = ALLOCATED; new_entry->retvalue = 0; *newthread = new_entry; - makecontext(&new_entry->context, (void (*)()) func, 1, funcarg); + makecontext(&new_entry->context, (void (*)(void)) thread_function_wrapper, 2, func, funcarg); counter++; TAILQ_INSERT_HEAD(&head, new_entry, link); return 0; } void print_entry(struct context_entry *entry) { - TRACE("CONTEXT (%p, %p, %d, %p);\n", entry, entry->id, (entry->status & FINISHED) > 0, entry->parent); + TRACE("CONTEXT (%p, %p, %d);", entry, entry->id, (entry->status & FINISHED) > 0); } int thread_join(thread_t thread, void **retval) { @@ -109,12 +115,14 @@ int thread_join(thread_t thread, void **retval) { if (entry->id != thread) { continue; } - TRACE("FIND"); - print_entry(entry); - while (!entry->status & FINISHED) { + TRACE("FIND %d",entry->status); + running->status |= WAITING; + running->retvalue = entry; + while (!(entry->status & FINISHED)) { TRACE("NOT FINISHED"); thread_yield(); } + running->status &= ~WAITING; TRACE("AFTER"); if (retval) *retval = entry->retvalue; @@ -144,6 +152,8 @@ int thread_join(thread_t thread, void **retval) { void thread_exit(void *retval) { TRACE("Exit thread %p", running); + if (running == 0) + exit(0); running->status |= FINISHED; running->retvalue = retval; thread_yield();