include include include import "./core.zc" import "./result.zc" import "./mem.zc" import "./sync.zc" // Essential raw block: required for pthread operations and closure trampolining // This block cannot be eliminated because: // 1. z_closure_T is an internal compiler type for Zen-C closures // 2. pthread_t, pthread_mutex_t are opaque types that can't be extern'd with void* // 3. The trampoline function needs to cast and execute Zen-C closures raw { typedef void (*ZenThreadFunc)(void*); struct ZenThreadCtx { void *func_ptr; void *ctx; }; static void* _z_thread_trampoline(void *arg) { z_closure_T *closure = (z_closure_T*)arg; void (*f)(void*) = (void(*)(void*))closure->func; f(closure->ctx); if (closure->drop) closure->drop(closure->ctx); // In MISRA mode, we don't freeCtx. // In non-MISRA mode, this still uses free() which is fine as it's raw C. // Actually, we should use a macro prefix to be consistent. #ifndef ZC_MISRA free(closure); #endif return NULL; } static int _z_thread_equal(void* handle1, void* handle2) { return pthread_equal((pthread_t)handle1, (pthread_t)handle2); } static int _z_thread_spawn(void *ctx_copy, size_t *out_handle) { pthread_t pt; int ret = pthread_create(&pt, NULL, _z_thread_trampoline, ctx_copy); if (ret == 0) { *out_handle = (size_t)pt; } return (int)ret; } static int _z_thread_join(void *handle) { return (int)pthread_join((pthread_t)handle, NULL); } static int _z_thread_detach(void* handle) { return pthread_detach((pthread_t)handle); } static int _z_thread_cancel(void* handle) { return pthread_cancel((pthread_t)handle); } static void _z_usleep(int micros) { usleep(micros); } } extern fn _z_thread_equal(handle1: void*, handle2: void*) -> c_int; extern fn _z_thread_spawn(ctx: void*, out: usize*) -> c_int; extern fn _z_thread_join(handle: void*) -> c_int; extern fn _z_thread_detach(handle: void*) -> c_int; extern fn _z_thread_cancel(handle: void*) -> c_int; extern fn _z_usleep(micros: c_int); struct Thread { handle: void*; } impl Thread { /// Spawns a thread running the closure. fn spawn(func: fn()) -> Result { let out_handle: usize = 0; let ctx = alloc_bytes(sizeof(fn())); if (ctx == NULL) return Result::Err("OOM"); memcpy(ctx, &func, sizeof(fn())); // Zero out the drop field to prevent f64-free by this function's cleanup raw { ((z_closure_T*)&func)->drop = NULL; } let ret = _z_thread_spawn(ctx, &out_handle); if ret != 0 { dealloc(ctx); return Result::Err("Failed to create thread"); } return Result::Ok(Thread { handle: (void*)out_handle }); } /// Waits for the thread to finish. fn join(self) -> Result { let err = _z_thread_join(self.handle); if err { return Result::Err("Join failed"); } return Result::Ok(true); } /// Detaches the thread (runs independently). fn detach(self) -> Result { let err = _z_thread_detach(self.handle); if err { return Result::Err("Detach failed"); } return Result::Ok(true); } fn cancel(self) -> Result { let err = _z_thread_cancel(self.handle); if err { return Result::Err("Cancel failed"); } return Result::Ok(true); } } fn sleep_ms(ms: int) { let micros: c_int = (c_int)(ms * 1000); _z_usleep(micros); }