@@ -40,6 +40,7 @@ static long long get_ticks_per_second() {
4040
4141ErrorOr<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