This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC v6 08/23] RISC-V: Define __NR_* as __NR_*_time64/64 for 32-bit


On Sat, Jan 25, 2020 at 9:33 PM Khem Raj <raj.khem@gmail.com> wrote:
> On 1/14/20 11:03 PM, Alistair Francis wrote:
>
> There is userspace code like [1] which expects SYS_futex
> These overrides do not end up in usr/include/bits/syscall-32.h
> so it fails to compile
>
> src/xshmfence_futex.h:58:17: error: use of undeclared identifier
> 'SYS_futex'; did you mean 'sys_futex'?
>          return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
>                         ^~~~~~~~~
>
> I wonder if __NR_futex and other aliases here should be exposed to
> userspace?

Please don't, that just makes it harder for the other ports to find
these instances and fix them in a portable way.

Any source code reference to a low-level system call that passes
a time32 type needs to be handled roughly like this:

typedef unsigned int __u32;
#if defined(__x86_64__) && defined(__ILP32__)
typedef long long __kernel_long_t;
#else
typedef long __kernel_long_t;
#endif

typedef __kernel_long_t __kernel_old_time_t;
struct __kernel_old_timespec {
        __kernel_long_t tv_sec;
        __kernel_long_t tv_nsec;
};
typedef long long __kernel_time64_t;
struct __kernel_timespec {
        __kernel_time64_t tv_sec;
        long long tv_nsec;
};

static inline long __kernel_futex_time64(__u32 * uaddr, int op, __u32 val,
                                         struct __kernel_timespec *utime,
                                         __u32 * uaddr2, __u32 val3)
{
#ifdef __NR_futex_time64
        return syscall(__NR_futex_time64, uaddr, op, val, utime, uaddr2, val3);
#else
        errno = -ENOSYS;
        return -1;
#endif
}

static inline long __kernel_futex_old(__u32 * uaddr, int op, __u32 val,
                                      struct __kernel_old_timespec *utime,
                                      __u32 * uaddr2, __u32 val3)
{
#ifdef __NR_futex
        return syscall(__NR_futex, uaddr, op, val, utime, uaddr2, val3);
#else
        errno = -ENOSYS;
        return -1;
#endif

}

static inline long __kernel_futex(__u32 *uaddr, int op, __u32 val,
                                      struct timespec *utime,
                                      __u32 *uaddr2, __u32 val3)
{
        long ret;

        if (sizeof(time_t) > sizeof(__kernel_long_t)) {
                if (utime) {
                        struct __kernel_timespec ts = {
                                .tv_sec = utime->tv_sec,.tv_nsec =
                                    utime->tv_nsec,
                        };
                        ret = __kernel_futex_time64(uaddr, op, val, &ts,
                                                    uaddr, val3);
                } else {
                        ret = __kernel_futex_time64(uaddr, op, val, NULL,
                                                    uaddr, val3);
                }
                if (ret != -1 || errno != -ENOSYS)
                        return ret;
        }
        if (utime) {
                struct __kernel_timespec ts = {
                        .tv_sec = utime->tv_sec,.tv_nsec = utime->tv_nsec,
                };

                return __kernel_futex_old(uaddr, op, val, &ts, uaddr,
                                          val3);
        }

        return __kernel_futex_old(uaddr, op, val, NULL, uaddr, val3);
}

I'm not sure if this covers all corner cases (or even works correctly
at all), but I'm fairly sure that anything simpler would break on some
configurations.

The code above uses the identifiers from the kernel namespace,
and this is how we might decide to distribute it along with the kernel
headers. If applications want to ship their own copy, they might
need to define their own types or require a very recent version of the
kernel headers, as __kernel_old_timespec was only added in linux-5.5
(the older headers just define 'timespec' which conflicts with the libc
type of the same name and cannot be included here at all).

I would like to actually provide automatically generated stubs like
the above from kernel headers, but that clearly requires more
discussion and some more work on turning
include/uapi/asm-generic/unistd.h into machine-readable format
first.

An alternative would be for all C libraries to start providing a futex()
wrapper and a way to identify whether it exists, then the applications
can largely start using that one on all architectures, and fall back to
the time32 version when building against an older libc.

      Arnd


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]