Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/libco_msvc_win32/trying-to-port-to-mingw-win32.c
2 views
1
//links of interest
2
//http://connect.microsoft.com/VisualStudio/feedback/details/100319/really-wierd-behaviour-in-crt-io-coupled-with-some-inline-assembly
3
//http://en.wikipedia.org/wiki/Thread_Information_Block
4
//http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/72093e46-4524-4f54-9f36-c7e8a309d1db/ //FS warning
5
6
#define LIBCO_C
7
#define LIBCO_EXPORT
8
#include "../bsnes/libco/libco.h"
9
#include <stdlib.h>
10
#include <setjmp.h>
11
12
#ifdef __cplusplus
13
extern "C" {
14
#endif
15
16
typedef void (*coentry_t)(void);
17
18
typedef struct
19
{
20
jmp_buf context;
21
coentry_t coentry;
22
void *stack;
23
unsigned long seh_frame, stack_top, stack_bottom;
24
cothread_t caller;
25
} cothread_struct;
26
27
static thread_local cothread_struct co_primary;
28
static thread_local cothread_struct *co_running = 0;
29
30
#define WINVER 0x0400
31
#define _WIN32_WINNT 0x0400
32
#define WIN32_LEAN_AND_MEAN
33
#include <windows.h>
34
35
#ifndef _MSC_VER
36
typedef struct __JUMP_BUFFER {
37
unsigned long Ebp;
38
unsigned long Ebx;
39
unsigned long Edi;
40
unsigned long Esi;
41
unsigned long Esp;
42
unsigned long Eip;
43
unsigned long Registration;
44
unsigned long TryLevel;
45
unsigned long Cookie;
46
unsigned long UnwindFunc;
47
unsigned long UnwindData[6];
48
} _JUMP_BUFFER;
49
#endif
50
51
#pragma warning(disable:4733)
52
#pragma warning(disable:4311)
53
54
static void capture_fs(cothread_struct* rec)
55
{
56
asm(
57
"mov %0, dword ptr fs:[0];"
58
"mov %1, dword ptr fs:[4];"
59
"mov %2, dword ptr fs:[8];"
60
:"=r"(rec->seh_frame), "=r"(rec->stack_top), "=r"(rec->stack_bottom)
61
:
62
:
63
);
64
}
65
66
static void restore_fs(cothread_struct* rec)
67
{
68
asm(
69
"mov dword ptr fs:[0], %0;"
70
"mov dword ptr fs:[4], %1;"
71
"mov dword ptr fs:[8], %2;"
72
:
73
:"r"(rec->seh_frame), "r"(rec->stack_top), "r"(rec->stack_bottom)
74
:
75
);
76
}
77
78
static void os_co_wrapper()
79
{
80
cothread_struct* rec = (cothread_struct*)co_active();
81
//__try
82
//{
83
rec->coentry();
84
//}
85
//__except(EXCEPTION_EXECUTE_HANDLER)
86
//{
87
// //unhandled win32 exception in coroutine.
88
// //this coroutine will now be suspended permanently and control will be yielded to caller, for lack of anything better to do.
89
// //perhaps the process should just terminate.
90
// for(;;)
91
// {
92
// //dead coroutine
93
// co_switch(rec->caller);
94
// }
95
//}
96
}
97
98
static void os_co_create(cothread_struct* rec, unsigned int size, coentry_t coentry)
99
{
100
_JUMP_BUFFER* jb = (_JUMP_BUFFER*)&rec->context;
101
cothread_struct temp;
102
103
jb->Esp = (unsigned long)rec->stack + size - 4;
104
jb->Eip = (unsigned long)os_co_wrapper;
105
106
rec->stack_top = jb->Esp + 4;
107
rec->stack_bottom = (unsigned long)rec->stack;
108
109
//wild assumption about SEH frame.. seems to work
110
capture_fs(&temp);
111
rec->seh_frame = temp.seh_frame;
112
}
113
114
static void os_pre_setjmp(cothread_t target)
115
{
116
cothread_struct* rec = (cothread_struct*)target;
117
capture_fs(co_running);
118
rec->caller = co_running;
119
}
120
121
static void os_pre_longjmp(cothread_struct* rec)
122
{
123
restore_fs(rec);
124
}
125
126
cothread_t co_active()
127
{
128
if(!co_running) co_running = &co_primary;
129
return (cothread_t)co_running;
130
}
131
132
133
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
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
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