missing_syscall: add epoll_pwait2() wrapper
authorLennart Poettering <lennart@poettering.net>
Thu, 25 Feb 2021 15:56:07 +0000 (16:56 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 26 Feb 2021 08:21:51 +0000 (09:21 +0100)
meson.build
src/basic/missing_syscall.h
src/basic/missing_syscall_def.h
src/basic/missing_syscalls.py

index 2c5150bfc18de93202af055d835c8f30336ad45c..8fbfd5fc494a8c3852c1045397f6eb4080e802da 100644 (file)
@@ -549,6 +549,7 @@ foreach ident : [
         ['mallinfo',          '''#include <malloc.h>'''],
         ['execveat',          '''#include <unistd.h>'''],
         ['close_range',       '''#include <unistd.h>'''],
+        ['epoll_pwait2',      '''#include <sys/epoll.h>'''],
 ]
 
         have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE')
@@ -672,6 +673,7 @@ foreach header : ['crypt.h',
                   'sys/auxv.h',
                   'valgrind/memcheck.h',
                   'valgrind/valgrind.h',
+                  'linux/time_types.h',
                  ]
 
         conf.set10('HAVE_' + header.underscorify().to_upper(),
index 52e9d5dea48dd73f00aeadad08ffe37c1979b4ff..13843248045a9eda3773dd725fc019ecae405908 100644 (file)
@@ -5,6 +5,11 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#if HAVE_LINUX_TIME_TYPES_H
+/* This header defines __kernel_timespec for us, but is only available since Linux 5.1, hence conditionally
+ * include this. */
+#include <linux/time_types.h>
+#endif
 #include <signal.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
@@ -382,3 +387,41 @@ static inline int missing_close_range(int first_fd, int end_fd, unsigned flags)
 
 #  define close_range missing_close_range
 #endif
+
+/* ======================================================================= */
+
+#if !HAVE_EPOLL_PWAIT2
+
+/* Defined to be equivalent to the kernel's _NSIG_WORDS, i.e. the size of the array of longs that is
+ * encapsulated by sigset_t. */
+#define KERNEL_NSIG_WORDS (64 / (sizeof(long) * 8))
+#define KERNEL_NSIG_BYTES (KERNEL_NSIG_WORDS * sizeof(long))
+
+struct epoll_event;
+
+static inline int missing_epoll_pwait2(
+                int fd,
+                struct epoll_event *events,
+                int maxevents,
+                const struct timespec *timeout,
+                const sigset_t *sigset) {
+
+#  if defined(__NR_epoll_pwait2) && HAVE_LINUX_TIME_TYPES_H
+        if (timeout) {
+                /* Convert from userspace timespec to kernel timespec */
+                struct __kernel_timespec ts = {
+                        .tv_sec = timeout->tv_sec,
+                        .tv_nsec = timeout->tv_nsec,
+                };
+
+                return syscall(__NR_epoll_pwait2, fd, events, maxevents, &ts, sigset, sigset ? KERNEL_NSIG_BYTES : 0);
+        } else
+                return syscall(__NR_epoll_pwait2, fd, events, maxevents, NULL, sigset, sigset ? KERNEL_NSIG_BYTES : 0);
+#  else
+        errno = ENOSYS;
+        return -1;
+#  endif
+}
+
+#  define epoll_pwait2 missing_epoll_pwait2
+#endif
index 44df37b37e878b12bc926d66e28332ee0e649b27..a66977cfec54183a38322515215a110210fb1dfe 100644 (file)
@@ -673,3 +673,58 @@ assert_cc(__NR_statx == systemd_NR_statx);
 #  endif
 #endif
 
+#ifndef __IGNORE_epoll_pwait2
+#  if defined(__aarch64__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__alpha__)
+#    define systemd_NR_epoll_pwait2 551
+#  elif defined(__arc__) || defined(__tilegx__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__arm__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__i386__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__ia64__)
+#    define systemd_NR_epoll_pwait2 1465
+#  elif defined(__m68k__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(_MIPS_SIM)
+#    if _MIPS_SIM == _MIPS_SIM_ABI32
+#      define systemd_NR_epoll_pwait2 4441
+#    elif _MIPS_SIM == _MIPS_SIM_NABI32
+#      define systemd_NR_epoll_pwait2 6441
+#    elif _MIPS_SIM == _MIPS_SIM_ABI64
+#      define systemd_NR_epoll_pwait2 5441
+#    else
+#      error "Unknown MIPS ABI"
+#    endif
+#  elif defined(__powerpc__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__s390__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__sparc__)
+#    define systemd_NR_epoll_pwait2 441
+#  elif defined(__x86_64__)
+#    if defined(__ILP32__)
+#      define systemd_NR_epoll_pwait2 (441 | /* __X32_SYSCALL_BIT */ 0x40000000)
+#    else
+#      define systemd_NR_epoll_pwait2 441
+#    endif
+#  else
+#    warning "epoll_pwait2() syscall number is unknown for your architecture"
+#  endif
+
+/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
+#  if defined __NR_epoll_pwait2 && __NR_epoll_pwait2 >= 0
+#    if defined systemd_NR_epoll_pwait2
+assert_cc(__NR_epoll_pwait2 == systemd_NR_epoll_pwait2);
+#    endif
+#  else
+#    if defined __NR_epoll_pwait2
+#      undef __NR_epoll_pwait2
+#    endif
+#    if defined systemd_NR_epoll_pwait2 && systemd_NR_epoll_pwait2 >= 0
+#      define __NR_epoll_pwait2 systemd_NR_epoll_pwait2
+#    endif
+#  endif
+#endif
index 746fbf4a26055844d8f00292ecd45db76b377072..650f62d1d4f7e33f96fc3383b92dcf45c640d4af 100644 (file)
@@ -17,7 +17,8 @@ SYSCALLS = [
     'pkey_mprotect',
     'renameat2',
     'setns',
-    'statx']
+    'statx',
+    'epoll_pwait2']
 
 def dictify(f):
     def wrap(*args, **kwargs):