kicad-developers team mailing list archive
-
kicad-developers team
-
Mailing list archive
-
Message #41284
[PATCH 7/9] MSVC support for libcontext
This uses the Windows native Fiber API.
---
common/system/libcontext.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++
include/system/libcontext.h | 16 ++++++++++-
include/tool/coroutine.h | 8 ++++--
3 files changed, 87 insertions(+), 3 deletions(-)
diff --git a/common/system/libcontext.cpp b/common/system/libcontext.cpp
index f6f83ceae..57478f12c 100644
--- a/common/system/libcontext.cpp
+++ b/common/system/libcontext.cpp
@@ -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
diff --git a/include/system/libcontext.h b/include/system/libcontext.h
index 8045fa2b7..dfa323dcd 100644
--- a/include/system/libcontext.h
+++ b/include/system/libcontext.h
@@ -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
diff --git a/include/tool/coroutine.h b/include/tool/coroutine.h
index 7be173adb..60144ebc0 100644
--- a/include/tool/coroutine.h
+++ b/include/tool/coroutine.h
@@ -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;
References