diff --git a/otherlibs/stdune/src/dune_clock.h b/otherlibs/stdune/src/dune_clock.h new file mode 100644 index 00000000000..cf0be2db0d0 --- /dev/null +++ b/otherlibs/stdune/src/dune_clock.h @@ -0,0 +1,71 @@ +// Cross-platform realtime clock with legacy fallbacks +// +// Provides dune_clock_gettime_ns() returning nanoseconds since Unix epoch. +// +// Platform support: +// >= Windows 8 GetSystemTimePreciseAsFileTime +// < Windows 8 GetSystemTimeAsFileTime +// >= macOS 10.12 clock_gettime +// < macOS 10.12 gettimeofday +// Other Unix clock_gettime + +#ifndef DUNE_CLOCK_H +#define DUNE_CLOCK_H + +#include + +#ifdef _WIN32 +#include + +// Windows epoch starts 1601-01-01, Unix epoch starts 1970-01-01 +// Difference is 11644473600 seconds +#define SEC_TO_UNIX_EPOCH 11644473600LL + +static inline int64_t dune_clock_gettime_ns(void) { + FILETIME ft; + static VOID (WINAPI *GetSystemTime)(LPFILETIME) = NULL; + + if (GetSystemTime == NULL) { + HMODULE h = GetModuleHandleA("kernel32.dll"); + if (h) { + GetSystemTime = (VOID (WINAPI *)(LPFILETIME))GetProcAddress(h, "GetSystemTimePreciseAsFileTime"); + } + if (GetSystemTime == NULL) { + // Fallback for Windows < 8 + GetSystemTime = GetSystemTimeAsFileTime; + } + } + + GetSystemTime(&ft); + ULARGE_INTEGER li; + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + + // Convert from 100ns intervals since Windows epoch to ns since Unix epoch + return (li.QuadPart - SEC_TO_UNIX_EPOCH * 10000000LL) * 100; +} + +#else // _WIN32 + +#include + +#if defined(__APPLE__) +#include +#include +#endif + +static inline int64_t dune_clock_gettime_ns(void) { +#if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED < 101200 + // macOS < 10.12 doesn't have clock_gettime, use gettimeofday + struct timeval tv; + gettimeofday(&tv, NULL); + return ((int64_t)tv.tv_sec * 1000000000LL) + ((int64_t)tv.tv_usec * 1000LL); +#else + struct timespec tp; + clock_gettime(CLOCK_REALTIME, &tp); + return ((int64_t)tp.tv_sec * 1000000000LL) + (int64_t)tp.tv_nsec; +#endif +} + +#endif // _WIN32 +#endif // DUNE_CLOCK_H diff --git a/otherlibs/stdune/src/time_stubs.c b/otherlibs/stdune/src/time_stubs.c index 8182dc8ccfd..1e4a0f5cb29 100644 --- a/otherlibs/stdune/src/time_stubs.c +++ b/otherlibs/stdune/src/time_stubs.c @@ -1,48 +1,9 @@ #include #include -#include -#ifdef _WIN32 -#include - -// Windows epoch starts 1601-01-01, Unix epoch starts 1970-01-01 -// Difference is 11644473600 seconds -#define SEC_TO_UNIX_EPOCH 11644473600LL - -CAMLprim value dune_clock_gettime_realtime(value v_unit) { - (void)v_unit; - FILETIME ft; - static VOID (WINAPI *GetSystemTime)(LPFILETIME) = NULL; - if (GetSystemTime == NULL) { - HMODULE h = GetModuleHandleA("kernel32.dll"); - if (h) { - GetSystemTime = (VOID (WINAPI *)(LPFILETIME))GetProcAddress(h, "GetSystemTimePreciseAsFileTime"); - } - if (GetSystemTime == NULL) { /* < Windows 8 */ - GetSystemTime = GetSystemTimeAsFileTime; - } - } - - GetSystemTime(&ft); - ULARGE_INTEGER li; - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - - // Convert from 100ns intervals since Windows epoch to ns since Unix epoch - int64_t ns = (li.QuadPart - SEC_TO_UNIX_EPOCH * 10000000LL) * 100; - return Val_long(ns); -} - -#else // Unix-like systems - -#include +#include "dune_clock.h" CAMLprim value dune_clock_gettime_realtime(value v_unit) { (void)v_unit; - struct timespec tp; - clock_gettime(CLOCK_REALTIME, &tp); - int64_t ns = ((int64_t)tp.tv_sec * 1000000000LL) + (int64_t)tp.tv_nsec; - return Val_long(ns); + return Val_long(dune_clock_gettime_ns()); } - -#endif diff --git a/otherlibs/stdune/src/wait4_stubs.c b/otherlibs/stdune/src/wait4_stubs.c index 8a007962108..645ebb34adc 100644 --- a/otherlibs/stdune/src/wait4_stubs.c +++ b/otherlibs/stdune/src/wait4_stubs.c @@ -24,9 +24,10 @@ void dune_wait4(value v_pid, value flags) { #include #include #include -#include #include +#include "dune_clock.h" + #define TAG_WEXITED 0 #define TAG_WSIGNALED 1 #define TAG_WSTOPPED 2 @@ -68,7 +69,7 @@ value dune_wait4(value v_pid, value flags) { CAMLlocal2(times, res); int status, cv_flags; - struct timespec tp; + int64_t time_ns; cv_flags = caml_convert_flag_list(flags, wait_flag_table); pid_t pid = Int_val(v_pid); @@ -78,7 +79,7 @@ value dune_wait4(value v_pid, value flags) { // returns the pid of the terminated process, or -1 on error pid = wait4(pid, &status, cv_flags, &ru); int wait_errno = errno; - clock_gettime(CLOCK_REALTIME, &tp); + time_ns = dune_clock_gettime_ns(); caml_leave_blocking_section(); if (pid == 0) { CAMLreturn(Val_none); @@ -107,8 +108,7 @@ value dune_wait4(value v_pid, value flags) { res = caml_alloc_tuple(4); Store_field(res, 0, Val_int(pid)); Store_field(res, 1, alloc_process_status(status)); - Store_field(res, 2, - Val_long(((int64_t)tp.tv_sec * 1000000000LL) + (int64_t)tp.tv_nsec)); + Store_field(res, 2, Val_long(time_ns)); Store_field(res, 3, times); CAMLreturn(caml_alloc_some_compat(res)); } diff --git a/src/fsevents/fsevents_stubs.c b/src/fsevents/fsevents_stubs.c index 3d15d0b5538..82f5fc0ec96 100644 --- a/src/fsevents/fsevents_stubs.c +++ b/src/fsevents/fsevents_stubs.c @@ -10,7 +10,7 @@ #include #endif -#if defined(__APPLE__) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 +#if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 #include #include @@ -155,7 +155,7 @@ static void dune_fsevents_callback(const FSEventStreamRef streamRef, continue; } CFStringRef cf_path; -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101300 CFDictionaryRef details = CFArrayGetValueAtIndex(eventPaths, i); cf_path = CFDictionaryGetValue(details, kFSEventStreamEventExtendedDataPathKey); @@ -228,7 +228,7 @@ CAMLprim value dune_fsevents_create(value v_paths, value v_latency, const FSEventStreamEventFlags flags = kFSEventStreamCreateFlagNoDefer | -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101300 kFSEventStreamCreateFlagUseExtendedData | #endif kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagFileEvents; @@ -385,7 +385,7 @@ static const FSEventStreamEventFlags all_flags[] = { kFSEventStreamEventFlagOwnEvent, kFSEventStreamEventFlagItemIsHardlink, kFSEventStreamEventFlagItemIsLastHardlink, -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101300 kFSEventStreamEventFlagItemCloned, #endif };