2 * Copyright 2016 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <folly/detail/Clock.h>
21 #include <mach/mach_time.h>
25 const mach_timebase_info_data_t* tbInfo() {
26 static auto info = [] {
27 static mach_timebase_info_data_t info;
28 return (mach_timebase_info(&info) == KERN_SUCCESS) ? &info : nullptr;
33 } // anonymous namespace
35 int clock_gettime(clockid_t clk_id, struct timespec* ts) {
36 auto tb_info = tbInfo();
37 if (tb_info == nullptr) {
42 uint64_t now_ticks = mach_absolute_time();
43 uint64_t now_ns = (now_ticks * tb_info->numer) / tb_info->denom;
44 ts->tv_sec = now_ns / 1000000000;
45 ts->tv_nsec = now_ns % 1000000000;
50 int clock_getres(clockid_t clk_id, struct timespec* ts) {
51 auto tb_info = tbInfo();
52 if (tb_info == nullptr) {
58 ts->tv_nsec = tb_info->numer / tb_info->denom;
62 #elif defined(_MSC_VER)
63 // The MSVC version has been extracted from the pthreads implemenation here:
64 // https://github.com/songdongsheng/libpthread
65 // Copyright(c) 2011, Dongsheng Song <songdongsheng@live.cn>
67 // It is under the Apache License Version 2.0, just as the rest of the file is.
68 // It has been mostly stripped down to what we have.
72 #define DELTA_EPOCH_IN_100NS INT64_C(116444736000000000)
73 #define POW10_7 INT64_C(10000000)
74 #define POW10_9 INT64_C(1000000000)
76 int clock_getres(clockid_t clock_id, struct timespec *res)
83 if (QueryPerformanceFrequency(&pf) == 0)
87 res->tv_nsec = (int)((POW10_9 + (pf.QuadPart >> 1)) / pf.QuadPart);
95 case CLOCK_PROCESS_CPUTIME_ID:
96 case CLOCK_THREAD_CPUTIME_ID:
98 DWORD timeAdjustment, timeIncrement;
99 BOOL isTimeAdjustmentDisabled;
101 (void)GetSystemTimeAdjustment(
104 &isTimeAdjustmentDisabled
107 res->tv_nsec = timeIncrement * 100;
118 int clock_gettime(clockid_t clock_id, struct timespec *tp)
121 LARGE_INTEGER pf, pc;
123 unsigned __int64 u64;
130 GetSystemTimeAsFileTime(&ct.ft);
131 t = ct.u64 - DELTA_EPOCH_IN_100NS;
132 tp->tv_sec = t / POW10_7;
133 tp->tv_nsec = ((int)(t % POW10_7)) * 100;
138 case CLOCK_MONOTONIC:
140 if (QueryPerformanceFrequency(&pf) == 0)
143 if (QueryPerformanceCounter(&pc) == 0)
146 tp->tv_sec = pc.QuadPart / pf.QuadPart;
148 ((pc.QuadPart % pf.QuadPart) * POW10_9 + (pf.QuadPart >> 1)) /
151 if (tp->tv_nsec >= POW10_9) {
153 tp->tv_nsec -= POW10_9;
159 case CLOCK_PROCESS_CPUTIME_ID:
161 if (0 == GetProcessTimes(GetCurrentProcess(),
162 &ct.ft, &et.ft, &kt.ft, &ut.ft)) {
166 tp->tv_sec = t / POW10_7;
167 tp->tv_nsec = ((int)(t % POW10_7)) * 100;
172 case CLOCK_THREAD_CPUTIME_ID:
174 if (0 == GetThreadTimes(GetCurrentThread(),
175 &ct.ft, &et.ft, &kt.ft, &ut.ft)) {
179 tp->tv_sec = t / POW10_7;
180 tp->tv_nsec = ((int)(t % POW10_7)) * 100;
191 #elif defined(__CYGWIN__) || defined(__MINGW__)
192 // using winpthreads from mingw-w64
193 // <pthreads_time.h> has clock_gettime and friends
194 // make sure to include <pthread.h> as well for typedefs of timespec/etc
196 #error No clock_gettime(2) compatibility wrapper available for this platform.