MSVC support for libcontext
This uses the Windows native Fiber API.
This commit is contained in:
parent
884ae5a7ff
commit
6cab769f41
|
@ -13,6 +13,8 @@
|
|||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
#include <system/libcontext.h>
|
||||
|
||||
#if defined(LIBCONTEXT_PLATFORM_windows_i386) && defined(LIBCONTEXT_COMPILER_gcc)
|
||||
|
@ -1268,3 +1270,67 @@ __asm (
|
|||
);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(LIBCONTEXT_PLATFORM_msvc_x86_64) || defined(LIBCONTEXT_PLATFORM_msvc_i386)
|
||||
|
||||
#include <map>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace libcontext
|
||||
{
|
||||
|
||||
static int threadHasFibers = 0;
|
||||
|
||||
struct FiberData
|
||||
{
|
||||
intptr_t inValue;
|
||||
intptr_t outValue;
|
||||
void(*entry)(intptr_t);
|
||||
};
|
||||
|
||||
static std::map<fcontext_t, FiberData> fiberParams;
|
||||
|
||||
static void fiberEntry(LPVOID params)
|
||||
{
|
||||
auto ctx = (fcontext_t) GetCurrentFiber();
|
||||
auto& d = fiberParams[ctx];
|
||||
d.entry(d.inValue);
|
||||
}
|
||||
|
||||
fcontext_t LIBCONTEXT_CALL_CONVENTION make_fcontext(void* sp, size_t size, void(*fn)(intptr_t))
|
||||
{
|
||||
if (!threadHasFibers)
|
||||
{
|
||||
ConvertThreadToFiber(nullptr);
|
||||
threadHasFibers = 1;
|
||||
}
|
||||
|
||||
fcontext_t ctx = CreateFiber(size, (LPFIBER_START_ROUTINE) fiberEntry, nullptr );
|
||||
fiberParams[ctx].entry = fn;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
intptr_t LIBCONTEXT_CALL_CONVENTION jump_fcontext(fcontext_t* ofc, fcontext_t nfc,
|
||||
intptr_t vp, bool preserve_fpu)
|
||||
{
|
||||
auto current = (void*)GetCurrentFiber();
|
||||
fiberParams[current].outValue = vp;
|
||||
*ofc = GetCurrentFiber();
|
||||
fiberParams[nfc].inValue = vp;
|
||||
SwitchToFiber(nfc);
|
||||
return fiberParams[*ofc].outValue;
|
||||
}
|
||||
|
||||
}; // namespace libcontext
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#if defined(__GNUC__) || defined(__APPLE__) || defined(__FreeBSD__)
|
||||
|
||||
#undef LIBCONTEXT_HAS_OWN_STACK
|
||||
|
||||
#define LIBCONTEXT_COMPILER_gcc
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
|
@ -46,7 +48,8 @@
|
|||
#ifdef _ARCH_PPC64
|
||||
#define LIBCONTEXT_PLATFORM_linux_ppc64
|
||||
#define LIBCONTEXT_CALL_CONVENTION
|
||||
#elif defined _ARCH_PPC
|
||||
#endif
|
||||
#ifdef _ARCH_PPC
|
||||
#define LIBCONTEXT_PLATFORM_linux_ppc32
|
||||
#define LIBCONTEXT_CALL_CONVENTION
|
||||
#endif
|
||||
|
@ -73,6 +76,17 @@
|
|||
#define LIBCONTEXT_CALL_CONVENTION
|
||||
#endif
|
||||
#endif
|
||||
#elif defined (_MSC_VER)
|
||||
|
||||
#define LIBCONTEXT_HAS_OWN_STACK
|
||||
|
||||
#define LIBCONTEXT_CALL_CONVENTION __cdecl
|
||||
|
||||
#if defined(_WIN64)
|
||||
#define LIBCONTEXT_PLATFORM_msvc_x86_64
|
||||
#elif defined(_WIN32)
|
||||
#define LIBCONTEXT_PLATFORM_msvc_i386
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -294,15 +294,19 @@ private:
|
|||
|
||||
assert( m_stack == nullptr );
|
||||
|
||||
// fixme: Clean up stack stuff. Add a guard
|
||||
size_t stackSize = c_defaultStackSize;
|
||||
void* sp = nullptr;
|
||||
|
||||
#ifndef LIBCONTEXT_HAS_OWN_STACK
|
||||
// fixme: Clean up stack stuff. Add a guard
|
||||
m_stack.reset( new char[stackSize] );
|
||||
|
||||
// align to 16 bytes
|
||||
void* sp = (void*)((((ptrdiff_t) m_stack.get()) + stackSize - 0xf) & (~0x0f));
|
||||
sp = (void*)((((ptrdiff_t) m_stack.get()) + stackSize - 0xf) & (~0x0f));
|
||||
|
||||
// correct the stack size
|
||||
stackSize -= size_t( ( (ptrdiff_t) m_stack.get() + stackSize ) - (ptrdiff_t) sp );
|
||||
#endif
|
||||
|
||||
m_callee = libcontext::make_fcontext( sp, stackSize, callerStub );
|
||||
m_running = true;
|
||||
|
|
Loading…
Reference in New Issue