win32: Support more clockid_t

Add `CLOCK_PROCESS_CPUTIME_ID` and `CLOCK_THREAD_CPUTIME_ID`.
This commit is contained in:
Nobuyoshi Nakada 2025-10-16 10:41:40 +09:00 committed by Nobuyoshi Nakada
parent ff6bd7fb4e
commit b2d4dc9c46
Notes: git 2025-10-17 05:52:49 +00:00
2 changed files with 63 additions and 13 deletions

View File

@ -126,12 +126,6 @@ typedef unsigned int uintptr_t;
#define O_SHARE_DELETE 0x20000000 /* for rb_w32_open(), rb_w32_wopen() */
typedef int clockid_t;
#if defined(__MINGW32__)
/* I don't know why but these return some strange values. */
#undef CLOCK_PROCESS_CPUTIME_ID
#undef CLOCK_THREAD_CPUTIME_ID
#undef CLOCK_REALTIME_COARSE
#endif
/* defined in win32/win32.c for old versions */
#if !defined(__MINGW32__) || !defined(HAVE_CLOCK_GETTIME)
@ -148,6 +142,15 @@ typedef int clockid_t;
#ifndef CLOCK_MONOTONIC
# define CLOCK_MONOTONIC 1
#endif
#ifndef CLOCK_PROCESS_CPUTIME_ID
# define CLOCK_PROCESS_CPUTIME_ID 2
#endif
#ifndef CLOCK_THREAD_CPUTIME_ID
# define CLOCK_THREAD_CPUTIME_ID 3
#endif
#ifndef CLOCK_REALTIME_COARSE
# define CLOCK_REALTIME_COARSE 4
#endif
#undef utime
#undef lseek

View File

@ -4762,19 +4762,39 @@ gettimeofday(struct timeval *tv, struct timezone *tz)
}
#ifdef NEED_CLOCK_GETTIME
/* License: Ruby's */
static FILETIME
filetimes_plus(FILETIME t1, FILETIME t2)
{
ULARGE_INTEGER i1 = {.u = {.LowPart = t1.dwLowDateTime, .HighPart = t1.dwHighDateTime}};
ULARGE_INTEGER i2 = {.u = {.LowPart = t2.dwLowDateTime, .HighPart = t2.dwHighDateTime}};
ULARGE_INTEGER i = {.QuadPart = i1.QuadPart + i2.QuadPart};
return (FILETIME){.dwLowDateTime = i.LowPart, .dwHighDateTime = i.HighPart};
}
static void
filetime_to_timespec(FILETIME ft, struct timespec *sp)
{
long subsec;
sp->tv_sec = filetime_split(&ft, &subsec);
sp->tv_nsec = subsec * 100;
}
/* License: Ruby's */
static const secs_in_ns = 1000000000;
/* License: Ruby's */
int
clock_gettime(clockid_t clock_id, struct timespec *sp)
{
switch (clock_id) {
case CLOCK_REALTIME:
case CLOCK_REALTIME_COARSE:
{
FILETIME ft;
long subsec;
GetSystemTimePreciseAsFileTime(&ft);
sp->tv_sec = filetime_split(&ft, &subsec);
sp->tv_nsec = subsec * 100;
filetime_to_timespec(ft, sp);
return 0;
}
case CLOCK_MONOTONIC:
@ -4790,10 +4810,28 @@ clock_gettime(clockid_t clock_id, struct timespec *sp)
return -1;
}
sp->tv_sec = count.QuadPart / freq.QuadPart;
if (freq.QuadPart < 1000000000)
sp->tv_nsec = (count.QuadPart % freq.QuadPart) * 1000000000 / freq.QuadPart;
if (freq.QuadPart < secs_in_ns)
sp->tv_nsec = (count.QuadPart % freq.QuadPart) * secs_in_ns / freq.QuadPart;
else
sp->tv_nsec = (long)((count.QuadPart % freq.QuadPart) * (1000000000.0 / freq.QuadPart));
sp->tv_nsec = (long)((count.QuadPart % freq.QuadPart) * ((double)secs_in_ns / freq.QuadPart));
return 0;
}
case CLOCK_PROCESS_CPUTIME_ID:
case CLOCK_THREAD_CPUTIME_ID:
{
FILETIME ct, et, kt, ut;
BOOL ok;
if (clock_id == CLOCK_PROCESS_CPUTIME_ID) {
ok = GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut);
}
else {
ok = GetThreadTimes(GetCurrentThread(), &ct, &et, &kt, &ut);
}
if (!ok) {
errno = map_errno(GetLastError());
return -1;
}
filetime_to_timespec(filetimes_plus(kt, ut), sp);
return 0;
}
default:
@ -4810,6 +4848,7 @@ clock_getres(clockid_t clock_id, struct timespec *sp)
{
switch (clock_id) {
case CLOCK_REALTIME:
case CLOCK_REALTIME_COARSE:
{
sp->tv_sec = 0;
sp->tv_nsec = 1000;
@ -4823,7 +4862,15 @@ clock_getres(clockid_t clock_id, struct timespec *sp)
return -1;
}
sp->tv_sec = 0;
sp->tv_nsec = (long)(1000000000.0 / freq.QuadPart);
sp->tv_nsec = (long)((double)secs_in_ns / freq.QuadPart);
return 0;
}
case CLOCK_PROCESS_CPUTIME_ID:
case CLOCK_THREAD_CPUTIME_ID:
{
const int frames_in_sec = 60;
sp->tv_sec = 0;
sp->tv_nsec = (long)(secs_in_ns / frames_in_sec);
return 0;
}
default: