summaryrefslogtreecommitdiff
path: root/src/basic/missing_syscall.h
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-02-25 16:56:07 +0100
committerLennart Poettering <lennart@poettering.net>2021-02-26 09:21:51 +0100
commit420297c9e1bf13757394f7f4dd0f312ba953466d (patch)
treeb70d19d8f2c6aa6c6be68800409662d5223b99d3 /src/basic/missing_syscall.h
parent8b2620ea8c0fcec96054b4b48625a6289dd23923 (diff)
downloadsystemd-420297c9e1bf13757394f7f4dd0f312ba953466d.tar.gz
missing_syscall: add epoll_pwait2() wrapper
Diffstat (limited to 'src/basic/missing_syscall.h')
-rw-r--r--src/basic/missing_syscall.h43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
index 52e9d5dea4..1384324804 100644
--- a/src/basic/missing_syscall.h
+++ b/src/basic/missing_syscall.h
@@ -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