mirror of https://github.com/bsnes-emu/bsnes.git
libco: Remove to make space for libco subtree
This commit is contained in:
parent
882e5d292f
commit
c5b39e2dfc
109
libco/aarch64.c
109
libco/aarch64.c
|
@ -1,109 +0,0 @@
|
|||
#define LIBCO_C
|
||||
#include "libco.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#ifdef LIBCO_MPROTECT
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
#ifdef LIBCO_MPROTECT
|
||||
alignas(4096)
|
||||
#else
|
||||
section(text)
|
||||
#endif
|
||||
static const uint32_t co_swap_function[1024] = {
|
||||
0xa9002428, /* stp x8,x9,[x1] */
|
||||
0xa9012c2a, /* stp x10,x11,[x1,#16] */
|
||||
0xa902342c, /* stp x12,x13,[x1,#32] */
|
||||
0xa9033c2e, /* stp x14,x15,[x1,#48] */
|
||||
0xf9002433, /* str x19,[x1,#72] */
|
||||
0xa9055434, /* stp x20,x21,[x1,#80] */
|
||||
0xa9065c36, /* stp x22,x23,[x1,#96] */
|
||||
0xa9076438, /* stp x24,x25,[x1,#112] */
|
||||
0xa9086c3a, /* stp x26,x27,[x1,#128] */
|
||||
0xa909743c, /* stp x28,x29,[x1,#144] */
|
||||
0x910003f0, /* mov x16,sp */
|
||||
0xa90a7830, /* stp x16,x30,[x1,#160] */
|
||||
|
||||
0xa9402408, /* ldp x8,x9,[x0] */
|
||||
0xa9412c0a, /* ldp x10,x11,[x0,#16] */
|
||||
0xa942340c, /* ldp x12,x13,[x0,#32] */
|
||||
0xa9433c0e, /* ldp x14,x15,[x0,#48] */
|
||||
0xf9402413, /* ldr x19,[x0,#72] */
|
||||
0xa9455414, /* ldp x20,x21,[x0,#80] */
|
||||
0xa9465c16, /* ldp x22,x23,[x0,#96] */
|
||||
0xa9476418, /* ldp x24,x25,[x0,#112] */
|
||||
0xa9486c1a, /* ldp x26,x27,[x0,#128] */
|
||||
0xa949741c, /* ldp x28,x29,[x0,#144] */
|
||||
0xa94a4410, /* ldp x16,x17,[x0,#160] */
|
||||
0x9100021f, /* mov sp,x16 */
|
||||
0xd61f0220, /* br x17 */
|
||||
};
|
||||
|
||||
static void co_init() {
|
||||
#ifdef LIBCO_MPROTECT
|
||||
unsigned long addr = (unsigned long)co_swap_function;
|
||||
unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE));
|
||||
unsigned long size = (addr - base) + sizeof co_swap_function;
|
||||
mprotect((void*)base, size, PROT_READ | PROT_EXEC);
|
||||
#endif
|
||||
}
|
||||
|
||||
cothread_t co_active() {
|
||||
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
||||
return co_active_handle;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void)) {
|
||||
unsigned long* handle;
|
||||
if(!co_swap) {
|
||||
co_init();
|
||||
co_swap = (void (*)(cothread_t, cothread_t))co_swap_function;
|
||||
}
|
||||
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
||||
|
||||
if(handle = (unsigned long*)memory) {
|
||||
unsigned int offset = (size & ~15);
|
||||
unsigned long* p = (unsigned long*)((unsigned char*)handle + offset);
|
||||
handle[19] = (unsigned long)p; /* x29 (frame pointer) */
|
||||
handle[20] = (unsigned long)p; /* x30 (stack pointer) */
|
||||
handle[21] = (unsigned long)entrypoint; /* x31 (link register) */
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
||||
void* memory = malloc(size);
|
||||
if(!memory) return (cothread_t)0;
|
||||
return co_derive(memory, size, entrypoint);
|
||||
}
|
||||
|
||||
void co_delete(cothread_t handle) {
|
||||
free(handle);
|
||||
}
|
||||
|
||||
void co_switch(cothread_t handle) {
|
||||
cothread_t co_previous_handle = co_active_handle;
|
||||
co_swap(co_active_handle = handle, co_previous_handle);
|
||||
}
|
||||
|
||||
int co_serializable() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
165
libco/amd64.c
165
libco/amd64.c
|
@ -1,165 +0,0 @@
|
|||
#define LIBCO_C
|
||||
#include "libco.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static thread_local long long co_active_buffer[64];
|
||||
static thread_local cothread_t co_active_handle = 0;
|
||||
static void (*co_swap)(cothread_t, cothread_t) = 0;
|
||||
|
||||
#ifdef LIBCO_MPROTECT
|
||||
alignas(4096)
|
||||
#else
|
||||
section(text)
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
/* ABI: Win64 */
|
||||
static const unsigned char co_swap_function[4096] = {
|
||||
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>
|
||||
|
||||
static void co_init() {
|
||||
#ifdef LIBCO_MPROTECT
|
||||
DWORD old_privileges;
|
||||
VirtualProtect((void*)co_swap_function, sizeof co_swap_function, PAGE_EXECUTE_READ, &old_privileges);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
/* ABI: SystemV */
|
||||
static const unsigned char co_swap_function[4096] = {
|
||||
0x48, 0x89, 0x26, /* mov [rsi],rsp */
|
||||
0x48, 0x8b, 0x27, /* mov rsp,[rdi] */
|
||||
0x58, /* pop rax */
|
||||
0x48, 0x89, 0x6e, 0x08, /* mov [rsi+ 8],rbp */
|
||||
0x48, 0x89, 0x5e, 0x10, /* mov [rsi+16],rbx */
|
||||
0x4c, 0x89, 0x66, 0x18, /* mov [rsi+24],r12 */
|
||||
0x4c, 0x89, 0x6e, 0x20, /* mov [rsi+32],r13 */
|
||||
0x4c, 0x89, 0x76, 0x28, /* mov [rsi+40],r14 */
|
||||
0x4c, 0x89, 0x7e, 0x30, /* mov [rsi+48],r15 */
|
||||
0x48, 0x8b, 0x6f, 0x08, /* mov rbp,[rdi+ 8] */
|
||||
0x48, 0x8b, 0x5f, 0x10, /* mov rbx,[rdi+16] */
|
||||
0x4c, 0x8b, 0x67, 0x18, /* mov r12,[rdi+24] */
|
||||
0x4c, 0x8b, 0x6f, 0x20, /* mov r13,[rdi+32] */
|
||||
0x4c, 0x8b, 0x77, 0x28, /* mov r14,[rdi+40] */
|
||||
0x4c, 0x8b, 0x7f, 0x30, /* mov r15,[rdi+48] */
|
||||
0xff, 0xe0, /* jmp rax */
|
||||
};
|
||||
|
||||
#ifdef LIBCO_MPROTECT
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
static void co_init() {
|
||||
#ifdef LIBCO_MPROTECT
|
||||
unsigned long long addr = (unsigned long long)co_swap_function;
|
||||
unsigned long long base = addr - (addr % sysconf(_SC_PAGESIZE));
|
||||
unsigned long long size = (addr - base) + sizeof co_swap_function;
|
||||
mprotect((void*)base, size, PROT_READ | PROT_EXEC);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void crash() {
|
||||
assert(0); /* called only if cothread_t entrypoint returns */
|
||||
}
|
||||
|
||||
cothread_t co_active() {
|
||||
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
||||
return co_active_handle;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void)) {
|
||||
cothread_t handle;
|
||||
if(!co_swap) {
|
||||
co_init();
|
||||
co_swap = (void (*)(cothread_t, cothread_t))co_swap_function;
|
||||
}
|
||||
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
||||
|
||||
if(handle = (cothread_t)memory) {
|
||||
unsigned int offset = (size & ~15) - 32;
|
||||
long long *p = (long long*)((char*)handle + offset); /* seek to 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 */
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
||||
void* memory = malloc(size);
|
||||
if(!memory) return (cothread_t)0;
|
||||
return co_derive(memory, size, entrypoint);
|
||||
}
|
||||
|
||||
void co_delete(cothread_t handle) {
|
||||
free(handle);
|
||||
}
|
||||
|
||||
void co_switch(cothread_t handle) {
|
||||
register cothread_t co_previous_handle = co_active_handle;
|
||||
co_swap(co_active_handle = handle, co_previous_handle);
|
||||
}
|
||||
|
||||
int co_serializable() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
84
libco/arm.c
84
libco/arm.c
|
@ -1,84 +0,0 @@
|
|||
#define LIBCO_C
|
||||
#include "libco.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef LIBCO_MPROTECT
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
#ifdef LIBCO_MPROTECT
|
||||
alignas(4096)
|
||||
#else
|
||||
section(text)
|
||||
#endif
|
||||
static const unsigned long co_swap_function[1024] = {
|
||||
0xe8a16ff0, /* stmia r1!, {r4-r11,sp,lr} */
|
||||
0xe8b0aff0, /* ldmia r0!, {r4-r11,sp,pc} */
|
||||
0xe12fff1e, /* bx lr */
|
||||
};
|
||||
|
||||
static void co_init() {
|
||||
#ifdef LIBCO_MPROTECT
|
||||
unsigned long addr = (unsigned long)co_swap_function;
|
||||
unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE));
|
||||
unsigned long size = (addr - base) + sizeof co_swap_function;
|
||||
mprotect((void*)base, size, PROT_READ | PROT_EXEC);
|
||||
#endif
|
||||
}
|
||||
|
||||
cothread_t co_active() {
|
||||
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
||||
return co_active_handle;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void)) {
|
||||
unsigned long* handle;
|
||||
if(!co_swap) {
|
||||
co_init();
|
||||
co_swap = (void (*)(cothread_t, cothread_t))co_swap_function;
|
||||
}
|
||||
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
||||
|
||||
if(handle = (unsigned long*)memory) {
|
||||
unsigned int offset = (size & ~15);
|
||||
unsigned long* p = (unsigned long*)((unsigned char*)handle + offset);
|
||||
handle[8] = (unsigned long)p;
|
||||
handle[9] = (unsigned long)entrypoint;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
||||
void* memory = malloc(size);
|
||||
if(!memory) return (cothread_t)0;
|
||||
return co_derive(memory, size, entrypoint);
|
||||
}
|
||||
|
||||
void co_delete(cothread_t handle) {
|
||||
free(handle);
|
||||
}
|
||||
|
||||
void co_switch(cothread_t handle) {
|
||||
cothread_t co_previous_handle = co_active_handle;
|
||||
co_swap(co_active_handle = handle, co_previous_handle);
|
||||
}
|
||||
|
||||
int co_serializable() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,12 +0,0 @@
|
|||
body {
|
||||
background: #333;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
code {
|
||||
background: #444;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #aaf;
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
<link href="style.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<b>Supported targets:</b><br/><br/>
|
||||
|
||||
Note that supported targets are only those that have been tested and confirmed
|
||||
working. It is quite possible that libco will work on more processors, compilers
|
||||
and operating systems than those listed below.
|
||||
<hr/>
|
||||
|
||||
<b>libco.x86</b><br/>
|
||||
Overhead: ~5x<br/>
|
||||
Supported processor(s): 32-bit x86<br/>
|
||||
Supported compiler(s): any<br/>
|
||||
Supported operating system(s):<ul>
|
||||
<li>Windows</li>
|
||||
<li>Mac OS X</li>
|
||||
<li>Linux</li>
|
||||
<li>BSD</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
|
||||
<b>libco.amd64</b><br/>
|
||||
Overhead: ~10x (Windows), ~6x (all other platforms)<br/>
|
||||
Supported processor(s): 64-bit amd64<br/>
|
||||
Supported compiler(s): any<br/>
|
||||
Supported operating system(s):<ul>
|
||||
<li>Windows</li>
|
||||
<li>Mac OS X</li>
|
||||
<li>Linux</li>
|
||||
<li>BSD</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
|
||||
<b>libco.ppc</b><br/>
|
||||
Overhead: ~20x<br/>
|
||||
Supported processor(s): 32-bit PowerPC, 64-bit PowerPC<br/>
|
||||
Supported compiler(s): GNU GCC<br/>
|
||||
Supported operating system(s):<ul>
|
||||
</ul>
|
||||
<li>Mac OS X</li>
|
||||
<li>Linux</li>
|
||||
<li>BSD</li>
|
||||
<li>Playstation 3</li>
|
||||
</ul>
|
||||
<br/>
|
||||
|
||||
Note: this module contains compiler flags to enable/disable FPU and Altivec
|
||||
support.
|
||||
|
||||
<hr/>
|
||||
|
||||
<b>libco.fiber</b><br/>
|
||||
Overhead: ~15x<br/>
|
||||
Supported processor(s): Processor independent<br/>
|
||||
Supported compiler(s): any<br/>
|
||||
Supported operating system(s):<ul>
|
||||
<li>Windows</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
|
||||
<b>libco.sjlj</b><br/>
|
||||
Overhead: ~30x<br/>
|
||||
Supported processor(s): Processor independent<br/>
|
||||
Supported compiler(s): any<br/>
|
||||
Supported operating system(s):<ul>
|
||||
<li>Mac OS X</li>
|
||||
<li>Linux</li>
|
||||
<li>BSD</li>
|
||||
<li>Solaris</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
|
||||
<b>libco.ucontext</b><br/>
|
||||
Overhead: <b><font color="#ff0000">~300x</font></b><br/>
|
||||
Supported processor(s): Processor independent<br/>
|
||||
Supported compiler(s): any<br/>
|
||||
Supported operating system(s):<ul>
|
||||
<li>Linux</li>
|
||||
<li>BSD</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,108 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
<link href="style.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<b>License:</b><br/><br/>
|
||||
libco is released under the ISC license.
|
||||
<hr/>
|
||||
|
||||
<b>Foreword:</b><br/><br/>
|
||||
libco is a cross-platform, permissively licensed implementation of
|
||||
cooperative-multithreading; a feature that is sorely lacking from the ISO C/C++
|
||||
standard.<br/>
|
||||
The library is designed for maximum speed and portability, and not for safety or
|
||||
features. If safety or extra functionality is desired, a wrapper API can easily
|
||||
be written to encapsulate all library functions.<br/>
|
||||
Behavior of executing operations that are listed as not permitted below result
|
||||
in undefined behavior. They may work anyway, they may cause undesired / unknown
|
||||
behavior, or they may crash the program entirely.<br/>
|
||||
The goal of this library was to simplify the base API as much as possible,
|
||||
implementing only that which cannot be implemented using pure C. Additional
|
||||
functionality after this would only complicate ports of this library to new
|
||||
platforms.
|
||||
<hr/>
|
||||
|
||||
<b>Porting:</b><br/><br/>
|
||||
This document is included as a reference for porting libco. Please submit any
|
||||
ports you create to me, so that libco can become more useful. Please note that
|
||||
since libco is permissively licensed, you must submit your code as a work of the
|
||||
public domain in order for it to be included in the official distribution.
|
||||
Full credit will be given in the source code of the official release. Please
|
||||
do not bother submitting code to me under any other license -- including GPL,
|
||||
LGPL, BSD or CC -- I am not interested in creating a library with multiple
|
||||
different licenses depending on which targets are used.
|
||||
<hr/>
|
||||
|
||||
<b>Synopsis:</b><br/><br/>
|
||||
<code>
|
||||
typedef void* cothread_t;<br/>
|
||||
<br/>
|
||||
cothread_t co_active();<br/>
|
||||
cothread_t co_create(unsigned int heapsize, void (*coentry)(void));<br/>
|
||||
void co_delete(cothread_t cothread);<br/>
|
||||
void co_switch(cothread_t cothread);<br/>
|
||||
</code>
|
||||
<hr/>
|
||||
|
||||
<b>Usage:</b>
|
||||
<hr/>
|
||||
|
||||
<code>typedef void* cothread_t;</code><br/><br/>
|
||||
Handle to cothread.<br/>
|
||||
Handle must be of type void*.<br/>
|
||||
A value of null (0) indicates an uninitialized or invalid
|
||||
handle, whereas a non-zero value indicates a valid handle.
|
||||
<hr/>
|
||||
|
||||
<code>cothread_t co_active();</code><br/><br/>
|
||||
Return handle to current cothread. Always returns a valid handle, even when
|
||||
called from the main program thread.
|
||||
<hr/>
|
||||
|
||||
<code>cothread_t co_derive(void* memory, unsigned int heapsize, void (*coentry)(void));</code><br/><br/>
|
||||
Initializes new cothread.</br>
|
||||
This function is identical to co_create, only it attempts to use the provided
|
||||
memory instead of allocating new memory on the heap. Please note that certain
|
||||
implementations (currently only Windows Fibers) cannot be created using existing
|
||||
memory, and as such, this function will fail.
|
||||
<hr/>
|
||||
|
||||
<code>cothread_t co_create(unsigned int heapsize, void (*coentry)(void));</code><br/><br/>
|
||||
Create new cothread.<br/>
|
||||
Heapsize is the amount of memory allocated for the cothread stack, specified
|
||||
in bytes. This is unfortunately impossible to make fully portable. It is
|
||||
recommended to specify sizes using `n * sizeof(void*)'. It is better to err
|
||||
on the side of caution and allocate more memory than will be needed to ensure
|
||||
compatibility with other platforms, within reason. A typical heapsize for a
|
||||
32-bit architecture is ~1MB.<br/>
|
||||
When the new cothread is first called, program execution jumps to coentry.
|
||||
This function does not take any arguments, due to portability issues with
|
||||
passing function arguments. However, arguments can be simulated by the use
|
||||
of global variables, which can be set before the first call to each cothread.<br/>
|
||||
coentry() must not return, and should end with an appropriate co_switch()
|
||||
statement. Behavior is undefined if entry point returns normally.<br/>
|
||||
Library is responsible for allocating cothread stack memory, to free
|
||||
the user from needing to allocate special memory capable of being used
|
||||
as program stack memory on platforms where this is required.<br/>
|
||||
User is always responsible for deleting cothreads with co_delete().<br/>
|
||||
Return value of null (0) indicates cothread creation failed.
|
||||
<hr/>
|
||||
|
||||
<code>void co_delete(cothread_t cothread);</code><br/><br/>
|
||||
Delete specified cothread.<br/>
|
||||
Null (0) or invalid cothread handle is not allowed.<br/>
|
||||
Passing handle of active cothread to this function is not allowed.<br/>
|
||||
Passing handle of primary cothread is not allowed.
|
||||
<hr/>
|
||||
|
||||
<code>void co_switch(cothread_t cothread);</code><br/><br/>
|
||||
Switch to specified cothread.<br/>
|
||||
Null (0) or invalid cothread handle is not allowed.<br/>
|
||||
Passing handle of active cothread to this function is not allowed.
|
||||
<hr/>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,55 +0,0 @@
|
|||
#define LIBCO_C
|
||||
#include "libco.h"
|
||||
#include "settings.h"
|
||||
|
||||
#define WINVER 0x0400
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static thread_local cothread_t co_active_ = 0;
|
||||
|
||||
static void __stdcall co_thunk(void* coentry) {
|
||||
((void (*)(void))coentry)();
|
||||
}
|
||||
|
||||
cothread_t co_active() {
|
||||
if(!co_active_) {
|
||||
ConvertThreadToFiber(0);
|
||||
co_active_ = GetCurrentFiber();
|
||||
}
|
||||
return co_active_;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int heapsize, void (*coentry)(void)) {
|
||||
//Windows fibers do not allow users to supply their own memory
|
||||
return (cothread_t)0;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) {
|
||||
if(!co_active_) {
|
||||
ConvertThreadToFiber(0);
|
||||
co_active_ = GetCurrentFiber();
|
||||
}
|
||||
return (cothread_t)CreateFiber(heapsize, co_thunk, (void*)coentry);
|
||||
}
|
||||
|
||||
void co_delete(cothread_t cothread) {
|
||||
DeleteFiber(cothread);
|
||||
}
|
||||
|
||||
void co_switch(cothread_t cothread) {
|
||||
co_active_ = cothread;
|
||||
SwitchToFiber(cothread);
|
||||
}
|
||||
|
||||
int co_serializable() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,37 +0,0 @@
|
|||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wparentheses"
|
||||
|
||||
/* placing code in section(text) does not mark it executable with Clang. */
|
||||
#undef LIBCO_MPROTECT
|
||||
#define LIBCO_MPROTECT
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#if defined(__i386__)
|
||||
#include "x86.c"
|
||||
#elif defined(__amd64__)
|
||||
#include "amd64.c"
|
||||
#elif defined(__arm__)
|
||||
#include "arm.c"
|
||||
#elif defined(__aarch64__)
|
||||
#include "aarch64.c"
|
||||
#elif defined(__powerpc64__) && defined(_CALL_ELF) && _CALL_ELF == 2
|
||||
#include "ppc64v2.c"
|
||||
#elif defined(_ARCH_PPC) && !defined(__LITTLE_ENDIAN__)
|
||||
#include "ppc.c"
|
||||
#elif defined(_WIN32)
|
||||
#include "fiber.c"
|
||||
#else
|
||||
#include "sjlj.c"
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#if defined(_M_IX86)
|
||||
#include "x86.c"
|
||||
#elif defined(_M_AMD64)
|
||||
#include "amd64.c"
|
||||
#else
|
||||
#include "fiber.c"
|
||||
#endif
|
||||
#else
|
||||
#error "libco: unsupported processor, compiler or operating system"
|
||||
#endif
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
libco v20 (2019-10-16)
|
||||
author: byuu
|
||||
license: ISC
|
||||
*/
|
||||
|
||||
#ifndef LIBCO_H
|
||||
#define LIBCO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* cothread_t;
|
||||
|
||||
cothread_t co_active();
|
||||
cothread_t co_derive(void*, unsigned int, void (*)(void));
|
||||
cothread_t co_create(unsigned int, void (*)(void));
|
||||
void co_delete(cothread_t);
|
||||
void co_switch(cothread_t);
|
||||
int co_serializable();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ifndef LIBCO_H */
|
||||
#endif
|
431
libco/ppc.c
431
libco/ppc.c
|
@ -1,431 +0,0 @@
|
|||
/* ppc64le (ELFv2) is not currently supported */
|
||||
|
||||
#define LIBCO_C
|
||||
#include "libco.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef LIBCO_MPROTECT
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
/* state format (offsets in 32-bit words)
|
||||
|
||||
+0 pointer to swap code
|
||||
rest of function descriptor for entry function
|
||||
+8 PC
|
||||
+10 SP
|
||||
special registers
|
||||
GPRs
|
||||
FPRs
|
||||
VRs
|
||||
stack
|
||||
*/
|
||||
|
||||
enum { state_size = 1024 };
|
||||
enum { above_stack = 2048 };
|
||||
enum { stack_align = 256 };
|
||||
|
||||
static thread_local cothread_t co_active_handle = 0;
|
||||
|
||||
/* determine environment */
|
||||
|
||||
#define LIBCO_PPC64 (_ARCH_PPC64 || __PPC64__ || __ppc64__ || __powerpc64__)
|
||||
|
||||
/* whether function calls are indirect through a descriptor, or are directly to function */
|
||||
#ifndef LIBCO_PPCDESC
|
||||
#if !_CALL_SYSV && (_CALL_AIX || _CALL_AIXDESC || (LIBCO_PPC64 && (!defined(_CALL_ELF) || _CALL_ELF == 1)))
|
||||
#define LIBCO_PPCDESC 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LIBCO_MPROTECT
|
||||
alignas(4096)
|
||||
#else
|
||||
section(text)
|
||||
#endif
|
||||
static const uint32_t libco_ppc_code[1024] = {
|
||||
#if LIBCO_PPC64
|
||||
0x7d000026, /* mfcr r8 */
|
||||
0xf8240028, /* std r1,40(r4) */
|
||||
0x7d2802a6, /* mflr r9 */
|
||||
0xf9c40048, /* std r14,72(r4) */
|
||||
0xf9e40050, /* std r15,80(r4) */
|
||||
0xfa040058, /* std r16,88(r4) */
|
||||
0xfa240060, /* std r17,96(r4) */
|
||||
0xfa440068, /* std r18,104(r4) */
|
||||
0xfa640070, /* std r19,112(r4) */
|
||||
0xfa840078, /* std r20,120(r4) */
|
||||
0xfaa40080, /* std r21,128(r4) */
|
||||
0xfac40088, /* std r22,136(r4) */
|
||||
0xfae40090, /* std r23,144(r4) */
|
||||
0xfb040098, /* std r24,152(r4) */
|
||||
0xfb2400a0, /* std r25,160(r4) */
|
||||
0xfb4400a8, /* std r26,168(r4) */
|
||||
0xfb6400b0, /* std r27,176(r4) */
|
||||
0xfb8400b8, /* std r28,184(r4) */
|
||||
0xfba400c0, /* std r29,192(r4) */
|
||||
0xfbc400c8, /* std r30,200(r4) */
|
||||
0xfbe400d0, /* std r31,208(r4) */
|
||||
0xf9240020, /* std r9,32(r4) */
|
||||
0xe8e30020, /* ld r7,32(r3) */
|
||||
0xe8230028, /* ld r1,40(r3) */
|
||||
0x48000009, /* bl 1 */
|
||||
0x7fe00008, /* trap */
|
||||
0x91040030, /*1:stw r8,48(r4) */
|
||||
0x80c30030, /* lwz r6,48(r3) */
|
||||
0x7ce903a6, /* mtctr r7 */
|
||||
0xe9c30048, /* ld r14,72(r3) */
|
||||
0xe9e30050, /* ld r15,80(r3) */
|
||||
0xea030058, /* ld r16,88(r3) */
|
||||
0xea230060, /* ld r17,96(r3) */
|
||||
0xea430068, /* ld r18,104(r3) */
|
||||
0xea630070, /* ld r19,112(r3) */
|
||||
0xea830078, /* ld r20,120(r3) */
|
||||
0xeaa30080, /* ld r21,128(r3) */
|
||||
0xeac30088, /* ld r22,136(r3) */
|
||||
0xeae30090, /* ld r23,144(r3) */
|
||||
0xeb030098, /* ld r24,152(r3) */
|
||||
0xeb2300a0, /* ld r25,160(r3) */
|
||||
0xeb4300a8, /* ld r26,168(r3) */
|
||||
0xeb6300b0, /* ld r27,176(r3) */
|
||||
0xeb8300b8, /* ld r28,184(r3) */
|
||||
0xeba300c0, /* ld r29,192(r3) */
|
||||
0xebc300c8, /* ld r30,200(r3) */
|
||||
0xebe300d0, /* ld r31,208(r3) */
|
||||
0x7ccff120, /* mtcr r6 */
|
||||
#else
|
||||
0x7d000026, /* mfcr r8 */
|
||||
0x90240028, /* stw r1,40(r4) */
|
||||
0x7d2802a6, /* mflr r9 */
|
||||
0x91a4003c, /* stw r13,60(r4) */
|
||||
0x91c40040, /* stw r14,64(r4) */
|
||||
0x91e40044, /* stw r15,68(r4) */
|
||||
0x92040048, /* stw r16,72(r4) */
|
||||
0x9224004c, /* stw r17,76(r4) */
|
||||
0x92440050, /* stw r18,80(r4) */
|
||||
0x92640054, /* stw r19,84(r4) */
|
||||
0x92840058, /* stw r20,88(r4) */
|
||||
0x92a4005c, /* stw r21,92(r4) */
|
||||
0x92c40060, /* stw r22,96(r4) */
|
||||
0x92e40064, /* stw r23,100(r4) */
|
||||
0x93040068, /* stw r24,104(r4) */
|
||||
0x9324006c, /* stw r25,108(r4) */
|
||||
0x93440070, /* stw r26,112(r4) */
|
||||
0x93640074, /* stw r27,116(r4) */
|
||||
0x93840078, /* stw r28,120(r4) */
|
||||
0x93a4007c, /* stw r29,124(r4) */
|
||||
0x93c40080, /* stw r30,128(r4) */
|
||||
0x93e40084, /* stw r31,132(r4) */
|
||||
0x91240020, /* stw r9,32(r4) */
|
||||
0x80e30020, /* lwz r7,32(r3) */
|
||||
0x80230028, /* lwz r1,40(r3) */
|
||||
0x48000009, /* bl 1 */
|
||||
0x7fe00008, /* trap */
|
||||
0x91040030, /*1:stw r8,48(r4) */
|
||||
0x80c30030, /* lwz r6,48(r3) */
|
||||
0x7ce903a6, /* mtctr r7 */
|
||||
0x81a3003c, /* lwz r13,60(r3) */
|
||||
0x81c30040, /* lwz r14,64(r3) */
|
||||
0x81e30044, /* lwz r15,68(r3) */
|
||||
0x82030048, /* lwz r16,72(r3) */
|
||||
0x8223004c, /* lwz r17,76(r3) */
|
||||
0x82430050, /* lwz r18,80(r3) */
|
||||
0x82630054, /* lwz r19,84(r3) */
|
||||
0x82830058, /* lwz r20,88(r3) */
|
||||
0x82a3005c, /* lwz r21,92(r3) */
|
||||
0x82c30060, /* lwz r22,96(r3) */
|
||||
0x82e30064, /* lwz r23,100(r3) */
|
||||
0x83030068, /* lwz r24,104(r3) */
|
||||
0x8323006c, /* lwz r25,108(r3) */
|
||||
0x83430070, /* lwz r26,112(r3) */
|
||||
0x83630074, /* lwz r27,116(r3) */
|
||||
0x83830078, /* lwz r28,120(r3) */
|
||||
0x83a3007c, /* lwz r29,124(r3) */
|
||||
0x83c30080, /* lwz r30,128(r3) */
|
||||
0x83e30084, /* lwz r31,132(r3) */
|
||||
0x7ccff120, /* mtcr r6 */
|
||||
#endif
|
||||
|
||||
#ifndef LIBCO_PPC_NOFP
|
||||
0xd9c400e0, /* stfd f14,224(r4) */
|
||||
0xd9e400e8, /* stfd f15,232(r4) */
|
||||
0xda0400f0, /* stfd f16,240(r4) */
|
||||
0xda2400f8, /* stfd f17,248(r4) */
|
||||
0xda440100, /* stfd f18,256(r4) */
|
||||
0xda640108, /* stfd f19,264(r4) */
|
||||
0xda840110, /* stfd f20,272(r4) */
|
||||
0xdaa40118, /* stfd f21,280(r4) */
|
||||
0xdac40120, /* stfd f22,288(r4) */
|
||||
0xdae40128, /* stfd f23,296(r4) */
|
||||
0xdb040130, /* stfd f24,304(r4) */
|
||||
0xdb240138, /* stfd f25,312(r4) */
|
||||
0xdb440140, /* stfd f26,320(r4) */
|
||||
0xdb640148, /* stfd f27,328(r4) */
|
||||
0xdb840150, /* stfd f28,336(r4) */
|
||||
0xdba40158, /* stfd f29,344(r4) */
|
||||
0xdbc40160, /* stfd f30,352(r4) */
|
||||
0xdbe40168, /* stfd f31,360(r4) */
|
||||
0xc9c300e0, /* lfd f14,224(r3) */
|
||||
0xc9e300e8, /* lfd f15,232(r3) */
|
||||
0xca0300f0, /* lfd f16,240(r3) */
|
||||
0xca2300f8, /* lfd f17,248(r3) */
|
||||
0xca430100, /* lfd f18,256(r3) */
|
||||
0xca630108, /* lfd f19,264(r3) */
|
||||
0xca830110, /* lfd f20,272(r3) */
|
||||
0xcaa30118, /* lfd f21,280(r3) */
|
||||
0xcac30120, /* lfd f22,288(r3) */
|
||||
0xcae30128, /* lfd f23,296(r3) */
|
||||
0xcb030130, /* lfd f24,304(r3) */
|
||||
0xcb230138, /* lfd f25,312(r3) */
|
||||
0xcb430140, /* lfd f26,320(r3) */
|
||||
0xcb630148, /* lfd f27,328(r3) */
|
||||
0xcb830150, /* lfd f28,336(r3) */
|
||||
0xcba30158, /* lfd f29,344(r3) */
|
||||
0xcbc30160, /* lfd f30,352(r3) */
|
||||
0xcbe30168, /* lfd f31,360(r3) */
|
||||
#endif
|
||||
|
||||
#ifdef __ALTIVEC__
|
||||
0x7ca042a6, /* mfvrsave r5 */
|
||||
0x39040180, /* addi r8,r4,384 */
|
||||
0x39240190, /* addi r9,r4,400 */
|
||||
0x70a00fff, /* andi. r0,r5,4095 */
|
||||
0x90a40034, /* stw r5,52(r4) */
|
||||
0x4182005c, /* beq- 2 */
|
||||
0x7e8041ce, /* stvx v20,r0,r8 */
|
||||
0x39080020, /* addi r8,r8,32 */
|
||||
0x7ea049ce, /* stvx v21,r0,r9 */
|
||||
0x39290020, /* addi r9,r9,32 */
|
||||
0x7ec041ce, /* stvx v22,r0,r8 */
|
||||
0x39080020, /* addi r8,r8,32 */
|
||||
0x7ee049ce, /* stvx v23,r0,r9 */
|
||||
0x39290020, /* addi r9,r9,32 */
|
||||
0x7f0041ce, /* stvx v24,r0,r8 */
|
||||
0x39080020, /* addi r8,r8,32 */
|
||||
0x7f2049ce, /* stvx v25,r0,r9 */
|
||||
0x39290020, /* addi r9,r9,32 */
|
||||
0x7f4041ce, /* stvx v26,r0,r8 */
|
||||
0x39080020, /* addi r8,r8,32 */
|
||||
0x7f6049ce, /* stvx v27,r0,r9 */
|
||||
0x39290020, /* addi r9,r9,32 */
|
||||
0x7f8041ce, /* stvx v28,r0,r8 */
|
||||
0x39080020, /* addi r8,r8,32 */
|
||||
0x7fa049ce, /* stvx v29,r0,r9 */
|
||||
0x39290020, /* addi r9,r9,32 */
|
||||
0x7fc041ce, /* stvx v30,r0,r8 */
|
||||
0x7fe049ce, /* stvx v31,r0,r9 */
|
||||
0x80a30034, /*2:lwz r5,52(r3) */
|
||||
0x39030180, /* addi r8,r3,384 */
|
||||
0x39230190, /* addi r9,r3,400 */
|
||||
0x70a00fff, /* andi. r0,r5,4095 */
|
||||
0x7ca043a6, /* mtvrsave r5 */
|
||||
0x4d820420, /* beqctr */
|
||||
0x7e8040ce, /* lvx v20,r0,r8 */
|
||||
0x39080020, /* addi r8,r8,32 */
|
||||
0x7ea048ce, /* lvx v21,r0,r9 */
|
||||
0x39290020, /* addi r9,r9,32 */
|
||||
0x7ec040ce, /* lvx v22,r0,r8 */
|
||||
0x39080020, /* addi r8,r8,32 */
|
||||
0x7ee048ce, /* lvx v23,r0,r9 */
|
||||
0x39290020, /* addi r9,r9,32 */
|
||||
0x7f0040ce, /* lvx v24,r0,r8 */
|
||||
0x39080020, /* addi r8,r8,32 */
|
||||
0x7f2048ce, /* lvx v25,r0,r9 */
|
||||
0x39290020, /* addi r9,r9,32 */
|
||||
0x7f4040ce, /* lvx v26,r0,r8 */
|
||||
0x39080020, /* addi r8,r8,32 */
|
||||
0x7f6048ce, /* lvx v27,r0,r9 */
|
||||
0x39290020, /* addi r9,r9,32 */
|
||||
0x7f8040ce, /* lvx v28,r0,r8 */
|
||||
0x39080020, /* addi r8,r8,32 */
|
||||
0x7fa048ce, /* lvx v29,r0,r9 */
|
||||
0x39290020, /* addi r9,r9,32 */
|
||||
0x7fc040ce, /* lvx v30,r0,r8 */
|
||||
0x7fe048ce, /* lvx v31,r0,r9 */
|
||||
#endif
|
||||
|
||||
0x4e800420, /* bctr */
|
||||
};
|
||||
|
||||
#if LIBCO_PPCDESC
|
||||
/* function call goes through indirect descriptor */
|
||||
#define CO_SWAP_ASM(x, y) ((void (*)(cothread_t, cothread_t))(uintptr_t)x)(x, y)
|
||||
#else
|
||||
/* function call goes directly to code */
|
||||
#define CO_SWAP_ASM(x, y) ((void (*)(cothread_t, cothread_t))(uintptr_t)libco_ppc_code)(x, y)
|
||||
#endif
|
||||
|
||||
static uint32_t* co_derive_(void* memory, unsigned size, uintptr_t entry) {
|
||||
(void)entry;
|
||||
|
||||
uint32_t* t = (uint32_t*)memory;
|
||||
|
||||
#if LIBCO_PPCDESC
|
||||
if(t) {
|
||||
memcpy(t, (void*)entry, sizeof(void*) * 3); /* copy entry's descriptor */
|
||||
*(const void**)t = libco_ppc_code; /* set function pointer to swap routine */
|
||||
}
|
||||
#endif
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int size, void (*entry_)(void)) {
|
||||
uintptr_t entry = (uintptr_t)entry_;
|
||||
uint32_t* t = 0;
|
||||
|
||||
/* be sure main thread was successfully allocated */
|
||||
if(co_active()) {
|
||||
t = co_derive_(memory, size, entry);
|
||||
}
|
||||
|
||||
if(t) {
|
||||
uintptr_t sp;
|
||||
int shift;
|
||||
|
||||
/* save current registers into new thread, so that any special ones will have proper values when thread is begun */
|
||||
CO_SWAP_ASM(t, t);
|
||||
|
||||
#if LIBCO_PPCDESC
|
||||
entry = (uintptr_t)*(void**)entry; /* get real address */
|
||||
#endif
|
||||
|
||||
/* put stack near end of block, and align */
|
||||
sp = (uintptr_t)t + size - above_stack;
|
||||
sp -= sp % stack_align;
|
||||
|
||||
/* on PPC32, we save and restore GPRs as 32 bits. for PPC64, we
|
||||
save and restore them as 64 bits, regardless of the size the ABI
|
||||
uses. so, we manually write pointers at the proper size. we always
|
||||
save and restore at the same address, and since PPC is big-endian,
|
||||
we must put the low byte first on PPC32. */
|
||||
|
||||
/* if uintptr_t is 32 bits, >>32 is undefined behavior,
|
||||
so we do two shifts and don't have to care how many bits uintptr_t is. */
|
||||
#if LIBCO_PPC64
|
||||
shift = 16;
|
||||
#else
|
||||
shift = 0;
|
||||
#endif
|
||||
|
||||
/* set up so entry will be called on next swap */
|
||||
t[ 8] = (uint32_t)(entry >> shift >> shift);
|
||||
t[ 9] = (uint32_t)entry;
|
||||
|
||||
t[10] = (uint32_t)(sp >> shift >> shift);
|
||||
t[11] = (uint32_t)sp;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static uint32_t* co_create_(unsigned size, uintptr_t entry) {
|
||||
(void)entry;
|
||||
|
||||
uint32_t* t = (uint32_t*)malloc(size);
|
||||
|
||||
#if LIBCO_PPCDESC
|
||||
if(t) {
|
||||
memcpy(t, (void*)entry, sizeof(void*) * 3); /* copy entry's descriptor */
|
||||
*(const void**)t = libco_ppc_code; /* set function pointer to swap routine */
|
||||
}
|
||||
#endif
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int size, void (*entry_)(void)) {
|
||||
uintptr_t entry = (uintptr_t)entry_;
|
||||
uint32_t* t = 0;
|
||||
|
||||
/* be sure main thread was successfully allocated */
|
||||
if(co_active()) {
|
||||
size += state_size + above_stack + stack_align;
|
||||
t = co_create_(size, entry);
|
||||
}
|
||||
|
||||
if(t) {
|
||||
uintptr_t sp;
|
||||
int shift;
|
||||
|
||||
/* save current registers into new thread, so that any special ones will have proper values when thread is begun */
|
||||
CO_SWAP_ASM(t, t);
|
||||
|
||||
#if LIBCO_PPCDESC
|
||||
entry = (uintptr_t)*(void**)entry; /* get real address */
|
||||
#endif
|
||||
|
||||
/* put stack near end of block, and align */
|
||||
sp = (uintptr_t)t + size - above_stack;
|
||||
sp -= sp % stack_align;
|
||||
|
||||
/* on PPC32, we save and restore GPRs as 32 bits. for PPC64, we
|
||||
save and restore them as 64 bits, regardless of the size the ABI
|
||||
uses. so, we manually write pointers at the proper size. we always
|
||||
save and restore at the same address, and since PPC is big-endian,
|
||||
we must put the low byte first on PPC32. */
|
||||
|
||||
/* if uintptr_t is 32 bits, >>32 is undefined behavior,
|
||||
so we do two shifts and don't have to care how many bits uintptr_t is. */
|
||||
#if LIBCO_PPC64
|
||||
shift = 16;
|
||||
#else
|
||||
shift = 0;
|
||||
#endif
|
||||
|
||||
/* set up so entry will be called on next swap */
|
||||
t[ 8] = (uint32_t)(entry >> shift >> shift);
|
||||
t[ 9] = (uint32_t)entry;
|
||||
|
||||
t[10] = (uint32_t)(sp >> shift >> shift);
|
||||
t[11] = (uint32_t)sp;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void co_delete(cothread_t t) {
|
||||
free(t);
|
||||
}
|
||||
|
||||
static void co_init_(void) {
|
||||
#if LIBCO_MPROTECT
|
||||
long page_size = sysconf(_SC_PAGESIZE);
|
||||
if(page_size > 0) {
|
||||
uintptr_t align = page_size;
|
||||
uintptr_t begin = (uintptr_t)libco_ppc_code;
|
||||
uintptr_t end = begin + sizeof libco_ppc_code;
|
||||
|
||||
/* align beginning and end */
|
||||
end += align - 1;
|
||||
end -= end % align;
|
||||
begin -= begin % align;
|
||||
|
||||
mprotect((void*)begin, end - begin, PROT_READ | PROT_EXEC);
|
||||
}
|
||||
#endif
|
||||
|
||||
co_active_handle = co_create_(state_size, (uintptr_t)&co_switch);
|
||||
}
|
||||
|
||||
cothread_t co_active() {
|
||||
if(!co_active_handle) co_init_();
|
||||
|
||||
return co_active_handle;
|
||||
}
|
||||
|
||||
void co_switch(cothread_t t) {
|
||||
cothread_t old = co_active_handle;
|
||||
co_active_handle = t;
|
||||
|
||||
CO_SWAP_ASM(t, old);
|
||||
}
|
||||
|
||||
int co_serializable() {
|
||||
return 0;
|
||||
}
|
279
libco/ppc64v2.c
279
libco/ppc64v2.c
|
@ -1,279 +0,0 @@
|
|||
/* author: Shawn Anastasio */
|
||||
|
||||
#define LIBCO_C
|
||||
#include "libco.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ppc64_context {
|
||||
//GPRs
|
||||
uint64_t gprs[32];
|
||||
uint64_t lr;
|
||||
uint64_t ccr;
|
||||
|
||||
//FPRs
|
||||
uint64_t fprs[32];
|
||||
|
||||
#ifdef __ALTIVEC__
|
||||
//Altivec (VMX)
|
||||
uint64_t vmx[12 * 2];
|
||||
uint32_t vrsave;
|
||||
#endif
|
||||
};
|
||||
|
||||
static thread_local struct ppc64_context* co_active_handle = 0;
|
||||
|
||||
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||
#define ALIGN(p, x) ((void*)((uintptr_t)(p) & ~((x) - 1)))
|
||||
|
||||
#define MIN_STACK 0x10000lu
|
||||
#define MIN_STACK_FRAME 0x20lu
|
||||
#define STACK_ALIGN 0x10lu
|
||||
|
||||
void swap_context(struct ppc64_context* read, struct ppc64_context* write);
|
||||
__asm__(
|
||||
".text\n"
|
||||
".align 4\n"
|
||||
".type swap_context @function\n"
|
||||
"swap_context:\n"
|
||||
".cfi_startproc\n"
|
||||
|
||||
//save GPRs
|
||||
"std 1, 8(4)\n"
|
||||
"std 2, 16(4)\n"
|
||||
"std 12, 96(4)\n"
|
||||
"std 13, 104(4)\n"
|
||||
"std 14, 112(4)\n"
|
||||
"std 15, 120(4)\n"
|
||||
"std 16, 128(4)\n"
|
||||
"std 17, 136(4)\n"
|
||||
"std 18, 144(4)\n"
|
||||
"std 19, 152(4)\n"
|
||||
"std 20, 160(4)\n"
|
||||
"std 21, 168(4)\n"
|
||||
"std 22, 176(4)\n"
|
||||
"std 23, 184(4)\n"
|
||||
"std 24, 192(4)\n"
|
||||
"std 25, 200(4)\n"
|
||||
"std 26, 208(4)\n"
|
||||
"std 27, 216(4)\n"
|
||||
"std 28, 224(4)\n"
|
||||
"std 29, 232(4)\n"
|
||||
"std 30, 240(4)\n"
|
||||
"std 31, 248(4)\n"
|
||||
|
||||
//save LR
|
||||
"mflr 5\n"
|
||||
"std 5, 256(4)\n"
|
||||
|
||||
//save CCR
|
||||
"mfcr 5\n"
|
||||
"std 5, 264(4)\n"
|
||||
|
||||
//save FPRs
|
||||
"stfd 14, 384(4)\n"
|
||||
"stfd 15, 392(4)\n"
|
||||
"stfd 16, 400(4)\n"
|
||||
"stfd 17, 408(4)\n"
|
||||
"stfd 18, 416(4)\n"
|
||||
"stfd 19, 424(4)\n"
|
||||
"stfd 20, 432(4)\n"
|
||||
"stfd 21, 440(4)\n"
|
||||
"stfd 22, 448(4)\n"
|
||||
"stfd 23, 456(4)\n"
|
||||
"stfd 24, 464(4)\n"
|
||||
"stfd 25, 472(4)\n"
|
||||
"stfd 26, 480(4)\n"
|
||||
"stfd 27, 488(4)\n"
|
||||
"stfd 28, 496(4)\n"
|
||||
"stfd 29, 504(4)\n"
|
||||
"stfd 30, 512(4)\n"
|
||||
"stfd 31, 520(4)\n"
|
||||
|
||||
#ifdef __ALTIVEC__
|
||||
//save VMX
|
||||
"li 5, 528\n"
|
||||
"stvxl 20, 4, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"stvxl 21, 4, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"stvxl 22, 4, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"stvxl 23, 4, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"stvxl 24, 4, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"stvxl 25, 4, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"stvxl 26, 4, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"stvxl 27, 4, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"stvxl 28, 4, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"stvxl 29, 4, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"stvxl 30, 4, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"stvxl 31, 4, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
|
||||
//save VRSAVE
|
||||
"mfvrsave 5\n"
|
||||
"stw 5, 736(4)\n"
|
||||
#endif
|
||||
|
||||
//restore GPRs
|
||||
"ld 1, 8(3)\n"
|
||||
"ld 2, 16(3)\n"
|
||||
"ld 12, 96(3)\n"
|
||||
"ld 13, 104(3)\n"
|
||||
"ld 14, 112(3)\n"
|
||||
"ld 15, 120(3)\n"
|
||||
"ld 16, 128(3)\n"
|
||||
"ld 17, 136(3)\n"
|
||||
"ld 18, 144(3)\n"
|
||||
"ld 19, 152(3)\n"
|
||||
"ld 20, 160(3)\n"
|
||||
"ld 21, 168(3)\n"
|
||||
"ld 22, 176(3)\n"
|
||||
"ld 23, 184(3)\n"
|
||||
"ld 24, 192(3)\n"
|
||||
"ld 25, 200(3)\n"
|
||||
"ld 26, 208(3)\n"
|
||||
"ld 27, 216(3)\n"
|
||||
"ld 28, 224(3)\n"
|
||||
"ld 29, 232(3)\n"
|
||||
"ld 30, 240(3)\n"
|
||||
"ld 31, 248(3)\n"
|
||||
|
||||
//restore LR
|
||||
"ld 5, 256(3)\n"
|
||||
"mtlr 5\n"
|
||||
|
||||
//restore CCR
|
||||
"ld 5, 264(3)\n"
|
||||
"mtcr 5\n"
|
||||
|
||||
//restore FPRs
|
||||
"lfd 14, 384(3)\n"
|
||||
"lfd 15, 392(3)\n"
|
||||
"lfd 16, 400(3)\n"
|
||||
"lfd 17, 408(3)\n"
|
||||
"lfd 18, 416(3)\n"
|
||||
"lfd 19, 424(3)\n"
|
||||
"lfd 20, 432(3)\n"
|
||||
"lfd 21, 440(3)\n"
|
||||
"lfd 22, 448(3)\n"
|
||||
"lfd 23, 456(3)\n"
|
||||
"lfd 24, 464(3)\n"
|
||||
"lfd 25, 472(3)\n"
|
||||
"lfd 26, 480(3)\n"
|
||||
"lfd 27, 488(3)\n"
|
||||
"lfd 28, 496(3)\n"
|
||||
"lfd 29, 504(3)\n"
|
||||
"lfd 30, 512(3)\n"
|
||||
"lfd 31, 520(3)\n"
|
||||
|
||||
#ifdef __ALTIVEC__
|
||||
//restore VMX
|
||||
"li 5, 528\n"
|
||||
"lvxl 20, 3, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"lvxl 21, 3, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"lvxl 22, 3, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"lvxl 23, 3, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"lvxl 24, 3, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"lvxl 25, 3, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"lvxl 26, 3, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"lvxl 27, 3, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"lvxl 28, 3, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"lvxl 29, 3, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"lvxl 30, 3, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
"lvxl 31, 3, 5\n"
|
||||
"addi 5, 5, 16\n"
|
||||
|
||||
//restore VRSAVE
|
||||
"lwz 5, 720(3)\n"
|
||||
"mtvrsave 5\n"
|
||||
#endif
|
||||
|
||||
//branch to LR
|
||||
"blr\n"
|
||||
|
||||
".cfi_endproc\n"
|
||||
".size swap_context, .-swap_context\n"
|
||||
);
|
||||
|
||||
cothread_t co_active() {
|
||||
if(!co_active_handle) {
|
||||
co_active_handle = (struct ppc64_context*)malloc(MIN_STACK + sizeof(struct ppc64_context));
|
||||
}
|
||||
return (cothread_t)co_active_handle;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int size, void (*coentry)(void)) {
|
||||
uint8_t* sp;
|
||||
struct ppc64_context* context = (struct ppc64_context*)memory;
|
||||
|
||||
//save current context into new context to initialize it
|
||||
swap_context(context, context);
|
||||
|
||||
//align stack
|
||||
sp = (uint8_t*)memory + size - STACK_ALIGN;
|
||||
sp = (uint8_t*)ALIGN(sp, STACK_ALIGN);
|
||||
|
||||
//write 0 for initial backchain
|
||||
*(uint64_t*)sp = 0;
|
||||
|
||||
//create new frame with backchain
|
||||
sp -= MIN_STACK_FRAME;
|
||||
*(uint64_t*)sp = (uint64_t)(sp + MIN_STACK_FRAME);
|
||||
|
||||
//update context with new stack (r1) and entrypoint (r12, lr)
|
||||
context->gprs[ 1] = (uint64_t)sp;
|
||||
context->gprs[12] = (uint64_t)coentry;
|
||||
context->lr = (uint64_t)coentry;
|
||||
|
||||
return (cothread_t)memory;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int size, void (*coentry)(void)) {
|
||||
void* memory = malloc(size);
|
||||
if(!memory) return (cothread_t)0;
|
||||
return co_derive(memory, size, coentry);
|
||||
}
|
||||
|
||||
void co_delete(cothread_t handle) {
|
||||
free(handle);
|
||||
}
|
||||
|
||||
void co_switch(cothread_t to) {
|
||||
struct ppc64_context* from = co_active_handle;
|
||||
co_active_handle = (struct ppc64_context*)to;
|
||||
swap_context((struct ppc64_context*)to, from);
|
||||
}
|
||||
|
||||
int co_serializable() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,38 +0,0 @@
|
|||
#if defined(LIBCO_C)
|
||||
|
||||
/*[amd64, arm, ppc, x86]:
|
||||
by default, co_swap_function is marked as a text (code) section
|
||||
if not supported, uncomment the below line to use mprotect instead */
|
||||
/* #define LIBCO_MPROTECT */
|
||||
|
||||
/*[amd64]:
|
||||
Win64 only: provides a substantial speed-up, but will thrash XMM regs
|
||||
do not use this unless you are certain your application won't use SSE */
|
||||
/* #define LIBCO_NO_SSE */
|
||||
|
||||
#if defined(LIBCO_C)
|
||||
#if defined(LIBCO_MP)
|
||||
#define thread_local __thread
|
||||
#else
|
||||
#define thread_local
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
#if !defined(_MSC_VER)
|
||||
#include <stdalign.h>
|
||||
#endif
|
||||
#else
|
||||
#define alignas(bytes)
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define section(name) __declspec(allocate("." #name))
|
||||
#elif defined(__APPLE__)
|
||||
#define section(name) __attribute__((section("__TEXT,__" #name)))
|
||||
#else
|
||||
#define section(name) __attribute__((section("." #name "#")))
|
||||
#endif
|
||||
|
||||
/* if defined(LIBCO_C) */
|
||||
#endif
|
145
libco/sjlj.c
145
libco/sjlj.c
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
note this was designed for UNIX systems. Based on ideas expressed in a paper by Ralf Engelschall.
|
||||
for SJLJ on other systems, one would want to rewrite springboard() and co_create() and hack the jmb_buf stack pointer.
|
||||
*/
|
||||
|
||||
#define LIBCO_C
|
||||
#include "libco.h"
|
||||
#include "settings.h"
|
||||
|
||||
#define _BSD_SOURCE
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
sigjmp_buf context;
|
||||
void (*coentry)(void);
|
||||
void* stack;
|
||||
} cothread_struct;
|
||||
|
||||
static thread_local cothread_struct co_primary;
|
||||
static thread_local cothread_struct* creating;
|
||||
static thread_local cothread_struct* co_running = 0;
|
||||
|
||||
static void springboard(int ignored) {
|
||||
if(sigsetjmp(creating->context, 0)) {
|
||||
co_running->coentry();
|
||||
}
|
||||
}
|
||||
|
||||
cothread_t co_active() {
|
||||
if(!co_running) co_running = &co_primary;
|
||||
return (cothread_t)co_running;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int size, void (*coentry)(void)) {
|
||||
if(!co_running) co_running = &co_primary;
|
||||
|
||||
cothread_struct* thread = (cothread_struct*)memory;
|
||||
memory = (unsigned char*)memory + sizeof(cothread_struct);
|
||||
size -= sizeof(cothread_struct);
|
||||
if(thread) {
|
||||
struct sigaction handler;
|
||||
struct sigaction old_handler;
|
||||
|
||||
stack_t stack;
|
||||
stack_t old_stack;
|
||||
|
||||
thread->coentry = thread->stack = 0;
|
||||
|
||||
stack.ss_flags = 0;
|
||||
stack.ss_size = size;
|
||||
thread->stack = stack.ss_sp = memory;
|
||||
if(stack.ss_sp && !sigaltstack(&stack, &old_stack)) {
|
||||
handler.sa_handler = springboard;
|
||||
handler.sa_flags = SA_ONSTACK;
|
||||
sigemptyset(&handler.sa_mask);
|
||||
creating = thread;
|
||||
|
||||
if(!sigaction(SIGUSR1, &handler, &old_handler)) {
|
||||
if(!raise(SIGUSR1)) {
|
||||
thread->coentry = coentry;
|
||||
}
|
||||
sigaltstack(&old_stack, 0);
|
||||
sigaction(SIGUSR1, &old_handler, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(thread->coentry != coentry) {
|
||||
co_delete(thread);
|
||||
thread = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (cothread_t)thread;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int size, void (*coentry)(void)) {
|
||||
if(!co_running) co_running = &co_primary;
|
||||
|
||||
cothread_struct* thread = (cothread_struct*)malloc(sizeof(cothread_struct));
|
||||
if(thread) {
|
||||
struct sigaction handler;
|
||||
struct sigaction old_handler;
|
||||
|
||||
stack_t stack;
|
||||
stack_t old_stack;
|
||||
|
||||
thread->coentry = thread->stack = 0;
|
||||
|
||||
stack.ss_flags = 0;
|
||||
stack.ss_size = size;
|
||||
thread->stack = stack.ss_sp = malloc(size);
|
||||
if(stack.ss_sp && !sigaltstack(&stack, &old_stack)) {
|
||||
handler.sa_handler = springboard;
|
||||
handler.sa_flags = SA_ONSTACK;
|
||||
sigemptyset(&handler.sa_mask);
|
||||
creating = thread;
|
||||
|
||||
if(!sigaction(SIGUSR1, &handler, &old_handler)) {
|
||||
if(!raise(SIGUSR1)) {
|
||||
thread->coentry = coentry;
|
||||
}
|
||||
sigaltstack(&old_stack, 0);
|
||||
sigaction(SIGUSR1, &old_handler, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(thread->coentry != coentry) {
|
||||
co_delete(thread);
|
||||
thread = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (cothread_t)thread;
|
||||
}
|
||||
|
||||
void co_delete(cothread_t cothread) {
|
||||
if(cothread) {
|
||||
if(((cothread_struct*)cothread)->stack) {
|
||||
free(((cothread_struct*)cothread)->stack);
|
||||
}
|
||||
free(cothread);
|
||||
}
|
||||
}
|
||||
|
||||
void co_switch(cothread_t cothread) {
|
||||
if(!sigsetjmp(co_running->context, 0)) {
|
||||
co_running = (cothread_struct*)cothread;
|
||||
siglongjmp(co_running->context, 1);
|
||||
}
|
||||
}
|
||||
|
||||
int co_serializable() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
WARNING: the overhead of POSIX ucontext is very high,
|
||||
assembly versions of libco or libco_sjlj should be much faster
|
||||
|
||||
this library only exists for two reasons:
|
||||
1: as an initial test for the viability of a ucontext implementation
|
||||
2: to demonstrate the power and speed of libco over existing implementations,
|
||||
such as pth (which defaults to wrapping ucontext on unix targets)
|
||||
|
||||
use this library only as a *last resort*
|
||||
*/
|
||||
|
||||
#define LIBCO_C
|
||||
#include "libco.h"
|
||||
#include "settings.h"
|
||||
|
||||
#define _BSD_SOURCE
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdlib.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static thread_local ucontext_t co_primary;
|
||||
static thread_local ucontext_t* co_running = 0;
|
||||
|
||||
cothread_t co_active() {
|
||||
if(!co_running) co_running = &co_primary;
|
||||
return (cothread_t)co_running;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int heapsize, void (*coentry)(void)) {
|
||||
if(!co_running) co_running = &co_primary;
|
||||
ucontext_t* thread = (ucontext_t*)memory;
|
||||
memory = (unsigned char*)memory + sizeof(ucontext_t);
|
||||
heapsize -= sizeof(ucontext_t);
|
||||
if(thread) {
|
||||
if((!getcontext(thread) && !(thread->uc_stack.ss_sp = 0)) && (thread->uc_stack.ss_sp = memory)) {
|
||||
thread->uc_link = co_running;
|
||||
thread->uc_stack.ss_size = heapsize;
|
||||
makecontext(thread, coentry, 0);
|
||||
} else {
|
||||
thread = 0;
|
||||
}
|
||||
}
|
||||
return (cothread_t)thread;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) {
|
||||
if(!co_running) co_running = &co_primary;
|
||||
ucontext_t* thread = (ucontext_t*)malloc(sizeof(ucontext_t));
|
||||
if(thread) {
|
||||
if((!getcontext(thread) && !(thread->uc_stack.ss_sp = 0)) && (thread->uc_stack.ss_sp = malloc(heapsize))) {
|
||||
thread->uc_link = co_running;
|
||||
thread->uc_stack.ss_size = heapsize;
|
||||
makecontext(thread, coentry, 0);
|
||||
} else {
|
||||
co_delete((cothread_t)thread);
|
||||
thread = 0;
|
||||
}
|
||||
}
|
||||
return (cothread_t)thread;
|
||||
}
|
||||
|
||||
void co_delete(cothread_t cothread) {
|
||||
if(cothread) {
|
||||
if(((ucontext_t*)cothread)->uc_stack.ss_sp) { free(((ucontext_t*)cothread)->uc_stack.ss_sp); }
|
||||
free(cothread);
|
||||
}
|
||||
}
|
||||
|
||||
void co_switch(cothread_t cothread) {
|
||||
ucontext_t* old_thread = co_running;
|
||||
co_running = (ucontext_t*)cothread;
|
||||
swapcontext(old_thread, co_running);
|
||||
}
|
||||
|
||||
int co_serializable() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
119
libco/x86.c
119
libco/x86.c
|
@ -1,119 +0,0 @@
|
|||
#define LIBCO_C
|
||||
#include "libco.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define fastcall __attribute__((fastcall))
|
||||
#elif defined(_MSC_VER)
|
||||
#define fastcall __fastcall
|
||||
#else
|
||||
#error "libco: please define fastcall macro"
|
||||
#endif
|
||||
|
||||
static thread_local long co_active_buffer[64];
|
||||
static thread_local cothread_t co_active_handle = 0;
|
||||
static void (fastcall *co_swap)(cothread_t, cothread_t) = 0;
|
||||
|
||||
#ifdef LIBCO_MPROTECT
|
||||
alignas(4096)
|
||||
#else
|
||||
section(text)
|
||||
#endif
|
||||
/* ABI: fastcall */
|
||||
static const unsigned char co_swap_function[4096] = {
|
||||
0x89, 0x22, /* mov [edx],esp */
|
||||
0x8b, 0x21, /* mov esp,[ecx] */
|
||||
0x58, /* pop eax */
|
||||
0x89, 0x6a, 0x04, /* mov [edx+ 4],ebp */
|
||||
0x89, 0x72, 0x08, /* mov [edx+ 8],esi */
|
||||
0x89, 0x7a, 0x0c, /* mov [edx+12],edi */
|
||||
0x89, 0x5a, 0x10, /* mov [edx+16],ebx */
|
||||
0x8b, 0x69, 0x04, /* mov ebp,[ecx+ 4] */
|
||||
0x8b, 0x71, 0x08, /* mov esi,[ecx+ 8] */
|
||||
0x8b, 0x79, 0x0c, /* mov edi,[ecx+12] */
|
||||
0x8b, 0x59, 0x10, /* mov ebx,[ecx+16] */
|
||||
0xff, 0xe0, /* jmp eax */
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
||||
static void co_init() {
|
||||
#ifdef LIBCO_MPROTECT
|
||||
DWORD old_privileges;
|
||||
VirtualProtect((void*)co_swap_function, sizeof co_swap_function, PAGE_EXECUTE_READ, &old_privileges);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#ifdef LIBCO_MPROTECT
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
static void co_init() {
|
||||
#ifdef LIBCO_MPROTECT
|
||||
unsigned long addr = (unsigned long)co_swap_function;
|
||||
unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE));
|
||||
unsigned long size = (addr - base) + sizeof co_swap_function;
|
||||
mprotect((void*)base, size, PROT_READ | PROT_EXEC);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void crash() {
|
||||
assert(0); /* called only if cothread_t entrypoint returns */
|
||||
}
|
||||
|
||||
cothread_t co_active() {
|
||||
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
||||
return co_active_handle;
|
||||
}
|
||||
|
||||
cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void)) {
|
||||
cothread_t handle;
|
||||
if(!co_swap) {
|
||||
co_init();
|
||||
co_swap = (void (fastcall*)(cothread_t, cothread_t))co_swap_function;
|
||||
}
|
||||
if(!co_active_handle) co_active_handle = &co_active_buffer;
|
||||
|
||||
if(handle = (cothread_t)memory) {
|
||||
unsigned int offset = (size & ~15) - 32;
|
||||
long *p = (long*)((char*)handle + offset); /* seek to top of stack */
|
||||
*--p = (long)crash; /* crash if entrypoint returns */
|
||||
*--p = (long)entrypoint; /* start of function */
|
||||
*(long*)handle = (long)p; /* stack pointer */
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
|
||||
void* memory = malloc(size);
|
||||
if(!memory) return (cothread_t)0;
|
||||
return co_derive(memory, size, entrypoint);
|
||||
}
|
||||
|
||||
void co_delete(cothread_t handle) {
|
||||
free(handle);
|
||||
}
|
||||
|
||||
void co_switch(cothread_t handle) {
|
||||
register cothread_t co_previous_handle = co_active_handle;
|
||||
co_swap(co_active_handle = handle, co_previous_handle);
|
||||
}
|
||||
|
||||
int co_serializable() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue