Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions include/ruby/win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
3 changes: 3 additions & 0 deletions tool/lib/core_assertions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,9 @@ def assert_all_assertions_foreach(msg = nil, *keys, &block)
rescue
# Constants may be defined but not implemented, e.g., mingw.
else
unless Process.clock_getres(clk) < 1.0e-03
next # needs msec precision
end
PERFORMANCE_CLOCK = clk
end
end
Expand Down
61 changes: 54 additions & 7 deletions win32/win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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;
Expand All @@ -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:
Expand Down
Loading