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

Reply via email to