Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/libco/x86.c
2 views
1
/*
2
libco.x86 (2009-10-12)
3
author: byuu
4
license: public domain
5
*/
6
7
#define LIBCO_C
8
#include "libco.h"
9
#include <assert.h>
10
#include <stdlib.h>
11
12
#ifdef __cplusplus
13
extern "C" {
14
#endif
15
16
#if defined(_MSC_VER)
17
#define fastcall __fastcall
18
#elif defined(__GNUC__)
19
#define fastcall __attribute__((fastcall))
20
#else
21
#error "libco: please define fastcall macro"
22
#endif
23
24
static thread_local long co_active_buffer[64];
25
static thread_local cothread_t co_active_handle = 0;
26
static void (fastcall *co_swap)(cothread_t, cothread_t) = 0;
27
28
//ABI: fastcall
29
static unsigned char co_swap_function[] = {
30
0x89, 0x22, 0x8B, 0x21, 0x58, 0x89, 0x6A, 0x04, 0x89, 0x72, 0x08, 0x89, 0x7A, 0x0C, 0x89, 0x5A,
31
0x10, 0x8B, 0x69, 0x04, 0x8B, 0x71, 0x08, 0x8B, 0x79, 0x0C, 0x8B, 0x59, 0x10, 0xFF, 0xE0,
32
};
33
34
#ifdef _WIN32
35
#include <windows.h>
36
37
void co_init() {
38
DWORD old_privileges;
39
VirtualProtect(co_swap_function, sizeof co_swap_function, PAGE_EXECUTE_READWRITE, &old_privileges);
40
}
41
#else
42
#include <unistd.h>
43
#include <sys/mman.h>
44
45
void co_init() {
46
unsigned long addr = (unsigned long)co_swap_function;
47
unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE));
48
unsigned long size = (addr - base) + sizeof co_swap_function;
49
mprotect((void*)base, size, PROT_READ | PROT_WRITE | PROT_EXEC);
50
}
51
#endif
52
53
static void crash() {
54
assert(0); /* called only if cothread_t entrypoint returns */
55
}
56
57
cothread_t co_active() {
58
if(!co_active_handle) co_active_handle = &co_active_buffer;
59
return co_active_handle;
60
}
61
62
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
63
cothread_t handle;
64
if(!co_swap) {
65
co_init();
66
co_swap = (void (fastcall*)(cothread_t, cothread_t))co_swap_function;
67
}
68
if(!co_active_handle) co_active_handle = &co_active_buffer;
69
size += 256; /* allocate additional space for storage */
70
size &= ~15; /* align stack to 16-byte boundary */
71
72
if(handle = (cothread_t)malloc(size)) {
73
long *p = (long*)((char*)handle + size); /* seek to top of stack */
74
*--p = (long)crash; /* crash if entrypoint returns */
75
*--p = (long)entrypoint; /* start of function */
76
*(long*)handle = (long)p; /* stack pointer */
77
}
78
79
return handle;
80
}
81
82
void co_delete(cothread_t handle) {
83
free(handle);
84
}
85
86
void co_switch(cothread_t handle) {
87
register cothread_t co_previous_handle = co_active_handle;
88
co_swap(co_active_handle = handle, co_previous_handle);
89
}
90
91
#ifdef __cplusplus
92
}
93
#endif
94
95