path: root/src/linux
diff options
authorRich Felker <>2014-05-29 21:01:32 -0400
committerRich Felker <>2014-05-29 21:01:32 -0400
commitdd5f50da6f6c3df5647e922e47f8568a8896a752 (patch)
treec5ab9a1006d2ab4c449f8fa922ce3237acad30e4 /src/linux
parent2e55da911896a91e95b24ab5dc8a9d9b0718f4de (diff)
support linux kernel apis (new archs) with old syscalls removed
such archs are expected to omit definitions of the SYS_* macros for syscalls their kernels lack from arch/$ARCH/bits/syscall.h. the preprocessor is then able to select the an appropriate implementation for affected functions. two basic strategies are used on a case-by-case basis: where the old syscalls correspond to deprecated library-level functions, the deprecated functions have been converted to wrappers for the modern function, and the modern function has fallback code (omitted at the preprocessor level on new archs) to make use of the old syscalls if the new syscall fails with ENOSYS. this also improves functionality on older kernels and eliminates the incentive to program with deprecated library-level functions for the sake of compatibility with older kernels. in other situations where the old syscalls correspond to library-level functions which are not deprecated but merely lack some new features, such as the *at functions, the old syscalls are still used on archs which support them. this may change at some point in the future if or when fallback code is added to the new functions to make them usable (possibly with reduced functionality) on old kernels.
Diffstat (limited to 'src/linux')
5 files changed, 29 insertions, 8 deletions
diff --git a/src/linux/epoll.c b/src/linux/epoll.c
index 030786d3..b45344fb 100644
--- a/src/linux/epoll.c
+++ b/src/linux/epoll.c
@@ -4,12 +4,16 @@
int epoll_create(int size)
- return syscall(SYS_epoll_create, size);
+ return epoll_create1(0);
int epoll_create1(int flags)
- return syscall(SYS_epoll_create1, flags);
+ int r = __syscall(SYS_epoll_create1, flags);
+#ifdef SYS_epoll_create
+ if (r==-ENOSYS && !flags) r = __syscall(SYS_epoll_create, 1);
+ return __syscall_ret(r);
int epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev)
@@ -19,10 +23,14 @@ int epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev)
int epoll_pwait(int fd, struct epoll_event *ev, int cnt, int to, const sigset_t *sigs)
- return syscall(SYS_epoll_pwait, fd, ev, cnt, to, sigs, _NSIG/8);
+ int r = __syscall(SYS_epoll_pwait, fd, ev, cnt, to, sigs, _NSIG/8);
+#ifdef SYS_epoll_wait
+ if (r==-ENOSYS && !sigs) r = __syscall(SYS_epoll_wait, fd, ev, cnt, to);
+ return __syscall_ret(r);
int epoll_wait(int fd, struct epoll_event *ev, int cnt, int to)
- return syscall(SYS_epoll_wait, fd, ev, cnt, to);
+ return epoll_pwait(fd, ev, cnt, to, 0);
diff --git a/src/linux/eventfd.c b/src/linux/eventfd.c
index 53066487..39968034 100644
--- a/src/linux/eventfd.c
+++ b/src/linux/eventfd.c
@@ -4,7 +4,11 @@
int eventfd(unsigned int count, int flags)
- return syscall(flags ? SYS_eventfd2 : SYS_eventfd, count, flags);
+ int r = __syscall(SYS_eventfd2, count, flags);
+#ifdef SYS_eventfd
+ if (r==-ENOSYS && !flags) r = __syscall(SYS_eventfd, count);
+ return __syscall_ret(r);
int eventfd_read(int fd, eventfd_t *value)
diff --git a/src/linux/inotify.c b/src/linux/inotify.c
index a417c891..84a56154 100644
--- a/src/linux/inotify.c
+++ b/src/linux/inotify.c
@@ -3,11 +3,15 @@
int inotify_init()
- return syscall(SYS_inotify_init);
+ return inotify_init1(0);
int inotify_init1(int flags)
- return syscall(SYS_inotify_init1, flags);
+ int r = __syscall(SYS_inotify_init1, flags);
+#ifdef SYS_inotify_init
+ if (r==-ENOSYS && !flags) r = __syscall(SYS_inotify_init);
+ return __syscall_ret(r);
int inotify_add_watch(int fd, const char *pathname, uint32_t mask)
diff --git a/src/linux/signalfd.c b/src/linux/signalfd.c
index da6bcedb..4bf43326 100644
--- a/src/linux/signalfd.c
+++ b/src/linux/signalfd.c
@@ -7,6 +7,7 @@
int signalfd(int fd, const sigset_t *sigs, int flags)
int ret = __syscall(SYS_signalfd4, fd, sigs, _NSIG/8, flags);
+#ifdef SYS_signalfd
if (ret != -ENOSYS) return __syscall_ret(ret);
ret = __syscall(SYS_signalfd, fd, sigs, _NSIG/8);
if (ret >= 0) {
@@ -15,5 +16,6 @@ int signalfd(int fd, const sigset_t *sigs, int flags)
if (flags & SFD_NONBLOCK)
__syscall(SYS_fcntl, ret, F_SETFL, O_NONBLOCK);
return __syscall_ret(ret);
diff --git a/src/linux/utimes.c b/src/linux/utimes.c
index 70c0695f..b814c88b 100644
--- a/src/linux/utimes.c
+++ b/src/linux/utimes.c
@@ -1,7 +1,10 @@
#include <sys/time.h>
+#include "fcntl.h"
#include "syscall.h"
+int __futimesat(int, const char *, const struct timeval [2]);
int utimes(const char *path, const struct timeval times[2])
- return syscall(SYS_utimes, path, times);
+ return __futimesat(AT_FDCWD, path, times);