Commit 53d21772 authored by Kenton Varda's avatar Kenton Varda

Use Win32 fibers on Cygwin.

While swapcontext() exists on Cygwin, it seems that throwing an exception in a stack other than the main stack leads to a hang. But the Win32 fiber API seems to work fine.
parent 609679fb
...@@ -896,7 +896,7 @@ private: ...@@ -896,7 +896,7 @@ private:
size_t stackSize; size_t stackSize;
#if _WIN32 #if _WIN32 || __CYGWIN__
void* osFiber; void* osFiber;
#else #else
struct Impl; struct Impl;
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#if _WIN32 #if _WIN32 || __CYGWIN__
#define WIN32_LEAN_AND_MEAN 1 // lolz #define WIN32_LEAN_AND_MEAN 1 // lolz
#elif __APPLE__ #elif __APPLE__
// getcontext() and friends are marked deprecated on MacOS but seemingly no replacement is // getcontext() and friends are marked deprecated on MacOS but seemingly no replacement is
...@@ -39,17 +39,20 @@ ...@@ -39,17 +39,20 @@
#include "threadlocal.h" #include "threadlocal.h"
#include "mutex.h" #include "mutex.h"
#if _WIN32 #if _WIN32 || __CYGWIN__
#include <windows.h> // for Sleep(0) and fibers #include <windows.h> // for Sleep(0) and fibers
#include "windows-sanity.h" #include "windows-sanity.h"
#else #else
#include <sched.h> // just for sched_yield()
#include <ucontext.h> #include <ucontext.h>
#include <sys/mman.h> #include <sys/mman.h> // mmap(), for allocating new stacks
#include <unistd.h> #include <unistd.h> // sysconf()
#include <errno.h> #include <errno.h>
#endif #endif
#if !_WIN32
#include <sched.h> // just for sched_yield()
#endif
#if !KJ_NO_RTTI #if !KJ_NO_RTTI
#include <typeinfo> #include <typeinfo>
#if __GNUC__ #if __GNUC__
...@@ -710,7 +713,7 @@ const Executor& getCurrentThreadExecutor() { ...@@ -710,7 +713,7 @@ const Executor& getCurrentThreadExecutor() {
namespace _ { // private namespace _ { // private
#if !_WIN32 #if !(_WIN32 || __CYGWIN__)
struct FiberBase::Impl { struct FiberBase::Impl {
// This struct serves two purposes: // This struct serves two purposes:
// - It contains OS-specific state that we don't want to declare in the header. // - It contains OS-specific state that we don't want to declare in the header.
...@@ -782,7 +785,7 @@ struct FiberBase::Impl { ...@@ -782,7 +785,7 @@ struct FiberBase::Impl {
#endif #endif
struct FiberBase::StartRoutine { struct FiberBase::StartRoutine {
#if _WIN32 #if _WIN32 || __CYGWIN__
static void WINAPI run(LPVOID ptr) { static void WINAPI run(LPVOID ptr) {
// This is the static C-style function we pass to CreateFiber(). // This is the static C-style function we pass to CreateFiber().
auto& fiber = *reinterpret_cast<FiberBase*>(ptr); auto& fiber = *reinterpret_cast<FiberBase*>(ptr);
...@@ -809,11 +812,11 @@ FiberBase::FiberBase(size_t stackSizeParam, _::ExceptionOrValue& result) ...@@ -809,11 +812,11 @@ FiberBase::FiberBase(size_t stackSizeParam, _::ExceptionOrValue& result)
: state(WAITING), : state(WAITING),
// Force stackSize to a reasonable minimum. // Force stackSize to a reasonable minimum.
stackSize(kj::max(stackSizeParam, 65536)), stackSize(kj::max(stackSizeParam, 65536)),
#if !_WIN32 #if !(_WIN32 || __CYGWIN__)
impl(Impl::alloc(stackSize)), impl(Impl::alloc(stackSize)),
#endif #endif
result(result) { result(result) {
#if _WIN32 #if _WIN32 || __CYGWIN__
auto& eventLoop = currentEventLoop(); auto& eventLoop = currentEventLoop();
if (eventLoop.mainFiber == nullptr) { if (eventLoop.mainFiber == nullptr) {
// First time we've created a fiber. We need to convert the main stack into a fiber as well // First time we've created a fiber. We need to convert the main stack into a fiber as well
...@@ -838,7 +841,7 @@ FiberBase::FiberBase(size_t stackSizeParam, _::ExceptionOrValue& result) ...@@ -838,7 +841,7 @@ FiberBase::FiberBase(size_t stackSizeParam, _::ExceptionOrValue& result)
} }
FiberBase::~FiberBase() noexcept(false) { FiberBase::~FiberBase() noexcept(false) {
#if _WIN32 #if _WIN32 || __CYGWIN__
KJ_DEFER(DeleteFiber(osFiber)); KJ_DEFER(DeleteFiber(osFiber));
#else #else
KJ_DEFER(Impl::free(impl, stackSize)); KJ_DEFER(Impl::free(impl, stackSize));
...@@ -879,7 +882,7 @@ Maybe<Own<Event>> FiberBase::fire() { ...@@ -879,7 +882,7 @@ Maybe<Own<Event>> FiberBase::fire() {
void FiberBase::switchToFiber() { void FiberBase::switchToFiber() {
// Switch from the main stack to the fiber. Returns once the fiber either calls switchToMain() // Switch from the main stack to the fiber. Returns once the fiber either calls switchToMain()
// or returns from its main function. // or returns from its main function.
#if _WIN32 #if _WIN32 || __CYGWIN__
SwitchToFiber(osFiber); SwitchToFiber(osFiber);
#else #else
KJ_SYSCALL(swapcontext(&impl.originalContext, &impl.fiberContext)); KJ_SYSCALL(swapcontext(&impl.originalContext, &impl.fiberContext));
...@@ -888,7 +891,7 @@ void FiberBase::switchToFiber() { ...@@ -888,7 +891,7 @@ void FiberBase::switchToFiber() {
void FiberBase::switchToMain() { void FiberBase::switchToMain() {
// Switch from the fiber to the main stack. Returns the next time the main stack calls // Switch from the fiber to the main stack. Returns the next time the main stack calls
// switchToFiber(). // switchToFiber().
#if _WIN32 #if _WIN32 || __CYGWIN__
SwitchToFiber(currentEventLoop().mainFiber); SwitchToFiber(currentEventLoop().mainFiber);
#else #else
KJ_SYSCALL(swapcontext(&impl.fiberContext, &impl.originalContext)); KJ_SYSCALL(swapcontext(&impl.fiberContext, &impl.originalContext));
...@@ -936,7 +939,7 @@ EventLoop::EventLoop(EventPort& port) ...@@ -936,7 +939,7 @@ EventLoop::EventLoop(EventPort& port)
daemons(kj::heap<TaskSet>(_::LoggingErrorHandler::instance)) {} daemons(kj::heap<TaskSet>(_::LoggingErrorHandler::instance)) {}
EventLoop::~EventLoop() noexcept(false) { EventLoop::~EventLoop() noexcept(false) {
#if _WIN32 #if _WIN32 || __CYGWIN__
KJ_DEFER({ KJ_DEFER({
if (mainFiber != nullptr) { if (mainFiber != nullptr) {
// We converted the thread to a fiber, need to convert it back. // We converted the thread to a fiber, need to convert it back.
......
...@@ -907,7 +907,7 @@ private: ...@@ -907,7 +907,7 @@ private:
Own<TaskSet> daemons; Own<TaskSet> daemons;
#if _WIN32 #if _WIN32 || __CYGWIN__
void* mainFiber = nullptr; void* mainFiber = nullptr;
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment