Commit 483f53e4 authored by zyearn's avatar zyearn

- use native clock_gettime after macos 10.12

- fix the initialization order problem of s_futex_map
parent 25e93185
...@@ -450,11 +450,7 @@ int pthread_fd_wait(int fd, unsigned events, ...@@ -450,11 +450,7 @@ int pthread_fd_wait(int fd, unsigned events,
int diff_ms = -1; int diff_ms = -1;
if (abstime) { if (abstime) {
timespec now; timespec now;
#ifdef __MACH__
clock_gettime(CALENDAR_CLOCK, &now);
#else
clock_gettime(CLOCK_REALTIME, &now); clock_gettime(CLOCK_REALTIME, &now);
#endif
int64_t now_us = butil::timespec_to_microseconds(now); int64_t now_us = butil::timespec_to_microseconds(now);
int64_t abstime_us = butil::timespec_to_microseconds(*abstime); int64_t abstime_us = butil::timespec_to_microseconds(*abstime);
if (abstime_us <= now_us) { if (abstime_us <= now_us) {
......
...@@ -45,12 +45,25 @@ public: ...@@ -45,12 +45,25 @@ public:
int32_t ref; int32_t ref;
}; };
static std::unordered_map<void*, SimuFutex> s_futex_map;
static pthread_mutex_t s_futex_map_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t s_futex_map_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_once_t init_futex_map_once = PTHREAD_ONCE_INIT;
static std::unordered_map<void*, SimuFutex>* s_futex_map = NULL;
static void InitFutexMap() {
// Leave memory to process's clean up.
s_futex_map = new (std::nothrow) std::unordered_map<void*, SimuFutex>();
if (NULL == s_futex_map) {
exit(1);
}
return;
}
int futex_wait_private(void* addr1, int expected, const timespec* timeout) { int futex_wait_private(void* addr1, int expected, const timespec* timeout) {
if (pthread_once(&init_futex_map_once, InitFutexMap) != 0) {
LOG(FATAL) << "Fail to pthread_once";
exit(1);
}
std::unique_lock<pthread_mutex_t> mu(s_futex_map_mutex); std::unique_lock<pthread_mutex_t> mu(s_futex_map_mutex);
SimuFutex& simu_futex = s_futex_map[addr1]; SimuFutex& simu_futex = (*s_futex_map)[addr1];
++simu_futex.ref; ++simu_futex.ref;
mu.unlock(); mu.unlock();
...@@ -80,16 +93,20 @@ int futex_wait_private(void* addr1, int expected, const timespec* timeout) { ...@@ -80,16 +93,20 @@ int futex_wait_private(void* addr1, int expected, const timespec* timeout) {
std::unique_lock<pthread_mutex_t> mu1(s_futex_map_mutex); std::unique_lock<pthread_mutex_t> mu1(s_futex_map_mutex);
if (--simu_futex.ref == 0) { if (--simu_futex.ref == 0) {
s_futex_map.erase(addr1); s_futex_map->erase(addr1);
} }
mu1.unlock(); mu1.unlock();
return rc; return rc;
} }
int futex_wake_private(void* addr1, int nwake) { int futex_wake_private(void* addr1, int nwake) {
if (pthread_once(&init_futex_map_once, InitFutexMap) != 0) {
LOG(FATAL) << "Fail to pthread_once";
exit(1);
}
std::unique_lock<pthread_mutex_t> mu(s_futex_map_mutex); std::unique_lock<pthread_mutex_t> mu(s_futex_map_mutex);
auto it = s_futex_map.find(addr1); auto it = s_futex_map->find(addr1);
if (it == s_futex_map.end()) { if (it == s_futex_map->end()) {
return 0; return 0;
} }
SimuFutex& simu_futex = it->second; SimuFutex& simu_futex = it->second;
...@@ -113,7 +130,7 @@ int futex_wake_private(void* addr1, int nwake) { ...@@ -113,7 +130,7 @@ int futex_wake_private(void* addr1, int nwake) {
std::unique_lock<pthread_mutex_t> mu2(s_futex_map_mutex); std::unique_lock<pthread_mutex_t> mu2(s_futex_map_mutex);
if (--simu_futex.ref == 0) { if (--simu_futex.ref == 0) {
s_futex_map.erase(addr1); s_futex_map->erase(addr1);
} }
mu2.unlock(); mu2.unlock();
return nwakedup; return nwakedup;
......
...@@ -35,13 +35,7 @@ int64_t monotonic_time_ns() { ...@@ -35,13 +35,7 @@ int64_t monotonic_time_ns() {
// use the RAW version does not make sense anymore. // use the RAW version does not make sense anymore.
// NOTE: Not inline to keep ABI-compatible with previous versions. // NOTE: Not inline to keep ABI-compatible with previous versions.
timespec now; timespec now;
#ifdef __MACH__
// The value returned is a monotonically increasing value according to
// https://opensource.apple.com/source/xnu/xnu-792.13.8/osfmk/man/clock_get_time.html
clock_gettime(CALENDAR_CLOCK, &now);
#else
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
#endif
return now.tv_sec * 1000000000L + now.tv_nsec; return now.tv_sec * 1000000000L + now.tv_nsec;
} }
......
...@@ -28,7 +28,12 @@ ...@@ -28,7 +28,12 @@
#include <mach/clock.h> #include <mach/clock.h>
#include <mach/mach.h> #include <mach/mach.h>
inline int clock_gettime(clock_id_t id, timespec* time) { # ifndef clock_gettime
# define CLOCK_REALTIME CALENDAR_CLOCK
# define CLOCK_MONOTONIC SYSTEM_CLOCK
typedef int clockid_t;
inline int clock_gettime(clockid_t id, timespec* time) {
// clock_gettime is not available in MacOS, use clock_get_time instead // clock_gettime is not available in MacOS, use clock_get_time instead
clock_serv_t cclock; clock_serv_t cclock;
mach_timespec_t mts; mach_timespec_t mts;
...@@ -39,6 +44,7 @@ inline int clock_gettime(clock_id_t id, timespec* time) { ...@@ -39,6 +44,7 @@ inline int clock_gettime(clock_id_t id, timespec* time) {
time->tv_nsec = mts.tv_nsec; time->tv_nsec = mts.tv_nsec;
return 0; return 0;
} }
# endif
#endif #endif
namespace butil { namespace butil {
...@@ -104,11 +110,7 @@ inline timespec seconds_from(timespec start_time, int64_t seconds) { ...@@ -104,11 +110,7 @@ inline timespec seconds_from(timespec start_time, int64_t seconds) {
// -------------------------------------------------------------------- // --------------------------------------------------------------------
inline timespec nanoseconds_from_now(int64_t nanoseconds) { inline timespec nanoseconds_from_now(int64_t nanoseconds) {
timespec time; timespec time;
#ifdef __MACH__
clock_gettime(CALENDAR_CLOCK, &time);
#else
clock_gettime(CLOCK_REALTIME, &time); clock_gettime(CLOCK_REALTIME, &time);
#endif
return nanoseconds_from(time, nanoseconds); return nanoseconds_from(time, nanoseconds);
} }
...@@ -126,11 +128,7 @@ inline timespec seconds_from_now(int64_t seconds) { ...@@ -126,11 +128,7 @@ inline timespec seconds_from_now(int64_t seconds) {
inline timespec timespec_from_now(const timespec& span) { inline timespec timespec_from_now(const timespec& span) {
timespec time; timespec time;
#ifdef __MACH__
clock_gettime(CALENDAR_CLOCK, &time);
#else
clock_gettime(CLOCK_REALTIME, &time); clock_gettime(CLOCK_REALTIME, &time);
#endif
timespec_add(&time, span); timespec_add(&time, span);
return time; return time;
} }
......
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