|
|
|
|
@ -32,32 +32,84 @@
|
|
|
|
|
|
|
|
|
|
#ifdef __UNIX_LIKE__ |
|
|
|
|
|
|
|
|
|
#include <stdint.h> |
|
|
|
|
#include <stdlib.h> |
|
|
|
|
#include <pthread.h> |
|
|
|
|
|
|
|
|
|
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<Mutex *>(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<Mutex *>(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<Mutex *>(&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 <Mutex *> (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 <Mutex *> (this))->lock(); |
|
|
|
|
|