Update libco

This commit is contained in:
twinaphex 2022-04-06 22:13:09 +02:00
parent bcff804632
commit 01058613a0
11 changed files with 601 additions and 46 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (libco.h).

View File

@ -0,0 +1,128 @@
/*
libco.aarch64 (2017-06-26)
author: webgeek1234
license: public domain
*/
#define LIBCO_C
#include "libco.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#ifndef __APPLE__
#include <malloc.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
static thread_local uint64_t co_active_buffer[64];
static thread_local cothread_t co_active_handle;
asm (
".globl co_switch_aarch64\n"
".globl _co_switch_aarch64\n"
"co_switch_aarch64:\n"
"_co_switch_aarch64:\n"
" stp x8, x9, [x1]\n"
" stp x10, x11, [x1, #16]\n"
" stp x12, x13, [x1, #32]\n"
" stp x14, x15, [x1, #48]\n"
" str x19, [x1, #72]\n"
" stp x20, x21, [x1, #80]\n"
" stp x22, x23, [x1, #96]\n"
" stp x24, x25, [x1, #112]\n"
" stp x26, x27, [x1, #128]\n"
" stp x28, x29, [x1, #144]\n"
" mov x16, sp\n"
" stp x16, x30, [x1, #160]\n"
" ldp x8, x9, [x0]\n"
" ldp x10, x11, [x0, #16]\n"
" ldp x12, x13, [x0, #32]\n"
" ldp x14, x15, [x0, #48]\n"
" ldr x19, [x0, #72]\n"
" ldp x20, x21, [x0, #80]\n"
" ldp x22, x23, [x0, #96]\n"
" ldp x24, x25, [x0, #112]\n"
" ldp x26, x27, [x0, #128]\n"
" ldp x28, x29, [x0, #144]\n"
" ldp x16, x17, [x0, #160]\n"
" mov sp, x16\n"
" br x17\n"
);
/* ASM */
void co_switch_aarch64(cothread_t handle, cothread_t current);
static void crash(void)
{
/* Called only if cothread_t entrypoint returns. */
assert(0);
}
cothread_t co_create(unsigned int size, void (*entrypoint)(void))
{
size = (size + 1023) & ~1023;
cothread_t handle = 0;
#if HAVE_POSIX_MEMALIGN >= 1
if (posix_memalign(&handle, 1024, size + 512) < 0)
return 0;
#else
handle = memalign(1024, size + 512);
#endif
if (!handle)
return handle;
uint64_t *ptr = (uint64_t*)handle;
/* Non-volatiles. */
ptr[0] = 0; /* x8 */
ptr[1] = 0; /* x9 */
ptr[2] = 0; /* x10 */
ptr[3] = 0; /* x11 */
ptr[4] = 0; /* x12 */
ptr[5] = 0; /* x13 */
ptr[6] = 0; /* x14 */
ptr[7] = 0; /* x15 */
ptr[8] = 0; /* padding */
ptr[9] = 0; /* x19 */
ptr[10] = 0; /* x20 */
ptr[11] = 0; /* x21 */
ptr[12] = 0; /* x22 */
ptr[13] = 0; /* x23 */
ptr[14] = 0; /* x24 */
ptr[15] = 0; /* x25 */
ptr[16] = 0; /* x26 */
ptr[17] = 0; /* x27 */
ptr[18] = 0; /* x28 */
ptr[20] = (uintptr_t)ptr + size + 512 - 16; /* x30, stack pointer */
ptr[19] = ptr[20]; /* x29, frame pointer */
ptr[21] = (uintptr_t)entrypoint; /* PC (link register x31 gets saved here). */
return handle;
}
cothread_t co_active(void)
{
if (!co_active_handle)
co_active_handle = co_active_buffer;
return co_active_handle;
}
void co_delete(cothread_t handle)
{
free(handle);
}
void co_switch(cothread_t handle)
{
cothread_t co_previous_handle = co_active();
co_switch_aarch64(co_active_handle = handle, co_previous_handle);
}
#ifdef __cplusplus
}
#endif

View File

@ -25,51 +25,56 @@ static void (*co_swap)(cothread_t, cothread_t) = 0;
#ifdef _WIN32
/* ABI: Win64 */
/* On windows handle is allocated by malloc and there it's guaranteed to
have at least 16-byte alignment. Hence we don't need to align
it in order to use movaps. */
static unsigned char co_swap_function[] = {
0x48, 0x89, 0x22, /* mov [rdx],rsp */
0x48, 0x8b, 0x21, /* mov rsp,[rcx] */
0x58, /* pop rax */
0x48, 0x89, 0x6a, 0x08, /* mov [rdx+0x8],rbp */
0x48, 0x89, 0x72, 0x10, /* mov [rdx+0x10],rsi */
0x48, 0x89, 0x7a, 0x18, /* mov [rdx+0x18],rdi */
0x48, 0x89, 0x5a, 0x20, /* mov [rdx+0x20],rbx */
0x4c, 0x89, 0x62, 0x28, /* mov [rdx+0x28],r12 */
0x4c, 0x89, 0x6a, 0x30, /* mov [rdx+0x30],r13 */
0x4c, 0x89, 0x72, 0x38, /* mov [rdx+0x38],r14 */
0x4c, 0x89, 0x7a, 0x40, /* mov [rdx+0x40],r15 */
0x48, 0x81, 0xc2, 0x80, 0x00, 0x00, 0x00, /* add rdx,0x80 */
0x48, 0x83, 0xe2, 0xf0, /* and rdx,-0x10 */
0x0f, 0x29, 0x32, /* movaps [rdx],xmm6 */
0x0f, 0x29, 0x7a, 0x10, /* movaps [rdx+0x10],xmm7 */
0x44, 0x0f, 0x29, 0x42, 0x20, /* movaps [rdx+0x20],xmm8 */
0x44, 0x0f, 0x29, 0x4a, 0x30, /* movaps [rdx+0x30],xmm9 */
0x44, 0x0f, 0x29, 0x52, 0x40, /* movaps [rdx+0x40],xmm10 */
0x44, 0x0f, 0x29, 0x5a, 0x50, /* movaps [rdx+0x50],xmm11 */
0x44, 0x0f, 0x29, 0x62, 0x60, /* movaps [rdx+0x60],xmm12 */
0x44, 0x0f, 0x29, 0x6a, 0x70, /* movaps [rdx+0x70],xmm13 */
0x44, 0x0f, 0x29, 0xb2, 0x80, 0x00, 0x00, 0x00, /* movaps [rdx+0x80],xmm14 */
0x44, 0x0f, 0x29, 0xba, 0x90, 0x00, 0x00, 0x00, /* movaps [rdx+0x90],xmm15 */
0x48, 0x8b, 0x69, 0x08, /* mov rbp,[rcx+0x8] */
0x48, 0x8b, 0x71, 0x10, /* mov rsi,[rcx+0x10] */
0x48, 0x8b, 0x79, 0x18, /* mov rdi,[rcx+0x18] */
0x48, 0x8b, 0x59, 0x20, /* mov rbx,[rcx+0x20] */
0x4c, 0x8b, 0x61, 0x28, /* mov r12,[rcx+0x28] */
0x4c, 0x8b, 0x69, 0x30, /* mov r13,[rcx+0x30] */
0x4c, 0x8b, 0x71, 0x38, /* mov r14,[rcx+0x38] */
0x4c, 0x8b, 0x79, 0x40, /* mov r15,[rcx+0x40] */
0x48, 0x81, 0xc1, 0x80, 0x00, 0x00, 0x00, /* add rcx,0x80 */
0x48, 0x83, 0xe1, 0xf0, /* and rcx,-0x10 */
0x0f, 0x29, 0x31, /* movaps [rcx],xmm6 */
0x0f, 0x29, 0x79, 0x10, /* movaps [rcx+0x10],xmm7 */
0x44, 0x0f, 0x29, 0x41, 0x20, /* movaps [rcx+0x20],xmm8 */
0x44, 0x0f, 0x29, 0x49, 0x30, /* movaps [rcx+0x30],xmm9 */
0x44, 0x0f, 0x29, 0x51, 0x40, /* movaps [rcx+0x40],xmm10 */
0x44, 0x0f, 0x29, 0x59, 0x50, /* movaps [rcx+0x50],xmm11 */
0x44, 0x0f, 0x29, 0x61, 0x60, /* movaps [rcx+0x60],xmm12 */
0x44, 0x0f, 0x29, 0x69, 0x70, /* movaps [rcx+0x70],xmm13 */
0x44, 0x0f, 0x29, 0xb1, 0x80, 0x00, 0x00, 0x00, /* movaps [rcx+0x80],xmm14 */
0x44, 0x0f, 0x29, 0xb9, 0x90, 0x00, 0x00, 0x00, /* movaps [rcx+0x90],xmm15 */
0xff, 0xe0, /* jmp rax */
0x48, 0x89, 0x22, /* mov [rdx],rsp */
0x48, 0x8b, 0x21, /* mov rsp,[rcx] */
0x58, /* pop rax */
0x48, 0x89, 0x6a, 0x08, /* mov [rdx+ 8],rbp */
0x48, 0x89, 0x72, 0x10, /* mov [rdx+16],rsi */
0x48, 0x89, 0x7a, 0x18, /* mov [rdx+24],rdi */
0x48, 0x89, 0x5a, 0x20, /* mov [rdx+32],rbx */
0x4c, 0x89, 0x62, 0x28, /* mov [rdx+40],r12 */
0x4c, 0x89, 0x6a, 0x30, /* mov [rdx+48],r13 */
0x4c, 0x89, 0x72, 0x38, /* mov [rdx+56],r14 */
0x4c, 0x89, 0x7a, 0x40, /* mov [rdx+64],r15 */
#if !defined(LIBCO_NO_SSE)
0x0f, 0x29, 0x72, 0x50, /* movaps [rdx+ 80],xmm6 */
0x0f, 0x29, 0x7a, 0x60, /* movaps [rdx+ 96],xmm7 */
0x44, 0x0f, 0x29, 0x42, 0x70, /* movaps [rdx+112],xmm8 */
0x48, 0x83, 0xc2, 0x70, /* add rdx,112 */
0x44, 0x0f, 0x29, 0x4a, 0x10, /* movaps [rdx+ 16],xmm9 */
0x44, 0x0f, 0x29, 0x52, 0x20, /* movaps [rdx+ 32],xmm10 */
0x44, 0x0f, 0x29, 0x5a, 0x30, /* movaps [rdx+ 48],xmm11 */
0x44, 0x0f, 0x29, 0x62, 0x40, /* movaps [rdx+ 64],xmm12 */
0x44, 0x0f, 0x29, 0x6a, 0x50, /* movaps [rdx+ 80],xmm13 */
0x44, 0x0f, 0x29, 0x72, 0x60, /* movaps [rdx+ 96],xmm14 */
0x44, 0x0f, 0x29, 0x7a, 0x70, /* movaps [rdx+112],xmm15 */
#endif
0x48, 0x8b, 0x69, 0x08, /* mov rbp,[rcx+ 8] */
0x48, 0x8b, 0x71, 0x10, /* mov rsi,[rcx+16] */
0x48, 0x8b, 0x79, 0x18, /* mov rdi,[rcx+24] */
0x48, 0x8b, 0x59, 0x20, /* mov rbx,[rcx+32] */
0x4c, 0x8b, 0x61, 0x28, /* mov r12,[rcx+40] */
0x4c, 0x8b, 0x69, 0x30, /* mov r13,[rcx+48] */
0x4c, 0x8b, 0x71, 0x38, /* mov r14,[rcx+56] */
0x4c, 0x8b, 0x79, 0x40, /* mov r15,[rcx+64] */
#if !defined(LIBCO_NO_SSE)
0x0f, 0x28, 0x71, 0x50, /* movaps xmm6, [rcx+ 80] */
0x0f, 0x28, 0x79, 0x60, /* movaps xmm7, [rcx+ 96] */
0x44, 0x0f, 0x28, 0x41, 0x70, /* movaps xmm8, [rcx+112] */
0x48, 0x83, 0xc1, 0x70, /* add rcx,112 */
0x44, 0x0f, 0x28, 0x49, 0x10, /* movaps xmm9, [rcx+ 16] */
0x44, 0x0f, 0x28, 0x51, 0x20, /* movaps xmm10,[rcx+ 32] */
0x44, 0x0f, 0x28, 0x59, 0x30, /* movaps xmm11,[rcx+ 48] */
0x44, 0x0f, 0x28, 0x61, 0x40, /* movaps xmm12,[rcx+ 64] */
0x44, 0x0f, 0x28, 0x69, 0x50, /* movaps xmm13,[rcx+ 80] */
0x44, 0x0f, 0x28, 0x71, 0x60, /* movaps xmm14,[rcx+ 96] */
0x44, 0x0f, 0x28, 0x79, 0x70, /* movaps xmm15,[rcx+112] */
#endif
0xff, 0xe0, /* jmp rax */
};
#include <windows.h>
@ -146,6 +151,15 @@ cothread_t co_create(unsigned int size, void (*entrypoint)(void))
size += 512; /* allocate additional space for storage */
size &= ~15; /* align stack to 16-byte boundary */
#ifdef __GENODE__
if((handle = (cothread_t)genode_alloc_secondary_stack(size)))
{
long long *p = (long long*)((char*)handle); /* OS returns top of stack */
*--p = (long long)crash; /* crash if entrypoint returns */
*--p = (long long)entrypoint; /* start of function */
*(long long*)handle = (long long)p; /* stack pointer */
}
#else
if((handle = (cothread_t)malloc(size)))
{
long long *p = (long long*)((char*)handle + size); /* seek to top of stack */
@ -153,13 +167,18 @@ cothread_t co_create(unsigned int size, void (*entrypoint)(void))
*--p = (long long)entrypoint; /* start of function */
*(long long*)handle = (long long)p; /* stack pointer */
}
#endif
return handle;
}
void co_delete(cothread_t handle)
{
#ifdef __GENODE__
genode_free_secondary_stack(handle);
#else
free(handle);
#endif
}
#ifndef CO_USE_INLINE_ASM

View File

@ -104,4 +104,3 @@ void co_switch(cothread_t handle)
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,29 @@
/*
libco.genode_secondary_stack (2018-09-15)
author: Emery Hemingway
license: public domain
*/
/* Genode include */
#include <base/thread.h>
/* Libco include */
#include <libco.h>
extern "C"
void *genode_alloc_secondary_stack(unsigned long stack_size)
{
try {
return Genode::Thread::myself()->alloc_secondary_stack("libco", stack_size); }
catch (...) {
Genode::error("libco: failed to allocate ", stack_size, " byte secondary stack");
return nullptr;
}
}
extern "C"
void genode_free_secondary_stack(void *stack)
{
Genode::Thread::myself()->free_secondary_stack(stack);
}

View File

@ -4,6 +4,11 @@
license: public domain
*/
#ifdef __GENODE__
void *genode_alloc_secondary_stack(unsigned long stack_size);
void genode_free_secondary_stack(void *stack);
#endif
#if defined _MSC_VER
#include <Windows.h>
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
@ -24,6 +29,10 @@
#include "ppc.c"
#elif defined(__aarch64__)
#include "aarch64.c"
#elif defined(PS2)
#include "ps2.c"
#elif defined(PSP)
#include "psp1.c"
#elif defined VITA
#include "scefiber.c"
#elif defined(__ARM_EABI__) || defined(__arm__)

View File

@ -0,0 +1,66 @@
#define LIBCO_C
#include "libco.h"
#include <stdlib.h>
#include <stdint.h>
#include <kernel.h>
/* 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 int32_t active_thread_id = -1;
extern void *_gp;
cothread_t co_active()
{
active_thread_id = GetThreadId();
return &active_thread_id;
}
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));
ee_thread_t thread;
// u8 threadStack[size/8] __attribute__ ((aligned(16)));
void *threadStack = (void *)malloc(size);
if ( threadStack== NULL)
{
printf("libco: ERROR: creating threadStack\n");
return(-1);
}
thread.stack_size = size;
thread.gp_reg = &_gp;
thread.func = (void *)entrypoint;
thread.stack = threadStack;
thread.option = 0;
thread.initial_priority = 1;
int32_t new_thread_id = CreateThread(&thread);
if (new_thread_id < 0)
printf("libco: ERROR: creating thread\n");
StartThread(new_thread_id, NULL);
*(uint32_t *)handle = new_thread_id;
return handle;
}
void co_delete(cothread_t handle)
{
TerminateThread(*(uint32_t *)handle);
DeleteThread(*(uint32_t *)handle);
free(handle);
}
void co_switch(cothread_t handle)
{
WakeupThread(*(uint32_t *)handle);
/* Sleep the currently active thread so the new thread can start */
SleepThread();
}

View File

@ -0,0 +1,55 @@
.globl .co_swap_asm
.globl co_swap_asm
.type .co_swap_asm, @function
.type co_swap_asm, @function
.co_swap_asm:
co_swap_asm:
mfcr 8
std 1,40(4)
mflr 9
std 14,72(4)
std 15,80(4)
std 16,88(4)
std 17,96(4)
std 18,104(4)
std 19,112(4)
std 20,120(4)
std 21,128(4)
std 22,136(4)
std 23,144(4)
std 24,152(4)
std 25,160(4)
std 26,168(4)
std 27,176(4)
std 28,184(4)
std 29,192(4)
std 30,200(4)
std 31,208(4)
std 9,32(4)
ld 7,32(3)
ld 1,40(3)
bl swap
trap
swap: stw 8,48(4)
lwz 6,48(3)
mtctr 7
ld 14,72(3)
ld 15,80(3)
ld 16,88(3)
ld 17,96(3)
ld 18,104(3)
ld 19,112(3)
ld 20,120(3)
ld 21,128(3)
ld 22,136(3)
ld 23,144(3)
ld 24,152(3)
ld 25,160(3)
ld 26,168(3)
ld 27,176(3)
ld 28,184(3)
ld 29,192(3)
ld 30,200(3)
ld 31,208(3)
mtcr 6
bctr

View File

@ -0,0 +1,41 @@
#define LIBCO_C
#include "libco.h"
#include <stdlib.h>
#include <pspthreadman.h>
typedef void (*entrypoint_t)(void);
cothread_t co_active()
{
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))
{
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)
{
SceUID id = (SceUID) handle;
sceKernelTerminateDeleteThread(id);
}
void co_switch(cothread_t handle)
{
SceUID id = (SceUID) handle;
sceKernelWakeupThread(id);
/* Sleep the currently active thread so the new thread can start */
sceKernelSleepThread();
}

View File

@ -0,0 +1,113 @@
/*
libco.arm (2015-06-18)
license: public domain
*/
#define LIBCO_C
#include "libco.h"
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <psp2/kernel/sysmem.h>
#include <stdio.h>
#include <string.h>
#define FOUR_KB_ALIGN(x) align(x, 12)
#define MB_ALIGN(x) align(x, 20)
#ifdef __cplusplus
extern "C" {
#endif
static inline int align(int x, int n)
{
return (((x >> n) + 1) << n);
}
static thread_local unsigned long co_active_buffer[64];
static thread_local cothread_t co_active_handle = 0;
static void(*co_swap)(cothread_t, cothread_t) = 0;
static int block;
static uint32_t co_swap_function[] = {
0xe8a16ff0, /* stmia r1!, {r4-r11,sp,lr} */
0xe8b0aff0, /* ldmia r0!, {r4-r11,sp,pc} */
0xe12fff1e, /* bx lr */
};
static void co_init(void)
{
int ret;
void *base;
block = sceKernelAllocMemBlockForVM("libco",
MB_ALIGN(FOUR_KB_ALIGN(sizeof co_swap_function)));
if (block < 0)
return;
/* get base address */
ret = sceKernelGetMemBlockBase(block, &base);
if (ret < 0)
return;
/* set domain to be writable by user */
ret = sceKernelOpenVMDomain();
if (ret < 0)
return;
memcpy(base, co_swap_function, sizeof co_swap_function);
/* set domain back to read-only */
ret = sceKernelCloseVMDomain();
if (ret < 0)
return;
/* flush icache */
ret = sceKernelSyncVMDomain(block, base,
MB_ALIGN(FOUR_KB_ALIGN(sizeof co_swap_function)));
if (ret < 0)
return;
co_swap = (void(*)(cothread_t, cothread_t))base;
}
cothread_t co_active(void)
{
if (!co_active_handle) co_active_handle = &co_active_buffer;
return co_active_handle;
}
cothread_t co_create(unsigned int size, void(*entrypoint)(void))
{
unsigned long* handle = 0;
if (!co_swap)
co_init();
if (!co_active_handle) co_active_handle = &co_active_buffer;
size += 256;
size &= ~15;
if ((handle = (unsigned long*)malloc(size)))
{
unsigned long* p = (unsigned long*)((unsigned char*)handle + size);
handle[8] = (unsigned long)p;
handle[9] = (unsigned long)entrypoint;
}
return handle;
}
void co_delete(cothread_t handle)
{
free(handle);
sceKernelFreeMemBlock(block);
}
void co_switch(cothread_t handle)
{
cothread_t co_previous_handle = co_active_handle;
co_swap(co_active_handle = handle, co_previous_handle);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,96 @@
/*
libco.win (2016-09-06)
authors: frangarcj
license: public domain
*/
#define LIBCO_C
#include <libco.h>
#include <stdlib.h>
#include <psp2/sysmodule.h>
#ifdef __cplusplus
extern "C" {
#endif
static thread_local cothread_t co_active_ = 0;
typedef struct SceFiber {
char reserved[128];
} SceFiber __attribute__( ( aligned ( 8 ) ) ) ;
int32_t _sceFiberInitializeImpl(SceFiber* fiber, char* name, void* entry, uint32_t argOnInitialize, void* addrContext, int32_t sizeContext, void* params);
int32_t sceFiberFinalize(SceFiber* fiber);
int32_t sceFiberRun(SceFiber* fiber, uint32_t argOnRunTo, uint32_t* argOnRun);
int32_t sceFiberSwitch(SceFiber* fiber, uint32_t argOnRunTo, uint32_t* argOnRun);
int32_t sceFiberReturnToThread(uint32_t argOnReturn, uint32_t* argOnRun);
static void co_thunk(uint32_t argOnInitialize, uint32_t argOnRun)
{
((void (*)(void))argOnInitialize)();
}
cothread_t co_active(void)
{
if(!co_active_)
{
sceSysmoduleLoadModule(SCE_SYSMODULE_FIBER);
co_active_ = (cothread_t)1;
}
return co_active_;
}
cothread_t co_create(unsigned int heapsize, void (*coentry)(void))
{
SceFiber* tailFiber = malloc(sizeof(SceFiber));
char * m_contextBuffer = malloc(sizeof(char)*heapsize);
if(!co_active_)
{
sceSysmoduleLoadModule(SCE_SYSMODULE_FIBER);
co_active_ = (cothread_t)1;
}
//_sceFiberInitializeImpl
int ret = _sceFiberInitializeImpl(tailFiber, "tailFiber", co_thunk, (uint32_t)coentry, (void*) m_contextBuffer, heapsize, NULL);
if(ret==0){
return (cothread_t)tailFiber;
}else{
return (cothread_t)ret;
}
}
void co_delete(cothread_t cothread)
{
if(cothread == (cothread_t)1){
return;
}
sceFiberFinalize((SceFiber*)cothread);
}
void co_switch(cothread_t cothread)
{
uint32_t argOnReturn = 0;
if(cothread == (cothread_t)1){
co_active_ = cothread;
sceFiberReturnToThread(0, NULL);
}else{
SceFiber* theFiber = (SceFiber*)cothread;
if(co_active_ == (cothread_t)1){
co_active_ = cothread;
sceFiberRun(theFiber, 0, &argOnReturn);
}else{
co_active_ = cothread;
sceFiberSwitch(theFiber, 0, &argOnReturn);
}
}
}
#ifdef __cplusplus
}
#endif