From f5b3a7a87e028fe1630d0abbbe82c1abcacdd969 Mon Sep 17 00:00:00 2001 From: Alessandre Laguierce Date: Thu, 20 Mar 2025 19:43:00 +0100 Subject: [PATCH] feat: first version, just want to beat M. Faverge on the leaderboard for the first benchmark --- Makefile | 7 +++ src/thread/thread.c | 102 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 101 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 6bb380e..818dcfb 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,9 @@ ifdef USE_PTHREAD LDFLAGS+=-lpthread CFLAGS+=-DUSE_PTHREAD endif +ifndef USE_DEBUG +CFLAGS+=-DNDEBUG +endif # Tests if the last compilation was with pthread ifeq ("$(wildcard .lastpthread)","") @@ -84,6 +87,10 @@ ${valgrind_targets}: valgrind_%: ${build_dir}/% .PHONY: build build: ${bins_target} ${build_dir}/libthread.so ${build_dir}/libthread.a +.PHONY: debug +debug: + $(MAKE) USE_DEBUG=. build + .PHONY: pthreads pthreads: $(MAKE) USE_PTHREAD=. ${pthread_targets} diff --git a/src/thread/thread.c b/src/thread/thread.c index 2b24486..3fbf083 100644 --- a/src/thread/thread.c +++ b/src/thread/thread.c @@ -3,32 +3,118 @@ #include "thread.h" #include "debug.h" #include "pthread.h" +#include #include -#include +#include +#include +#ifndef STACK_SIZE +#define STACK_SIZE 4096*4 +#endif + +struct context_entry { + ucontext_t context; + thread_t id; + thread_t parent; + int finished; + void *retvalue; + TAILQ_ENTRY(context_entry) link; +}; + +static TAILQ_HEAD(context_head, context_entry) head = TAILQ_HEAD_INITIALIZER(head); +static struct context_entry *running = 0; +static unsigned long long counter = 0; int thread_yield(void) { - return sched_yield(); + if (counter <= 1) { + return 0; + } + struct context_entry *first; + do { + first = TAILQ_FIRST(&head); + if (!first) { + return -1; + } + if (first->id == running->id) { + return 0; + } + TAILQ_REMOVE(&head, first, link); + TAILQ_INSERT_TAIL(&head, first, link); + } while (first->finished); + struct context_entry *old_runner = running; + running = first; + swapcontext(&old_runner->context, &running->context); + return 0; } - thread_t thread_self(void) { -return (void *) pthread_self(); + if (running == NULL) { + return 0; + } + return running->id; } int thread_create(thread_t *newthread, void *(*func)(void *), void *funcarg) { TRACE("Create a new thread that execute function %p", func); - return pthread_create((pthread_t *) newthread, NULL, func, funcarg); + if (counter == 0) { + struct context_entry *main = malloc(sizeof(*main)); + getcontext(&main->context); + main->id = 0; + TAILQ_INSERT_HEAD(&head, main, link); + running = main; + counter++; + } + struct context_entry *new_entry = malloc(sizeof(*new_entry)); + getcontext(&new_entry->context); + new_entry->context.uc_stack.ss_sp = malloc(STACK_SIZE); + new_entry->context.uc_stack.ss_size = STACK_SIZE; + new_entry->id = new_entry; + new_entry->parent = running->id; + new_entry->finished = 0; + new_entry->retvalue = 0; + *newthread = new_entry; + makecontext(&new_entry->context, (void (*)()) func, 1, 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->finished, entry->parent); } int thread_join(thread_t thread, void **retval) { TRACE("Join thread %p", thread); - return pthread_join((pthread_t) thread, retval); + struct context_entry *entry; + TAILQ_FOREACH(entry, &head, link) { + if (entry->id != thread) { + continue; + } + while (!entry->finished) { + thread_yield(); + } + if (retval) + *retval = entry->retvalue; + TAILQ_REMOVE(&head, entry, link); + free(entry->context.uc_stack.ss_sp); + free(entry); + if (--counter == 1) { + TAILQ_REMOVE(&head, running, link); + free(running->context.uc_stack.ss_sp); + free(running); + running = 0; + counter = 0; + } + return 0; + } + return -1; } void thread_exit(void *retval) { - TRACE("Exit thread"); - pthread_exit(retval); + TRACE("Exit thread %p", running); + running->finished = 1; + running->retvalue = retval; + thread_yield(); } int thread_mutex_init(thread_mutex_t *mutex) {