Add os_tick_us() and os_tick_ns() monotonic high-resolution timers

This commit is contained in:
Andrea Mazzoleni 2026-10-02 10:13:35 +02:00
parent 68b94bfdf5
commit a7a85a259c
5 changed files with 58 additions and 16 deletions

View file

@ -71,7 +71,7 @@ AC_HEADER_ASSERT
AC_HEADER_SYS_WAIT AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([dirent.h stdint.h inttypes.h unistd.h math.h execinfo.h strings.h getopt.h syslog.h grp.h pwd.h io.h alloca.h]) AC_CHECK_HEADERS([dirent.h stdint.h inttypes.h unistd.h math.h execinfo.h strings.h getopt.h syslog.h grp.h pwd.h io.h alloca.h])
AC_CHECK_HEADERS([sys/file.h sys/sysctl.h sys/ioctl.h sys/time.h sys/types.h sys/mkdev.h sys/sysmacros.h sys/stat.h sys/prctl.h sys/sysinfo.h sys/utsname.h]) AC_CHECK_HEADERS([sys/file.h sys/sysctl.h sys/ioctl.h sys/time.h sys/types.h sys/mkdev.h sys/sysmacros.h sys/stat.h sys/prctl.h sys/sysinfo.h sys/utsname.h])
AC_CHECK_HEADERS([linux/fs.h linux/btrfs.h linux/fiemap.h mach/mach_time.h]) AC_CHECK_HEADERS([linux/fs.h linux/btrfs.h linux/fiemap.h])
# Check for the close_range(...,CLOSE_RANGE_CLOEXEC) # Check for the close_range(...,CLOSE_RANGE_CLOEXEC)
AC_CHECK_HEADERS([linux/close_range.h]) AC_CHECK_HEADERS([linux/close_range.h])
@ -126,7 +126,6 @@ AC_CHECK_FUNCS([fsync posix_fadvise sync_file_range syncfs])
AC_CHECK_FUNCS([getc_unlocked ferror_unlocked]) AC_CHECK_FUNCS([getc_unlocked ferror_unlocked])
AC_CHECK_FUNCS([futimes futimens futimesat localtime_r lutimes utimensat]) AC_CHECK_FUNCS([futimes futimens futimesat localtime_r lutimes utimensat])
AC_CHECK_FUNCS([fstatat flock renameat statx]) AC_CHECK_FUNCS([fstatat flock renameat statx])
AC_CHECK_FUNCS([mach_absolute_time])
AC_CHECK_FUNCS([backtrace backtrace_symbols]) AC_CHECK_FUNCS([backtrace backtrace_symbols])
AC_SEARCH_LIBS([clock_gettime], [rt]) AC_SEARCH_LIBS([clock_gettime], [rt])
AC_CHECK_FUNCS([clock_gettime]) AC_CHECK_FUNCS([clock_gettime])

View file

@ -64,6 +64,7 @@ static windows_key_t last_error;
*/ */
static windows_mutex_t tick_lock; static windows_mutex_t tick_lock;
static uint64_t tick_last; static uint64_t tick_last;
static uint64_t tick_frequency;
/** /**
* Mutex for process reference publication, termination, and unpublication. * Mutex for process reference publication, termination, and unpublication.
@ -4498,6 +4499,24 @@ uint64_t os_tick_ms(void)
return GetTickCount64(); return GetTickCount64();
} }
uint64_t os_tick_us(void)
{
uint64_t ticks = os_tick();
uint64_t sec = ticks / tick_frequency;
uint64_t rem = ticks % tick_frequency;
return sec * 1000000ULL + (rem * 1000000ULL) / tick_frequency;
}
uint64_t os_tick_ns(void)
{
uint64_t ticks = os_tick();
uint64_t sec = ticks / tick_frequency;
uint64_t rem = ticks % tick_frequency;
return sec * 1000000000ULL + (rem * 1000000000ULL) / tick_frequency;
}
int os_usleep(uint64_t usec) int os_usleep(uint64_t usec)
{ {
while (usec > 0) { while (usec > 0) {
@ -4609,6 +4628,13 @@ void os_init(unsigned opt)
os_exit(); os_exit();
} }
LARGE_INTEGER freq;
if (!QueryPerformanceFrequency(&freq) || freq.QuadPart <= 0) {
os_syslog(OS_LVL_CRITICAL, "error calling QueryPerformanceFrequency()");
os_exit();
}
tick_frequency = freq.QuadPart;
if (windows_mutex_init(&exec_mutex, 0) != 0) { if (windows_mutex_init(&exec_mutex, 0) != 0) {
os_syslog(OS_LVL_CRITICAL, "error calling windows_mutex_init()"); os_syslog(OS_LVL_CRITICAL, "error calling windows_mutex_init()");
os_exit(); os_exit();
@ -4684,6 +4710,7 @@ void os_done(void)
windows_mutex_destroy(&exec_mutex); windows_mutex_destroy(&exec_mutex);
windows_mutex_destroy(&tick_lock); windows_mutex_destroy(&tick_lock);
tick_frequency = 0;
/* restore the normal execution level */ /* restore the normal execution level */
SetThreadExecutionState(WIN32_ES_CONTINUOUS); SetThreadExecutionState(WIN32_ES_CONTINUOUS);

12
os/os.h
View file

@ -397,6 +397,18 @@ uint64_t os_tick(void);
*/ */
uint64_t os_tick_ms(void); uint64_t os_tick_ms(void);
/**
* Get the os_tick counter value in microsecond.
* \return Monotonic clock value in microseconds.
*/
uint64_t os_tick_us(void);
/**
* Get the os_tick counter value in nanosecond.
* \return Monotonic clock value in nanoseconds.
*/
uint64_t os_tick_ns(void);
/** /**
* Get the os_tick counter value in seconds. * Get the os_tick counter value in seconds.
* \return Monotonic clock value in seconds. * \return Monotonic clock value in seconds.

View file

@ -132,7 +132,6 @@
#include <linux/fiemap.h> #include <linux/fiemap.h>
#endif #endif
/** /**
* Includes some standard headers. * Includes some standard headers.
*/ */
@ -174,10 +173,6 @@
#endif #endif
#endif #endif
#if HAVE_MACH_MACH_TIME_H
#include <mach/mach_time.h>
#endif
#if HAVE_DIRENT_H #if HAVE_DIRENT_H
#include <dirent.h> #include <dirent.h>
#endif #endif

View file

@ -2217,17 +2217,18 @@ void os_privileges_release(void)
uint64_t os_tick(void) uint64_t os_tick(void)
{ {
#if HAVE_MACH_ABSOLUTE_TIME #if HAVE_CLOCK_GETTIME && (defined(CLOCK_UPTIME_RAW) || defined(CLOCK_MONOTONIC_RAW) || defined(CLOCK_MONOTONIC))
/* for Mac OS X */
return mach_absolute_time();
#elif HAVE_CLOCK_GETTIME && (defined(CLOCK_MONOTONIC) || defined(CLOCK_MONOTONIC_RAW))
/* for Linux */
struct timespec tv; struct timespec tv;
/* nanosecond precision with clock_gettime() */ /* nanosecond precision with clock_gettime() */
#if defined(CLOCK_MONOTONIC_RAW) #if defined(CLOCK_UPTIME_RAW)
/* for macOS (without sleep and without NTP slewing) */
if (clock_gettime(CLOCK_UPTIME_RAW, &tv) != 0) {
#elif defined(CLOCK_MONOTONIC_RAW)
/* for Linux (without sleep and without NTP slewing) */
if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) { if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) {
#else #else
/* for other POSIX */
if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) { if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) {
#endif #endif
/* LCOV_EXCL_START */ /* LCOV_EXCL_START */
@ -2247,7 +2248,7 @@ uint64_t os_tick(void)
/* LCOV_EXCL_STOP */ /* LCOV_EXCL_STOP */
} }
return tv.tv_sec * 1000000ULL + tv.tv_usec; return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ULL;
#endif #endif
} }
@ -2276,6 +2277,16 @@ uint64_t os_tick_ms(void)
#endif #endif
} }
uint64_t os_tick_us(void)
{
return os_tick() / 1000;
}
uint64_t os_tick_ns(void)
{
return os_tick();
}
uint64_t os_tick_sec(void) uint64_t os_tick_sec(void)
{ {
#if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC) #if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC)
@ -2327,8 +2338,6 @@ int os_usleep(uint64_t usec)
return 0; return 0;
} }
int os_randomize(void* ptr, size_t size) int os_randomize(void* ptr, size_t size)
{ {
int f; int f;