diff options
| author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2025-10-16 10:41:40 +0900 |
|---|---|---|
| committer | Nobuyoshi Nakada <nobu.nakada@gmail.com> | 2025-10-17 14:52:19 +0900 |
| commit | b2d4dc9c46719b1a67bd24a4b4cf444c90621a78 (patch) | |
| tree | d598b148f3ba9d0c00e02713d7e04e51101ebd8a | |
| parent | ff6bd7fb4ef54b6963b5a09f2e09e3dd0d9d7156 (diff) | |
win32: Support more `clockid_t`
Add `CLOCK_PROCESS_CPUTIME_ID` and `CLOCK_THREAD_CPUTIME_ID`.
| -rw-r--r-- | include/ruby/win32.h | 15 | ||||
| -rw-r--r-- | win32/win32.c | 61 |
2 files changed, 63 insertions, 13 deletions
diff --git a/include/ruby/win32.h b/include/ruby/win32.h index 31dc13e932..be3a1cce96 100644 --- a/include/ruby/win32.h +++ b/include/ruby/win32.h @@ -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 diff --git a/win32/win32.c b/win32/win32.c index 1a5308337a..9bdc9f8276 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -4763,18 +4763,38 @@ 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: |
