~ chicken-core (chicken-5) 051234429d8cfccdad8609cdcaf8c431acb2e81f
commit 051234429d8cfccdad8609cdcaf8c431acb2e81f
Author: Peter Bex <peter@more-magic.net>
AuthorDate: Sun May 3 12:33:20 2020 +0200
Commit: felix <felix@call-with-current-continuation.org>
CommitDate: Wed May 6 11:22:03 2020 +0200
Fix a few platform-specific issues with current-process-millisecond
On Windows, clock() will return (clock_t)(-1) after about 24.8 days
(see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/clock?view=vs-2019)
Instead, use GetTickCount64(), which returns the milliseconds since
system startup time as a 64-bit quantity, which does not have these
problems. Unfortunately, the old mingw32 (which is close to
unmaintained) does not support this. For compatibility, we will
use GetTickCount() there.
The C_NONUNIX macro is defined only on Mingw32 in chicken.h, so change
the #ifdef guard around this code to check on __MINGW32__, to make it
clear what it is checking for (for example, Haiku is not UNIX, but we
don't define that macro there). If we need to support other non-UNIX
platforms, we should add specific guards per platform.
While we're at it, on Windows, also record the current value at
startup, so that we can tighten the definition of
current-process-milliseconds to state that it always returns the
number of milliseconds since process startup. This means less
variance across platforms and makes the functionality less "vague".
Finally, split up the startup time into seconds and milliseconds, to
make the time since startup more precise; otherwise you get seemingly
random values when retrieving this due to only looking at the tv_sec
part of the gettimeofday return value.
Signed-off-by: felix <felix@call-with-current-continuation.org>
diff --git a/NEWS b/NEWS
index 67cc9f55..67b81974 100644
--- a/NEWS
+++ b/NEWS
@@ -7,7 +7,12 @@
- current-milliseconds has been deprecated in favor of the name
current-process-milliseconds, to avoid confusion due to naming
of current-milliseconds versus current-seconds, which do something
- quite different.
+ quite different. Also, its definition has been tweaked to
+ guarantee that it returns the time since process startup. On
+ Windows, it will now return sane values after 24 days of uptime.
+ On UNIX, the values returned will be precise to the millisecond
+ instead of rounded down to the nearest second at startup (which
+ would result in erratic startup times).
- Runtime system
- Sleeping primordial thread doesn't forget mutations made to
diff --git a/manual/Module (chicken time) b/manual/Module (chicken time)
index 2f302c4e..4422ce64 100644
--- a/manual/Module (chicken time)
+++ b/manual/Module (chicken time)
@@ -23,7 +23,7 @@ system time will be always be 0.
<procedure>(current-process-milliseconds)</procedure>
-Returns the number of milliseconds since process- or machine startup.
+Returns the number of milliseconds since process startup.
==== current-seconds
diff --git a/runtime.c b/runtime.c
index b01cdd06..ab14f66e 100644
--- a/runtime.c
+++ b/runtime.c
@@ -362,7 +362,8 @@ C_TLS C_uword
C_heap_shrinkage_used = DEFAULT_HEAP_SHRINKAGE_USED,
C_maximal_heap_size = DEFAULT_MAXIMAL_HEAP_SIZE;
C_TLS time_t
- C_startup_time_seconds,
+ C_startup_time_sec,
+ C_startup_time_msec,
profile_frequency = 10000;
C_TLS char
**C_main_argv,
@@ -684,17 +685,23 @@ int CHICKEN_initialize(int heap, int stack, int symbols, void *toplevel)
struct sigaction sa;
#endif
- /*FIXME Should have C_tzset in chicken.h? */
-#ifdef C_NONUNIX
- C_startup_time_seconds = (time_t)0;
-# if defined(__MINGW32__)
+ /* FIXME Should have C_tzset in chicken.h? */
+#if defined(__MINGW32__)
+# if defined(__MINGW64_VERSION_MAJOR)
+ ULONGLONG tick_count = GetTickCount64();
+# else
+ /* mingw32 doesn't yet have GetTickCount64 support */
+ ULONGLONG tick_count = GetTickCount();
+# endif
+ C_startup_time_sec = tick_count / 1000;
+ C_startup_time_msec = tick_count % 1000;
/* Make sure _tzname, _timezone, and _daylight are set */
_tzset();
-# endif
#else
struct timeval tv;
C_gettimeofday(&tv, NULL);
- C_startup_time_seconds = tv.tv_sec;
+ C_startup_time_sec = tv.tv_sec;
+ C_startup_time_msec = tv.tv_usec / 1000;
/* Make sure tzname, timezone, and daylight are set */
tzset();
#endif
@@ -2033,14 +2040,18 @@ C_regparm C_u64 C_fcall C_milliseconds(void)
C_regparm C_u64 C_fcall C_current_process_milliseconds(void)
{
-#ifdef C_NONUNIX
- if(CLOCKS_PER_SEC == 1000) return clock();
- else return (C_u64)clock() / (C_u64)CLOCKS_PER_SEC * 1000;
+#if defined(__MINGW32__)
+# if defined(__MINGW64_VERSION_MAJOR)
+ ULONGLONG tick_count = GetTickCount64();
+# else
+ ULONGLONG tick_count = GetTickCount();
+# endif
+ return tick_count - (C_startup_time_sec * 1000) - C_startup_time_msec;
#else
struct timeval tv;
if(C_gettimeofday(&tv, NULL) == -1) return 0;
- else return (tv.tv_sec - C_startup_time_seconds) * 1000 + tv.tv_usec / 1000;
+ else return (tv.tv_sec - C_startup_time_sec) * 1000 + tv.tv_usec / 1000 - C_startup_time_msec;
#endif
}
Trap