Path: blob/master/libsnes/libco_msvc_win32/libco_msvc_win32.c
2 views
/*1libco.sjlj (2008-01-28)2author: Nach3license: public domain4*/56/*7* Note this was designed for UNIX systems. Based on ideas expressed in a paper8* by Ralf Engelschall.9* For SJLJ on other systems, one would want to rewrite springboard() and10* co_create() and hack the jmb_buf stack pointer.11*/1213#define LIBCO_C14#define LIBCO_EXPORT15#include "../bsnes/libco/libco.h"16#include <stdlib.h>17#include <setjmp.h>1819#ifdef __cplusplus20extern "C" {21#endif2223typedef struct24{25jmp_buf context;26coentry_t coentry;27void *stack;28unsigned long seh_frame, stack_top, stack_bottom;29cothread_t caller;30} cothread_struct;3132static thread_local cothread_struct co_primary;33static thread_local cothread_struct *co_running = 0;343536//links of interest37//http://connect.microsoft.com/VisualStudio/feedback/details/100319/really-wierd-behaviour-in-crt-io-coupled-with-some-inline-assembly38//http://en.wikipedia.org/wiki/Thread_Information_Block39//http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/72093e46-4524-4f54-9f36-c7e8a309d1db/ //FS warning404142#define WINVER 0x040043#define _WIN32_WINNT 0x040044#define WIN32_LEAN_AND_MEAN45#include <windows.h>4647#pragma warning(disable:4733)48#pragma warning(disable:4311)4950static void capture_fs(cothread_struct* rec)51{52int temp;53__asm mov eax, dword ptr fs:[0];54__asm mov temp, eax;55rec->seh_frame = temp;56__asm mov eax, dword ptr fs:[4];57__asm mov temp, eax;58rec->stack_top = temp;59__asm mov eax, dword ptr fs:[8];60__asm mov temp, eax;61rec->stack_bottom = temp;62}6364static void restore_fs(cothread_struct* rec)65{66int temp;67temp = rec->seh_frame;68__asm mov eax, temp;69__asm mov dword ptr fs:[0], eax70temp = rec->stack_top;71__asm mov eax, temp;72__asm mov dword ptr fs:[4], eax73temp = rec->stack_bottom;74__asm mov eax, temp;75__asm mov dword ptr fs:[8], eax76}7778static void os_co_wrapper()79{80cothread_struct* rec = (cothread_struct*)co_active();81//__try82//{83rec->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 coroutine93// co_switch(rec->caller);94// }95//}96}9798static void os_co_create(cothread_struct* rec, unsigned int size, coentry_t coentry)99{100_JUMP_BUFFER* jb = (_JUMP_BUFFER*)&rec->context;101cothread_struct temp;102103jb->Esp = (unsigned long)rec->stack + size - 4;104jb->Eip = (unsigned long)os_co_wrapper;105106rec->stack_top = jb->Esp + 4;107rec->stack_bottom = (unsigned long)rec->stack;108109//wild assumption about SEH frame.. seems to work110capture_fs(&temp);111rec->seh_frame = temp.seh_frame;112}113114static void os_pre_setjmp(cothread_t target)115{116cothread_struct* rec = (cothread_struct*)target;117capture_fs(co_running);118rec->caller = co_running;119}120121static void os_pre_longjmp(cothread_struct* rec)122{123restore_fs(rec);124}125126__declspec(dllexport) cothread_t co_active()127{128if(!co_running) co_running = &co_primary;129return (cothread_t)co_running;130}131132__declspec(dllexport) cothread_t co_create(unsigned int size, void (*coentry)(void))133{134cothread_struct *thread;135136if(!co_running) co_running = &co_primary;137138thread = (cothread_struct*)malloc(sizeof(cothread_struct));139if(thread)140{141thread->coentry = coentry;142thread->stack = malloc(size);143{144setjmp(thread->context);145os_co_create(thread,size,coentry);146}147}148149return (cothread_t)thread;150}151152__declspec(dllexport) void co_delete(cothread_t cothread)153{154if(cothread)155{156if(((cothread_struct*)cothread)->stack)157{158free(((cothread_struct*)cothread)->stack);159}160free(cothread);161}162}163164__declspec(dllexport) void co_switch(cothread_t cothread)165{166os_pre_setjmp(cothread);167if(!setjmp(co_running->context))168{169co_running = (cothread_struct*)cothread;170os_pre_longjmp(co_running);171longjmp(co_running->context,0);172}173}174175#ifdef __cplusplus176}177#endif178179180