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:
Since SYS_clock_getres itself is provided by the libc implementation, I wouldn't trust that this actually means the same as __NR_clock_getres, and it might be set to __NR_clock_getres_time64.
Should that case not work anyways, as libc would also need to convert the parameters transparently?
Not sure, I certainly wouldn't expect all libc implementations to do this the same way.
But I'll switch it over to __NR instead.
Ok
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); }
but the simpler check falling back to the 'old' version is probably sufficient.
Arnd