Path: blob/master/libsnes/libco_msvc_win32/trying-to-port-to-mingw-win32.c
2 views
//links of interest1//http://connect.microsoft.com/VisualStudio/feedback/details/100319/really-wierd-behaviour-in-crt-io-coupled-with-some-inline-assembly2//http://en.wikipedia.org/wiki/Thread_Information_Block3//http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/72093e46-4524-4f54-9f36-c7e8a309d1db/ //FS warning45#define LIBCO_C6#define LIBCO_EXPORT7#include "../bsnes/libco/libco.h"8#include <stdlib.h>9#include <setjmp.h>1011#ifdef __cplusplus12extern "C" {13#endif1415typedef void (*coentry_t)(void);1617typedef struct18{19jmp_buf context;20coentry_t coentry;21void *stack;22unsigned long seh_frame, stack_top, stack_bottom;23cothread_t caller;24} cothread_struct;2526static thread_local cothread_struct co_primary;27static thread_local cothread_struct *co_running = 0;2829#define WINVER 0x040030#define _WIN32_WINNT 0x040031#define WIN32_LEAN_AND_MEAN32#include <windows.h>3334#ifndef _MSC_VER35typedef struct __JUMP_BUFFER {36unsigned long Ebp;37unsigned long Ebx;38unsigned long Edi;39unsigned long Esi;40unsigned long Esp;41unsigned long Eip;42unsigned long Registration;43unsigned long TryLevel;44unsigned long Cookie;45unsigned long UnwindFunc;46unsigned long UnwindData[6];47} _JUMP_BUFFER;48#endif4950#pragma warning(disable:4733)51#pragma warning(disable:4311)5253static void capture_fs(cothread_struct* rec)54{55asm(56"mov %0, dword ptr fs:[0];"57"mov %1, dword ptr fs:[4];"58"mov %2, dword ptr fs:[8];"59:"=r"(rec->seh_frame), "=r"(rec->stack_top), "=r"(rec->stack_bottom)60:61:62);63}6465static void restore_fs(cothread_struct* rec)66{67asm(68"mov dword ptr fs:[0], %0;"69"mov dword ptr fs:[4], %1;"70"mov dword ptr fs:[8], %2;"71:72:"r"(rec->seh_frame), "r"(rec->stack_top), "r"(rec->stack_bottom)73:74);75}7677static void os_co_wrapper()78{79cothread_struct* rec = (cothread_struct*)co_active();80//__try81//{82rec->coentry();83//}84//__except(EXCEPTION_EXECUTE_HANDLER)85//{86// //unhandled win32 exception in coroutine.87// //this coroutine will now be suspended permanently and control will be yielded to caller, for lack of anything better to do.88// //perhaps the process should just terminate.89// for(;;)90// {91// //dead coroutine92// co_switch(rec->caller);93// }94//}95}9697static void os_co_create(cothread_struct* rec, unsigned int size, coentry_t coentry)98{99_JUMP_BUFFER* jb = (_JUMP_BUFFER*)&rec->context;100cothread_struct temp;101102jb->Esp = (unsigned long)rec->stack + size - 4;103jb->Eip = (unsigned long)os_co_wrapper;104105rec->stack_top = jb->Esp + 4;106rec->stack_bottom = (unsigned long)rec->stack;107108//wild assumption about SEH frame.. seems to work109capture_fs(&temp);110rec->seh_frame = temp.seh_frame;111}112113static void os_pre_setjmp(cothread_t target)114{115cothread_struct* rec = (cothread_struct*)target;116capture_fs(co_running);117rec->caller = co_running;118}119120static void os_pre_longjmp(cothread_struct* rec)121{122restore_fs(rec);123}124125cothread_t co_active()126{127if(!co_running) co_running = &co_primary;128return (cothread_t)co_running;129}130131132cothread_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}151152void 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}163164void 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