Skip to content

Commit 5b5ed2e

Browse files
add two more clock
1 parent e7f8e70 commit 5b5ed2e

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

libc/include/llvm-libc-macros/windows/time-macros-ext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@
1111

1212
#define CLOCK_MONOTONIC 0
1313
#define CLOCK_REALTIME 1
14+
#define CLOCK_PROCESS_CPUTIME_ID 2
15+
#define CLOCK_THREAD_CPUTIME_ID 3
1416

1517
#endif // LLVM_LIBC_MACROS_WINDOWS_TIME_MACROS_EXT_H

libc/src/__support/time/windows/clock_gettime.cpp

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ static long long get_ticks_per_second() {
4040

4141
ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
4242
using namespace time_units;
43+
constexpr unsigned long long HNS_PER_SEC = 1_s_ns / 100ULL;
4344
constexpr long long SEC_LIMIT =
4445
cpp::numeric_limits<decltype(ts->tv_sec)>::max();
4546
ErrorOr<int> ret = 0;
@@ -81,7 +82,6 @@ ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
8182
time.HighPart = file_time.dwHighDateTime;
8283

8384
// adjust to POSIX epoch (from Jan 1, 1601 to Jan 1, 1970)
84-
constexpr unsigned long long HNS_PER_SEC = 1_s_ns / 100ULL;
8585
constexpr unsigned long long POSIX_TIME_SHIFT =
8686
(11644473600ULL * HNS_PER_SEC);
8787
if (LIBC_UNLIKELY(POSIX_TIME_SHIFT > time.QuadPart)) {
@@ -99,6 +99,54 @@ ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
9999
ts->tv_nsec = static_cast<decltype(ts->tv_nsec)>(tv_nsec);
100100
break;
101101
}
102+
case CLOCK_PROCESS_CPUTIME_ID:
103+
case CLOCK_THREAD_CPUTIME_ID: {
104+
[[clang::uninitialized]] FILETIME creation_time;
105+
[[clang::uninitialized]] FILETIME exit_time;
106+
[[clang::uninitialized]] FILETIME kernel_time;
107+
[[clang::uninitialized]] FILETIME user_time;
108+
bool success;
109+
if (clockid == CLOCK_PROCESS_CPUTIME_ID) {
110+
// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocesstimes
111+
success = ::GetProcessTimes(::GetCurrentProcess(), &creation_time,
112+
&exit_time, &kernel_time, &user_time);
113+
} else {
114+
// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadtimes
115+
success = ::GetThreadTimes(::GetCurrentThread(), &creation_time,
116+
&exit_time, &kernel_time, &user_time);
117+
}
118+
if (!success) {
119+
ret = cpp::unexpected(EINVAL);
120+
break;
121+
}
122+
// https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
123+
// It is not recommended that you add and subtract values from the FILETIME
124+
// structure to obtain relative times. Instead, you should copy the low- and
125+
// high-order parts of the file time to a ULARGE_INTEGER structure, perform
126+
// 64-bit arithmetic on the QuadPart member, and copy the LowPart and
127+
// HighPart members into the FILETIME structure.
128+
auto kernel_time_hns = cpp::bit_cast<ULARGE_INTEGER>(kernel_time);
129+
auto user_time_hns = cpp::bit_cast<ULARGE_INTEGER>(user_time);
130+
auto total_time_hns = kernel_time_hns.QuadPart + user_time_hns.QuadPart;
131+
132+
if (LIBC_UNLIKELY(tv_sec > SEC_LIMIT)) {
133+
ret = cpp::unexpected(EOVERFLOW);
134+
break;
135+
}
136+
137+
unsigned long long tv_sec = total_time_hns / HNS_PER_SEC;
138+
unsigned long long tv_nsec = (total_time_hns % HNS_PER_SEC) * 100ULL;
139+
140+
if (LIBC_UNLIKELY(tv_sec > SEC_LIMIT)) {
141+
ret = cpp::unexpected(EOVERFLOW);
142+
break;
143+
}
144+
145+
ts->tv_sec = static_cast<decltype(ts->tv_sec)>(tv_sec);
146+
ts->tv_nsec = static_cast<decltype(ts->tv_nsec)>(tv_nsec);
147+
148+
break;
149+
}
102150
}
103151
return ret;
104152
}

0 commit comments

Comments
 (0)