mirror of
https://github.com/libretro/libretro-common.git
synced 2024-11-24 00:29:50 +00:00
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
This commit is contained in:
parent
5baa0fc101
commit
1c38a2289a
40
libco/psp1.c
40
libco/psp1.c
@ -4,42 +4,38 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <pspthreadman.h>
|
#include <pspthreadman.h>
|
||||||
|
|
||||||
/* Since cothread_t is a void pointer it must contain an address. We can't return a reference to a local variable
|
typedef void (*entrypoint_t)(void);
|
||||||
* 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;
|
|
||||||
|
|
||||||
cothread_t co_active()
|
cothread_t co_active()
|
||||||
{
|
{
|
||||||
active_thread_id = sceKernelGetThreadId();
|
return (void *) sceKernelGetThreadId();
|
||||||
return &active_thread_id;
|
}
|
||||||
|
|
||||||
|
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))
|
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
|
SceUID new_thread_id = sceKernelCreateThread("cothread", thread_wrap, 0x12, size, 0, NULL);
|
||||||
* new threads each with their own handle, so we create them on the heap instead and delete them manually when they're
|
sceKernelStartThread(new_thread_id, sizeof (entrypoint), &entrypoint);
|
||||||
* no longer needed in co_delete().
|
return (void *) new_thread_id;
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_delete(cothread_t handle)
|
void co_delete(cothread_t handle)
|
||||||
{
|
{
|
||||||
sceKernelTerminateDeleteThread(*(SceUID *)handle);
|
SceUID id = (SceUID) handle;
|
||||||
free(handle);
|
sceKernelTerminateDeleteThread(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void co_switch(cothread_t handle)
|
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 */
|
/* Sleep the currently active thread so the new thread can start */
|
||||||
sceKernelSleepThread();
|
sceKernelSleepThread();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user