From 1c38a2289adf8426468b7ca8324d5cfc579d0963 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Mon, 27 Apr 2020 21:09:54 +0200 Subject: [PATCH] Rewrite psp1 libco Major differences: 1. Use of SceUID casted to void* as cothread_t. This fixes semantics of co_active which now cann be called several times with results staying valid and removes bunch of malloc and free 2. In co_create immediately suspend new thread to avoid it running simultaneoulsy with creating thread --- libco/psp1.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/libco/psp1.c b/libco/psp1.c index 45850a4..75a71c2 100644 --- a/libco/psp1.c +++ b/libco/psp1.c @@ -4,42 +4,38 @@ #include #include -/* Since cothread_t is a void pointer it must contain an address. We can't return a reference to a local variable - * because it would go out of scope, so we create a static variable instead so we can return a reference to it. - */ -static SceUID active_thread_id = 0; +typedef void (*entrypoint_t)(void); cothread_t co_active() { - active_thread_id = sceKernelGetThreadId(); - return &active_thread_id; + return (void *) sceKernelGetThreadId(); +} + +static int thread_wrap(unsigned int argc, void *argp) +{ + entrypoint_t entrypoint = *(entrypoint_t *) argp; + sceKernelSleepThread(); + entrypoint(); + return 0; } cothread_t co_create(unsigned int size, void (*entrypoint)(void)) { - /* Similar scenario as with active_thread_id except there will only be one active_thread_id while there could be many - * new threads each with their own handle, so we create them on the heap instead and delete them manually when they're - * no longer needed in co_delete(). - */ - cothread_t handle = malloc(sizeof(cothread_t)); - - /* SceKernelThreadEntry has a different signature than entrypoint, but in practice this seems to work */ - SceUID new_thread_id = sceKernelCreateThread("cothread", (SceKernelThreadEntry)entrypoint, 0x12, size, 0, NULL); - sceKernelStartThread(new_thread_id, 0, NULL); - - *(SceUID *)handle = new_thread_id; - return handle; + SceUID new_thread_id = sceKernelCreateThread("cothread", thread_wrap, 0x12, size, 0, NULL); + sceKernelStartThread(new_thread_id, sizeof (entrypoint), &entrypoint); + return (void *) new_thread_id; } void co_delete(cothread_t handle) { - sceKernelTerminateDeleteThread(*(SceUID *)handle); - free(handle); + SceUID id = (SceUID) handle; + sceKernelTerminateDeleteThread(id); } void co_switch(cothread_t handle) { - sceKernelWakeupThread(*(SceUID *)handle); + SceUID id = (SceUID) handle; + sceKernelWakeupThread(id); /* Sleep the currently active thread so the new thread can start */ sceKernelSleepThread(); -} \ No newline at end of file +}