26 template <
typename _Rep,
typename _Period>
28 std::chrono::duration<_Rep, _Period> d,
29 struct timespec* ts) {
31 time_t(std::chrono::duration_cast<std::chrono::seconds>(d).
count());
32 ts->tv_nsec = long(std::chrono::duration_cast<std::chrono::nanoseconds>(
33 d % std::chrono::seconds(1))
37 #if !FOLLY_HAVE_CLOCK_GETTIME || FOLLY_FORCE_CLOCK_GETTIME_DEFINITION 40 #include <mach/mach_init.h> 41 #include <mach/mach_port.h> 42 #include <mach/mach_time.h> 43 #include <mach/mach_types.h> 44 #include <mach/task.h> 45 #include <mach/thread_act.h> 46 #include <mach/vm_map.h> 48 static std::chrono::nanoseconds time_value_to_ns(time_value_t
t) {
49 return std::chrono::seconds(t.seconds) +
50 std::chrono::microseconds(t.microseconds);
53 static int clock_process_cputime(
struct timespec* ts) {
55 task_thread_times_info thread_times_info;
56 mach_msg_type_number_t thread_times_info_count = TASK_THREAD_TIMES_INFO_COUNT;
57 kern_return_t kern_result = task_info(
59 TASK_THREAD_TIMES_INFO,
60 (thread_info_t)&thread_times_info,
61 &thread_times_info_count);
62 if (
UNLIKELY(kern_result != KERN_SUCCESS)) {
67 mach_task_basic_info task_basic_info;
68 mach_msg_type_number_t task_basic_info_count = MACH_TASK_BASIC_INFO_COUNT;
69 kern_result = task_info(
72 (thread_info_t)&task_basic_info,
73 &task_basic_info_count);
74 if (
UNLIKELY(kern_result != KERN_SUCCESS)) {
78 auto cputime = time_value_to_ns(thread_times_info.user_time) +
79 time_value_to_ns(thread_times_info.system_time) +
80 time_value_to_ns(task_basic_info.user_time) +
81 time_value_to_ns(task_basic_info.system_time);
86 static int clock_thread_cputime(
struct timespec* ts) {
87 mach_msg_type_number_t
count = THREAD_BASIC_INFO_COUNT;
88 thread_basic_info_data_t thread_info_data;
89 thread_act_t thread = mach_thread_self();
90 kern_return_t kern_result = thread_info(
91 thread, THREAD_BASIC_INFO, (thread_info_t)&thread_info_data, &count);
92 mach_port_deallocate(mach_task_self(), thread);
93 if (
UNLIKELY(kern_result != KERN_SUCCESS)) {
96 auto cputime = time_value_to_ns(thread_info_data.system_time) +
97 time_value_to_ns(thread_info_data.user_time);
104 case CLOCK_REALTIME: {
109 case CLOCK_MONOTONIC: {
114 case CLOCK_PROCESS_CPUTIME_ID:
115 return clock_process_cputime(ts);
116 case CLOCK_THREAD_CPUTIME_ID:
117 return clock_thread_cputime(ts);
124 int clock_getres(clockid_t clk_id,
struct timespec* ts) {
125 if (clk_id != CLOCK_MONOTONIC) {
129 static auto info = [] {
130 static mach_timebase_info_data_t
info;
131 auto result = (mach_timebase_info(&info) == KERN_SUCCESS) ? &info :
nullptr;
137 ts->tv_nsec =
info->numer /
info->denom;
141 #elif defined(_WIN32) 149 using unsigned_nanos = std::chrono::duration<uint64_t, std::nano>;
151 static unsigned_nanos filetimeToUnsignedNanos(FILETIME ft) {
153 i.HighPart = ft.dwHighDateTime;
154 i.LowPart = ft.dwLowDateTime;
157 return unsigned_nanos(i.QuadPart * 100);
160 static LARGE_INTEGER performanceFrequency() {
161 static auto result = [] {
164 BOOL res = QueryPerformanceFrequency(&freq);
171 extern "C" int clock_getres(clockid_t clock_id,
struct timespec* res) {
177 static constexpr
size_t kNsPerSec = 1000000000;
179 case CLOCK_REALTIME: {
180 constexpr
auto perSec = double(std::chrono::system_clock::period::num) /
181 std::chrono::system_clock::period::den;
182 res->tv_sec = time_t(perSec);
183 res->tv_nsec = time_t(perSec * kNsPerSec);
186 case CLOCK_MONOTONIC: {
187 constexpr
auto perSec = double(std::chrono::steady_clock::period::num) /
188 std::chrono::steady_clock::period::den;
189 res->tv_sec = time_t(perSec);
190 res->tv_nsec = time_t(perSec * kNsPerSec);
193 case CLOCK_PROCESS_CPUTIME_ID:
194 case CLOCK_THREAD_CPUTIME_ID: {
195 DWORD adj, timeIncrement;
197 if (!GetSystemTimeAdjustment(&adj, &timeIncrement, &adjDisabled)) {
203 res->tv_nsec = long(timeIncrement * 100);
213 extern "C" int clock_gettime(clockid_t clock_id,
struct timespec*
tp) {
219 const auto unanosToTimespec = [](timespec*
tp, unsigned_nanos
t) ->
int {
220 static constexpr unsigned_nanos one_sec{std::chrono::seconds(1)};
222 time_t(std::chrono::duration_cast<std::chrono::seconds>(
t).
count());
223 tp->tv_nsec = long((
t % one_sec).
count());
227 FILETIME createTime, exitTime, kernalTime, userTime;
229 case CLOCK_REALTIME: {
234 case CLOCK_MONOTONIC: {
239 case CLOCK_PROCESS_CPUTIME_ID: {
240 if (!GetProcessTimes(
250 return unanosToTimespec(
252 filetimeToUnsignedNanos(kernalTime) +
253 filetimeToUnsignedNanos(userTime));
255 case CLOCK_THREAD_CPUTIME_ID: {
266 return unanosToTimespec(
268 filetimeToUnsignedNanos(kernalTime) +
269 filetimeToUnsignedNanos(userTime));
278 #error No clock_gettime(3) compatibility wrapper available for this platform. 289 char* asctime_r(
const tm* tm,
char* buf) {
291 if (asctime_s(tmpBuf, tm)) {
295 return strcpy(buf, tmpBuf);
298 char* ctime_r(
const time_t*
t,
char* buf) {
300 if (ctime_s(tmpBuf, 64, t)) {
304 return strcpy(buf, tmpBuf);
307 tm* gmtime_r(
const time_t* t, tm* res) {
308 if (!gmtime_s(res, t)) {
314 tm* localtime_r(
const time_t* t, tm* o) {
315 if (!localtime_s(o, t)) {
321 int nanosleep(
const struct timespec* request,
struct timespec* remain) {
322 Sleep((DWORD)((request->tv_sec * 1000) + (request->tv_nsec / 1000000)));
323 if (remain !=
nullptr) {
331 const char* __restrict
s,
332 const char* __restrict
f,
333 struct tm* __restrict tm) {
340 std::istringstream input(s);
341 input.imbue(std::locale(setlocale(LC_ALL,
nullptr)));
342 input >> std::get_time(tm, f);
346 return const_cast<char*
>(s + input.tellg());
int(* clock_gettime)(clockid_t, timespec *ts)
std::chrono::steady_clock::time_point now()
static void duration_to_ts(std::chrono::duration< _Rep, _Period > d, struct timespec *ts)