From 48d275a022f1347c2b1240872606e692053a8527 Mon Sep 17 00:00:00 2001 From: mxork <> Date: Fri, 10 Jul 2026 17:30:18 -0400 Subject: [PATCH 1/4] use monotonic, higher resolution jiffies --- lib/scheme/time.c | 44 ++++++++++++++++++++++++++++++++++++++++---- lib/scheme/time.sld | 5 +---- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/lib/scheme/time.c b/lib/scheme/time.c index 959c84bcb..8324a5d30 100644 --- a/lib/scheme/time.c +++ b/lib/scheme/time.c @@ -4,12 +4,15 @@ /* BSD-style license: http://synthcode.com/license.txt */ #include +#include +#include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #elif !defined(PLAN9) #include +#include #else typedef long time_t; #endif @@ -49,10 +52,10 @@ static void current_ntp_clock_values (double *second, int *leap_second_indicator struct ntptimeval ntv; int status = ntp_gettime(&ntv); if (ntp_resolution != 0 && ( - status == TIME_OK || - status == TIME_INS || - status == TIME_DEL || - status == TIME_OOP || + status == TIME_OK || + status == TIME_INS || + status == TIME_DEL || + status == TIME_OOP || status == TIME_WAIT)) { if (ntp_resolution == 1e-6) { struct timeval *tv = (struct timeval *) &ntv.time; @@ -108,11 +111,44 @@ sexp sexp_current_clock_second (sexp ctx, sexp self, sexp_sint_t n) { #endif } +sexp sexp_current_jiffy (sexp ctx, sexp self, sexp_sint_t n) { +#ifdef _WIN32 + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + return sexp_make_fixnum(t); +#elif !defined(PLAN9) + struct timespec tv; + int err = clock_gettime(CLOCK_MONOTONIC, &tv); + // :note could use errno, here + if (err) + return sexp_user_exception(ctx, self, "couldn't get current jiffy", SEXP_FALSE); + return sexp_make_fixnum(1000000000*tv.tv_sec + tv.tv_nsec); +#else + // :note plan9 has `cycles`, but converting that to a clock is non-trivial + vlong res = nsec(NULL); + return sexp_make_fixnum(res); +#endif +} + +sexp sexp_jiffies_per_second(sexp ctx, sexp self, sexp_sint_t n) { +#ifdef _WIN32 + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + return sexp_make_fixnum(frequency); +#elif !defined(PLAN9) + return sexp_make_fixnum(1000000000); +#else + return sexp_make_fixnum(1000000000); +#endif +} + sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char* version, const sexp_abi_identifier_t abi) { if (!(sexp_version_compatible(ctx, version, sexp_version) && sexp_abi_compatible(ctx, abi, SEXP_ABI_IDENTIFIER))) return sexp_global(ctx, SEXP_G_ABI_ERROR); sexp_define_foreign(ctx, env, "current-clock-second", 0, sexp_current_clock_second); + sexp_define_foreign(ctx, env, "current-jiffy", 0, sexp_current_jiffy); + sexp_define_foreign(ctx, env, "jiffies-per-second", 0, sexp_jiffies_per_second); #if SEXP_USE_NTP_GETTIME determine_ntp_resolution(); sexp_define_foreign(ctx, env, "current-ntp-clock-values", 0, sexp_current_ntp_clock_values); diff --git a/lib/scheme/time.sld b/lib/scheme/time.sld index c34040a52..c1edbb354 100644 --- a/lib/scheme/time.sld +++ b/lib/scheme/time.sld @@ -72,7 +72,4 @@ ;; Exported interface. (define current-second - (make-tai-clock clock-type call-with-current-clock-values)) - (define (current-jiffy) - (inexact->exact (round (* (current-second) (jiffies-per-second))))) - (define (jiffies-per-second) 1000))) + (make-tai-clock clock-type call-with-current-clock-values)))) From bb3b386621e29ded34a6b6188b0f838fb96e3c4c Mon Sep 17 00:00:00 2001 From: mxork <> Date: Tue, 14 Jul 2026 11:00:54 -0400 Subject: [PATCH 2/4] use millisecond jiffies on 32bit platforms --- lib/scheme/time.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/scheme/time.c b/lib/scheme/time.c index 8324a5d30..06a17cf68 100644 --- a/lib/scheme/time.c +++ b/lib/scheme/time.c @@ -111,26 +111,49 @@ sexp sexp_current_clock_second (sexp ctx, sexp self, sexp_sint_t n) { #endif } +#define SEXP_MS_JIFFY !SEXP_64_BIT sexp sexp_current_jiffy (sexp ctx, sexp self, sexp_sint_t n) { #ifdef _WIN32 LARGE_INTEGER t; QueryPerformanceCounter(&t); +#if SEXP_MS_JIFFY + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + return sexp_make_fixnum((1000*t)/frequency); +#else return sexp_make_fixnum(t); +#endif + #elif !defined(PLAN9) struct timespec tv; int err = clock_gettime(CLOCK_MONOTONIC, &tv); // :note could use errno, here if (err) return sexp_user_exception(ctx, self, "couldn't get current jiffy", SEXP_FALSE); - return sexp_make_fixnum(1000000000*tv.tv_sec + tv.tv_nsec); + uint64_t current_ns = 1000000000*tv.tv_sec + tv.tv_nsec; +#if SEXP_MS_JIFFY + uint32_t current_ms = current_ns / 1000000; + return sexp_make_fixnum(current_ms); +#else + return sexp_make_fixnum(current_ns); +#endif + #else // :note plan9 has `cycles`, but converting that to a clock is non-trivial - vlong res = nsec(NULL); - return sexp_make_fixnum(res); + uint64_t current_ns = nsec(NULL); +#if SEXP_MS_JIFFY + uint32_t current_ms = current_ns / 1000000; + return sexp_make_fixnum(current_ms); +#else + return sexp_make_fixnum(current_ns); +#endif #endif } sexp sexp_jiffies_per_second(sexp ctx, sexp self, sexp_sint_t n) { +#if SEXP_MS_JIFFY + return sexp_make_fixnum(1000); +#else #ifdef _WIN32 LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); @@ -140,6 +163,7 @@ sexp sexp_jiffies_per_second(sexp ctx, sexp self, sexp_sint_t n) { #else return sexp_make_fixnum(1000000000); #endif +#endif } sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char* version, const sexp_abi_identifier_t abi) { From 255ced8b2ce90e534fe4efed6b5f525047a5414a Mon Sep 17 00:00:00 2001 From: mxork <> Date: Tue, 14 Jul 2026 11:38:28 -0400 Subject: [PATCH 3/4] fixup; LARGE_INTEGER.QuadPart --- lib/scheme/time.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/scheme/time.c b/lib/scheme/time.c index 06a17cf68..2f801d187 100644 --- a/lib/scheme/time.c +++ b/lib/scheme/time.c @@ -119,9 +119,9 @@ sexp sexp_current_jiffy (sexp ctx, sexp self, sexp_sint_t n) { #if SEXP_MS_JIFFY LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); - return sexp_make_fixnum((1000*t)/frequency); + return sexp_make_fixnum((1000*t.QuadPart)/frequency.QuadPart); #else - return sexp_make_fixnum(t); + return sexp_make_fixnum(t.QuadPart); #endif #elif !defined(PLAN9) @@ -157,7 +157,7 @@ sexp sexp_jiffies_per_second(sexp ctx, sexp self, sexp_sint_t n) { #ifdef _WIN32 LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); - return sexp_make_fixnum(frequency); + return sexp_make_fixnum(frequency.QuadPart); #elif !defined(PLAN9) return sexp_make_fixnum(1000000000); #else From 88e24e389795a309f0fb861cb450bc678597bdde Mon Sep 17 00:00:00 2001 From: mxork <> Date: Wed, 15 Jul 2026 10:59:02 -0400 Subject: [PATCH 4/4] fixup; unify repeats --- lib/scheme/time.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/lib/scheme/time.c b/lib/scheme/time.c index 2f801d187..ea7fabd10 100644 --- a/lib/scheme/time.c +++ b/lib/scheme/time.c @@ -123,31 +123,25 @@ sexp sexp_current_jiffy (sexp ctx, sexp self, sexp_sint_t n) { #else return sexp_make_fixnum(t.QuadPart); #endif - -#elif !defined(PLAN9) +#else // _WIN32 +#if !defined(PLAN9) struct timespec tv; int err = clock_gettime(CLOCK_MONOTONIC, &tv); // :note could use errno, here if (err) return sexp_user_exception(ctx, self, "couldn't get current jiffy", SEXP_FALSE); uint64_t current_ns = 1000000000*tv.tv_sec + tv.tv_nsec; -#if SEXP_MS_JIFFY - uint32_t current_ms = current_ns / 1000000; - return sexp_make_fixnum(current_ms); -#else - return sexp_make_fixnum(current_ns); -#endif - #else // :note plan9 has `cycles`, but converting that to a clock is non-trivial uint64_t current_ns = nsec(NULL); +#endif #if SEXP_MS_JIFFY uint32_t current_ms = current_ns / 1000000; return sexp_make_fixnum(current_ms); #else return sexp_make_fixnum(current_ns); #endif -#endif +#endif // _WIN32 } sexp sexp_jiffies_per_second(sexp ctx, sexp self, sexp_sint_t n) { @@ -158,8 +152,6 @@ sexp sexp_jiffies_per_second(sexp ctx, sexp self, sexp_sint_t n) { LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); return sexp_make_fixnum(frequency.QuadPart); -#elif !defined(PLAN9) - return sexp_make_fixnum(1000000000); #else return sexp_make_fixnum(1000000000); #endif