diff --git a/_test_green_threads/bux.toml b/_test_green_threads/bux.toml new file mode 100644 index 0000000..fda4e10 --- /dev/null +++ b/_test_green_threads/bux.toml @@ -0,0 +1,4 @@ +[package] +name = "green_threads_test" +version = "0.1.0" +pkgType = "bin" diff --git a/_test_green_threads/src/Main.bux b/_test_green_threads/src/Main.bux new file mode 100644 index 0000000..24c4aaa --- /dev/null +++ b/_test_green_threads/src/Main.bux @@ -0,0 +1,29 @@ +import Std::Task; +import Std::String; + +func Worker(id: int) { + PrintLine(String_Concat(String_Concat("Worker ", String_FromInt(id)), " starting")); + Task_Sleep(50); + PrintLine(String_Concat(String_Concat("Worker ", String_FromInt(id)), " done")); +} + +func Main() -> int { + PrintLine("=== Green Thread Test ==="); + + Task_Init(4); + + let h1: TaskHandle = Task_Spawn(Worker as *void, 1 as *void); + let h2: TaskHandle = Task_Spawn(Worker as *void, 2 as *void); + let h3: TaskHandle = Task_Spawn(Worker as *void, 3 as *void); + + PrintLine("Waiting for tasks..."); + + Task_Wait(h1); + Task_Wait(h2); + Task_Wait(h3); + + Task_Shutdown(); + + PrintLine("=== All tasks complete ==="); + return 0; +} diff --git a/rt/runtime.c b/rt/runtime.c index a992841..74934a7 100644 --- a/rt/runtime.c +++ b/rt/runtime.c @@ -829,8 +829,7 @@ typedef struct { static BuxTaskPool g_task_pool = {0}; static __thread BuxScheduler *g_scheduler = NULL; -static __thread BuxTask *g_task_creating = NULL; -static ucontext_t g_scheduler_context; +static __thread ucontext_t g_scheduler_context; static volatile int g_scheduler_active = 0; static int64_t bux_now_ms(void); @@ -901,7 +900,11 @@ static BuxTask* bux_find_task(BuxScheduler *sched) { } static void bux_task_entry(void) { - BuxTask *t = g_task_creating; + BuxTask *t = g_scheduler->current; + if (!t) { + fprintf(stderr, "bux runtime: task entry with NULL task\n"); + abort(); + } t->func(t->arg); t->state = BUX_TASK_FINISHED; swapcontext(&t->ctx, &g_scheduler_context); @@ -987,9 +990,7 @@ void* bux_task_spawn(void* (*func)(void*), void* arg) { task->ctx.uc_stack.ss_sp = task->stack; task->ctx.uc_stack.ss_size = task->stack_size; task->ctx.uc_link = &g_scheduler_context; - g_task_creating = task; makecontext(&task->ctx, bux_task_entry, 0); - g_task_creating = NULL; int worker = rand() % g_task_pool.num_workers; bux_queue_push(g_task_pool.schedulers[worker], task); return task;