Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/libco_msvc_win32/libco_msvc_win32.c
2 views
1
/*
2
libco.sjlj (2008-01-28)
3
author: Nach
4
license: public domain
5
*/
6
7
/*
8
* Note this was designed for UNIX systems. Based on ideas expressed in a paper
9
* by Ralf Engelschall.
10
* For SJLJ on other systems, one would want to rewrite springboard() and
11
* co_create() and hack the jmb_buf stack pointer.
12
*/
13
14
#define LIBCO_C
15
#define LIBCO_EXPORT
16
#include "../bsnes/libco/libco.h"
17
#include <stdlib.h>
18
#include <setjmp.h>
19
20
#ifdef __cplusplus
21
extern "C" {
22
#endif
23
24
typedef struct
25
{
26
jmp_buf context;
27
coentry_t coentry;
28
void *stack;
29
unsigned long seh_frame, stack_top, stack_bottom;
30
cothread_t caller;
31
} cothread_struct;
32
33
static thread_local cothread_struct co_primary;
34
static thread_local cothread_struct *co_running = 0;
35
36
37
//links of interest
38
//http://connect.microsoft.com/VisualStudio/feedback/details/100319/really-wierd-behaviour-in-crt-io-coupled-with-some-inline-assembly
39
//http://en.wikipedia.org/wiki/Thread_Information_Block
40
//http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/72093e46-4524-4f54-9f36-c7e8a309d1db/ //FS warning
41
42
43
#define WINVER 0x0400
44
#define _WIN32_WINNT 0x0400
45
#define WIN32_LEAN_AND_MEAN
46
#include <windows.h>
47
48
#pragma warning(disable:4733)
49
#pragma warning(disable:4311)
50
51
static void capture_fs(cothread_struct* rec)
52
{
53
int temp;
54
__asm mov eax, dword ptr fs:[0];
55
__asm mov temp, eax;
56
rec->seh_frame = temp;
57
__asm mov eax, dword ptr fs:[4];
58
__asm mov temp, eax;
59
rec->stack_top = temp;
60
__asm mov eax, dword ptr fs:[8];
61
__asm mov temp, eax;
62
rec->stack_bottom = temp;
63
}
64
65
static void restore_fs(cothread_struct* rec)
66
{
67
int temp;
68
temp = rec->seh_frame;
69
__asm mov eax, temp;
70
__asm mov dword ptr fs:[0], eax
71
temp = rec->stack_top;
72
__asm mov eax, temp;
73
__asm mov dword ptr fs:[4], eax
74
temp = rec->stack_bottom;
75
__asm mov eax, temp;
76
__asm mov dword ptr fs:[8], eax
77
}
78
79
static void os_co_wrapper()
80
{
81
cothread_struct* rec = (cothread_struct*)co_active();
82
//__try
83
//{
84
rec->coentry();
85
//}
86
//__except(EXCEPTION_EXECUTE_HANDLER)
87
//{
88
// //unhandled win32 exception in coroutine.
89
// //this coroutine will now be suspended permanently and control will be yielded to caller, for lack of anything better to do.
90
// //perhaps the process should just terminate.
91
// for(;;)
92
// {
93
// //dead coroutine
94
// co_switch(rec->caller);
95
// }
96
//}
97
}
98
99
static void os_co_create(cothread_struct* rec, unsigned int size, coentry_t coentry)
100
{
101
_JUMP_BUFFER* jb = (_JUMP_BUFFER*)&rec->context;
102
cothread_struct temp;
103
104
jb->Esp = (unsigned long)rec->stack + size - 4;
105
jb->Eip = (unsigned long)os_co_wrapper;
106
107
rec->stack_top = jb->Esp + 4;
108
rec->stack_bottom = (unsigned long)rec->stack;
109
110
//wild assumption about SEH frame.. seems to work
111
capture_fs(&temp);
112
rec->seh_frame = temp.seh_frame;
113
}
114
115
static void os_pre_setjmp(cothread_t target)
116
{
117
cothread_struct* rec = (cothread_struct*)target;
118
capture_fs(co_running);
119
rec->caller = co_running;
120
}
121
122
static void os_pre_longjmp(cothread_struct* rec)
123
{
124
restore_fs(rec);
125
}
126
127
__declspec(dllexport) cothread_t co_active()
128
{
129
if(!co_running) co_running = &co_primary;
130
return (cothread_t)co_running;
131
}
132
133
__declspec(dllexport) cothread_t co_create(unsigned int size, void (*coentry)(void))
134
{
135
cothread_struct *thread;
136
137
if(!co_running) co_running = &co_primary;
138
139
thread = (cothread_struct*)malloc(sizeof(cothread_struct));
140
if(thread)
141
{
142
thread->coentry = coentry;
143
thread->stack = malloc(size);
144
{
145
setjmp(thread->context);
146
os_co_create(thread,size,coentry);
147
}
148
}
149
150
return (cothread_t)thread;
151
}
152
153
__declspec(dllexport) void co_delete(cothread_t cothread)
154
{
155
if(cothread)
156
{
157
if(((cothread_struct*)cothread)->stack)
158
{
159
free(((cothread_struct*)cothread)->stack);
160
}
161
free(cothread);
162
}
163
}
164
165
__declspec(dllexport) void co_switch(cothread_t cothread)
166
{
167
os_pre_setjmp(cothread);
168
if(!setjmp(co_running->context))
169
{
170
co_running = (cothread_struct*)cothread;
171
os_pre_longjmp(co_running);
172
longjmp(co_running->context,0);
173
}
174
}
175
176
#ifdef __cplusplus
177
}
178
#endif
179
180