ClickHouse/base/common/sleep.cpp

66 lines
1.9 KiB
C++
Raw Normal View History

2019-07-10 20:47:39 +00:00
#include "common/sleep.h"
2019-07-05 13:48:47 +00:00
#include <time.h>
#include <errno.h>
#if defined(OS_DARWIN)
2019-09-21 18:30:01 +00:00
#include <mach/mach.h>
#include <mach/mach_time.h>
#endif
2019-07-05 13:48:47 +00:00
/**
2019-07-10 20:47:39 +00:00
* Sleep with nanoseconds precision. Tolerant to signal interruptions
2019-07-05 13:48:47 +00:00
*
* In case query profiler is turned on, all threads spawned for
* query execution are repeatedly interrupted by signals from timer.
* Functions for relative sleep (sleep(3), nanosleep(2), etc.) have
* problems in this setup and man page for nanosleep(2) suggests
* using absolute deadlines, for instance clock_nanosleep(2).
*/
2019-07-10 20:47:39 +00:00
void sleepForNanoseconds(uint64_t nanoseconds)
{
#if defined(OS_DARWIN)
2019-09-21 18:30:01 +00:00
//https://developer.apple.com/library/archive/technotes/tn2169/_index.html
//https://dshil.github.io/blog/missed-os-x-clock-guide/
static mach_timebase_info_data_t timebase_info = {0};
2019-09-21 20:44:56 +00:00
if (timebase_info.denom == 0)
2019-09-21 18:30:01 +00:00
mach_timebase_info(&timebase_info);
uint64_t time_to_wait = nanoseconds * timebase_info.denom / timebase_info.numer;
uint64_t now = mach_absolute_time();
2019-09-21 20:44:56 +00:00
while (mach_wait_until(now + time_to_wait) != KERN_SUCCESS);
2019-09-21 18:30:01 +00:00
#else
2019-07-10 20:47:39 +00:00
constexpr auto clock_type = CLOCK_MONOTONIC;
struct timespec current_time;
clock_gettime(clock_type, &current_time);
2019-07-10 20:47:39 +00:00
constexpr uint64_t resolution = 1'000'000'000;
struct timespec finish_time = current_time;
finish_time.tv_nsec += nanoseconds % resolution;
2019-05-19 09:14:23 +00:00
const uint64_t extra_second = finish_time.tv_nsec / resolution;
finish_time.tv_nsec %= resolution;
finish_time.tv_sec += (nanoseconds / resolution) + extra_second;
while (clock_nanosleep(clock_type, TIMER_ABSTIME, &finish_time, nullptr) == EINTR);
2019-09-15 10:35:19 +00:00
#endif
}
2019-07-10 20:47:39 +00:00
void sleepForMicroseconds(uint64_t microseconds)
{
2019-07-10 20:47:39 +00:00
sleepForNanoseconds(microseconds * 1000);
}
2019-07-10 20:47:39 +00:00
void sleepForMilliseconds(uint64_t milliseconds)
{
2019-07-10 20:47:39 +00:00
sleepForMicroseconds(milliseconds * 1000);
}
2019-07-10 20:47:39 +00:00
void sleepForSeconds(uint64_t seconds)
{
2019-07-10 20:47:39 +00:00
sleepForMilliseconds(seconds * 1000);
}