From 49fa30d495c0524a15ba86668f4fee12b9715089 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 23 Aug 2017 18:52:32 -0700 Subject: Ticket lock for x64/gcc/clang platforms. --- node/Mutex.hpp | 84 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 21 deletions(-) (limited to 'node') diff --git a/node/Mutex.hpp b/node/Mutex.hpp index 854f321a..b16f53f7 100644 --- a/node/Mutex.hpp +++ b/node/Mutex.hpp @@ -32,32 +32,84 @@ #ifdef __UNIX_LIKE__ +#include #include #include namespace ZeroTier { +#if defined(__GNUC__) && (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64)) + +// Inline ticket lock on x64 systems with GCC and CLANG (Mac, Linux) -- this is really fast as long as locking durations are very short class Mutex : NonCopyable { public: - Mutex() + Mutex() : + nextTicket(0), + nowServing(0) { - pthread_mutex_init(&_mh,(const pthread_mutexattr_t *)0); } - ~Mutex() + inline void lock() const { - pthread_mutex_destroy(&_mh); + const uint16_t myTicket = __sync_fetch_and_add(&(const_cast(this)->nextTicket),1); + while (nowServing != myTicket) { + __asm__ __volatile__("rep;nop"::); + __asm__ __volatile__("":::"memory"); + } } - inline void lock() + inline void unlock() const { - pthread_mutex_lock(&_mh); + ++(const_cast(this)->nowServing); } - inline void unlock() + /** + * Uses C++ contexts and constructor/destructor to lock/unlock automatically + */ + class Lock : NonCopyable { - pthread_mutex_unlock(&_mh); + public: + Lock(Mutex &m) : + _m(&m) + { + m.lock(); + } + + Lock(const Mutex &m) : + _m(const_cast(&m)) + { + _m->lock(); + } + + ~Lock() + { + _m->unlock(); + } + + private: + Mutex *const _m; + }; + +private: + uint16_t nextTicket; + uint16_t nowServing; +}; + +#else + +// libpthread based mutex lock +class Mutex : NonCopyable +{ +public: + Mutex() + { + pthread_mutex_init(&_mh,(const pthread_mutexattr_t *)0); + } + + ~Mutex() + { + pthread_mutex_destroy(&_mh); } inline void lock() const @@ -70,9 +122,6 @@ public: (const_cast (this))->unlock(); } - /** - * Uses C++ contexts and constructor/destructor to lock/unlock automatically - */ class Lock : NonCopyable { public: @@ -101,6 +150,8 @@ private: pthread_mutex_t _mh; }; +#endif + } // namespace ZeroTier #endif // Apple / Linux @@ -112,6 +163,7 @@ private: namespace ZeroTier { +// Windows critical section based lock class Mutex : NonCopyable { public: @@ -125,16 +177,6 @@ public: DeleteCriticalSection(&_cs); } - inline void lock() - { - EnterCriticalSection(&_cs); - } - - inline void unlock() - { - LeaveCriticalSection(&_cs); - } - inline void lock() const { (const_cast (this))->lock(); -- cgit v1.2.3