Commit ce8d05a7 authored by Kenton Varda's avatar Kenton Varda

Use Win32 synchronization APIs on Cygwin.

They are more efficient, and self-contained enough not to create trouble.

Also, Cygwin's pthread_rwlock implementation appears buggy. I am seeing it allow double locks from time to time.
parent 3d2a505f
...@@ -120,7 +120,7 @@ TEST(Mutex, MutexGuarded) { ...@@ -120,7 +120,7 @@ TEST(Mutex, MutexGuarded) {
EXPECT_EQ(321u, *value.lockExclusive()); EXPECT_EQ(321u, *value.lockExclusive());
#if !_WIN32 // Not checked on win32. #if !_WIN32 && !__CYGWIN__ // Not checked on win32.
EXPECT_DEBUG_ANY_THROW(value.getAlreadyLockedExclusive()); EXPECT_DEBUG_ANY_THROW(value.getAlreadyLockedExclusive());
EXPECT_DEBUG_ANY_THROW(value.getAlreadyLockedShared()); EXPECT_DEBUG_ANY_THROW(value.getAlreadyLockedShared());
#endif #endif
......
...@@ -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
#define WINVER 0x0600 #define WINVER 0x0600
#define _WIN32_WINNT 0x0600 #define _WIN32_WINNT 0x0600
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "mutex.h" #include "mutex.h"
#include "debug.h" #include "debug.h"
#if !_WIN32 #if !_WIN32 && !__CYGWIN__
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#endif #endif
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
#define FUTEX_WAKE_PRIVATE FUTEX_WAKE #define FUTEX_WAKE_PRIVATE FUTEX_WAKE
#endif #endif
#elif _WIN32 #elif _WIN32 || __CYGWIN__
#include <windows.h> #include <windows.h>
#endif #endif
...@@ -95,7 +95,7 @@ bool Mutex::checkPredicate(Waiter& waiter) { ...@@ -95,7 +95,7 @@ bool Mutex::checkPredicate(Waiter& waiter) {
return result; return result;
} }
#if !_WIN32 #if !_WIN32 && !__CYGWIN__
namespace { namespace {
TimePoint toTimePoint(struct timespec ts) { TimePoint toTimePoint(struct timespec ts) {
...@@ -422,7 +422,7 @@ void Once::reset() { ...@@ -422,7 +422,7 @@ void Once::reset() {
} }
} }
#elif _WIN32 #elif _WIN32 || __CYGWIN__
// ======================================================================================= // =======================================================================================
// Win32 implementation // Win32 implementation
......
...@@ -33,8 +33,14 @@ ...@@ -33,8 +33,14 @@
#define KJ_USE_FUTEX 1 #define KJ_USE_FUTEX 1
#endif #endif
#if !KJ_USE_FUTEX && !_WIN32 #if !KJ_USE_FUTEX && !_WIN32 && !__CYGWIN__
// On Linux we use futex. On other platforms we wrap pthreads. // We fall back to pthreads when we don't have a better platform-specific primitive. pthreads
// mutexes are bloated, though, so we like to avoid them. Hence on Linux we use futex(), and on
// Windows we use SRW locks and friends. On Cygwin we prefer the Win32 primitives both because they
// are more efficient and because I ran into problems with Cygwin's implementation of RW locks
// seeming to allow multiple threads to lock the same mutex (but I didn't investigate very
// closely).
//
// TODO(someday): Write efficient low-level locking primitives for other platforms. // TODO(someday): Write efficient low-level locking primitives for other platforms.
#include <pthread.h> #include <pthread.h>
#endif #endif
...@@ -101,7 +107,7 @@ private: ...@@ -101,7 +107,7 @@ private:
static constexpr uint EXCLUSIVE_REQUESTED = 1u << 30; static constexpr uint EXCLUSIVE_REQUESTED = 1u << 30;
static constexpr uint SHARED_COUNT_MASK = EXCLUSIVE_REQUESTED - 1; static constexpr uint SHARED_COUNT_MASK = EXCLUSIVE_REQUESTED - 1;
#elif _WIN32 #elif _WIN32 || __CYGWIN__
uintptr_t srwLock; // Actually an SRWLOCK, but don't want to #include <windows.h> in header. uintptr_t srwLock; // Actually an SRWLOCK, but don't want to #include <windows.h> in header.
#else #else
...@@ -116,7 +122,7 @@ private: ...@@ -116,7 +122,7 @@ private:
#if KJ_USE_FUTEX #if KJ_USE_FUTEX
uint futex; uint futex;
bool hasTimeout; bool hasTimeout;
#elif _WIN32 #elif _WIN32 || __CYGWIN__
uintptr_t condvar; uintptr_t condvar;
// Actually CONDITION_VARIABLE, but don't want to #include <windows.h> in header. // Actually CONDITION_VARIABLE, but don't want to #include <windows.h> in header.
#else #else
...@@ -135,7 +141,7 @@ private: ...@@ -135,7 +141,7 @@ private:
inline void addWaiter(Waiter& waiter); inline void addWaiter(Waiter& waiter);
inline void removeWaiter(Waiter& waiter); inline void removeWaiter(Waiter& waiter);
bool checkPredicate(Waiter& waiter); bool checkPredicate(Waiter& waiter);
#if _WIN32 #if _WIN32 || __CYGWIN__
void wakeReadyWaiter(Waiter* waiterToSkip); void wakeReadyWaiter(Waiter* waiterToSkip);
#endif #endif
}; };
...@@ -160,7 +166,7 @@ public: ...@@ -160,7 +166,7 @@ public:
void runOnce(Initializer& init); void runOnce(Initializer& init);
#if _WIN32 // TODO(perf): Can we make this inline on win32 somehow? #if _WIN32 || __CYGWIN__ // TODO(perf): Can we make this inline on win32 somehow?
bool isInitialized() noexcept; bool isInitialized() noexcept;
#else #else
...@@ -190,7 +196,7 @@ private: ...@@ -190,7 +196,7 @@ private:
INITIALIZED INITIALIZED
}; };
#elif _WIN32 #elif _WIN32 || __CYGWIN__
uintptr_t initOnce; // Actually an INIT_ONCE, but don't want to #include <windows.h> in header. uintptr_t initOnce; // Actually an INIT_ONCE, but don't want to #include <windows.h> in header.
#else #else
......
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