On Tue, Nov 11, 2025 at 04:07:58PM +0100, Arnd Bergmann wrote:
On Tue, Nov 11, 2025, at 15:46, Thomas Weißschuh wrote:
On Tue, Nov 11, 2025 at 03:19:00PM +0100, Arnd Bergmann wrote:
(...)
If we are trying to validate the interface here, we should probably call both if available. If we just want to know the result and trust that both work correctly, I'd always use __NR_clock_getres_time64 on 32-bit systems and __NR_clock_getres on 64-bit systems.
As these are vDSO and not timer selftests I think we trust the syscalls. But how do we detect a native 64-bit time system? The preprocessor builtins won't work as a 32-bit pointer system may use 64-bit time syscalls. I am not aware of the UAPI #define, beyond the absence of __NR_clock_getres_time64.
I would just check __BITS_PER_LONG=32 and require a linux-5.6+ kernel at runtime to ensure the 64-bit calls are available.
That doesn't work for x32. It uses __BITS_PER_LONG but does not have __NR_clock_getres_time64.
Right. In C code, we can usually check for 'sizeof(time_t) > sizeof(__kernel_long_t)' to catch that case, but that doesn't work as easily with the preprocessor.
A more complex setup using both compile-time and run-time fallbacks would work, e.g.
static int syscall_clock_getres_old(clockid_t clockid, struct timespec *res); #ifdef __NR_clock_getres struct __kernel_old_timespec ts_old; ret = syscall(__NR_clock_getres, clockid, &ts_old); if (ret) return ret; res->tv_sec = ts_old.sec; res->tv_nsec = ts_old.tv_nsec; return 0; #else return -ENOSYS; #endif }
static int syscall_clock_getres_time64(clockid_t clockid, struct timespec *res); #ifdef __NR_clock_getres_time64 struct __kernel_timespec ts_64; ret = syscall(__NR_clock_getres_time64, clockid, &ts_64); if (ret) return ret; res->tv_sec = ts_64.sec; res->tv_nsec = ts_64.tv_nsec; return 0; #else return -ENOSYS; #endif }
static int syscall_clock_getres(clockid_t clockid, struct timespec *res) { ret = syscall_clock_getres_time64(clockid, res); if (ret != -ENOSYS) return ret; return syscall_clock_getres_old(clockid, &ts_old); }
This is exactly what I tried to avoid.
but the simpler check falling back to the 'old' version is probably sufficient.
On musl there is no SYS_clock_getres_time64 but instead there is SYS_clock_getres_time32. Switching to __NR gives us back the more natural fallback logic. We are back at the nolibc 64-bit time functions. We can add a static_assert() to gain some compile-time safety.
static int syscall_clock_getres(__kernel_clockid_t clockid, struct __kernel_timespec *res) { #ifdef __NR_clock_getres_time64 return syscall(__NR_clock_getres_time64, clockid, res); #else /* * __NR_clock_getres expects __kernel_old_timespec. * Make sure the actual parameter is compatible. */ _Static_assert(sizeof(struct __kernel_old_timespec) == sizeof(*res)); return syscall(__NR_clock_getres, clockid, res); #endif }
And stick all of those wrappers into another helper header.
Thomas