The __nolibc_enosys() fallback is used when the UAPI headers do not provide a certain syscall number or any possible fallback syscall. This is either because the syscall definition is fairly new and nolibc tries to be compatible with old UAPI headers or an architecture does not support a syscall at all. Many of these __nolibc_enosys() fallbacks have become unnecessary. Either because the "new" syscalls or not so new anymore or real fallbacks have been implemented in the meantime.
Unnecessary usages of __nolibc_enosys() as it is not obvious anymore if a given function is really implemented on all architectures.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- Thomas Weißschuh (7): tools/nolibc: remove __nolibc_enosys() fallback from time64-related functions tools/nolibc: remove __nolibc_enosys() fallback from *at() functions tools/nolibc: remove __nolibc_enosys() fallback from dup2() tools/nolibc: remove __nolibc_enosys() fallback from fork functions tools/nolibc: fold llseek fallback into lseek() kselftest/arm64: tpidr2: Switch to waitpid() over wait4() tools/nolibc: drop wait4() support
tools/include/nolibc/poll.h | 4 +- tools/include/nolibc/sys.h | 90 +++++++++--------------------- tools/include/nolibc/sys/timerfd.h | 8 +-- tools/include/nolibc/sys/wait.h | 17 ------ tools/include/nolibc/time.h | 8 +-- tools/testing/selftests/arm64/abi/tpidr2.c | 6 +- 6 files changed, 34 insertions(+), 99 deletions(-) --- base-commit: 850047b19741490631855a475ccaa3ed29316039 change-id: 20250821-nolibc-enosys-2b2ec0b505ba
Best regards,
These fallbacks where added when no explicit fallbacks for time64 was implemented. Now that these fallbacks are in place, the additional fallback to __nolibc_enosys() is superfluous.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/poll.h | 4 +--- tools/include/nolibc/sys.h | 4 +--- tools/include/nolibc/sys/timerfd.h | 8 ++------ tools/include/nolibc/time.h | 8 ++------ 4 files changed, 6 insertions(+), 18 deletions(-)
diff --git a/tools/include/nolibc/poll.h b/tools/include/nolibc/poll.h index 1765acb17ea01ff53cbad0b4750e4938446b6a45..0d053f93ea99b0363b4bdfd2c400d6df2f932684 100644 --- a/tools/include/nolibc/poll.h +++ b/tools/include/nolibc/poll.h @@ -39,10 +39,8 @@ int sys_poll(struct pollfd *fds, int nfds, int timeout) t.tv_nsec = (timeout % 1000) * 1000000; } return my_syscall5(__NR_ppoll_time64, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0); -#elif defined(__NR_poll) - return my_syscall3(__NR_poll, fds, nfds, timeout); #else - return __nolibc_enosys(__func__, fds, nfds, timeout); + return my_syscall3(__NR_poll, fds, nfds, timeout); #endif }
diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 295e71d34abadb7f9c7ca995012b4395b6830975..4e5389edda03a61e76ad0377213e8ef0a621d300 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -801,7 +801,7 @@ int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeva t.tv_nsec = timeout->tv_usec * 1000; } return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); -#elif defined(__NR_pselect6_time64) +#else struct __kernel_timespec t;
if (timeout) { @@ -809,8 +809,6 @@ int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeva t.tv_nsec = timeout->tv_usec * 1000; } return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); -#else - return __nolibc_enosys(__func__, nfds, rfds, wfds, efds, timeout); #endif }
diff --git a/tools/include/nolibc/sys/timerfd.h b/tools/include/nolibc/sys/timerfd.h index 4375d546ba58f849b3ba48e7b221e6ec3c15fcf6..5dd61030c9914d2b6b2a71130d07a32ef7c37781 100644 --- a/tools/include/nolibc/sys/timerfd.h +++ b/tools/include/nolibc/sys/timerfd.h @@ -34,7 +34,7 @@ int sys_timerfd_gettime(int fd, struct itimerspec *curr_value) { #if defined(__NR_timerfd_gettime) return my_syscall2(__NR_timerfd_gettime, fd, curr_value); -#elif defined(__NR_timerfd_gettime64) +#else struct __kernel_itimerspec kcurr_value; int ret;
@@ -42,8 +42,6 @@ int sys_timerfd_gettime(int fd, struct itimerspec *curr_value) __nolibc_timespec_kernel_to_user(&kcurr_value.it_interval, &curr_value->it_interval); __nolibc_timespec_kernel_to_user(&kcurr_value.it_value, &curr_value->it_value); return ret; -#else - return __nolibc_enosys(__func__, fd, curr_value); #endif }
@@ -60,7 +58,7 @@ int sys_timerfd_settime(int fd, int flags, { #if defined(__NR_timerfd_settime) return my_syscall4(__NR_timerfd_settime, fd, flags, new_value, old_value); -#elif defined(__NR_timerfd_settime64) +#else struct __kernel_itimerspec knew_value, kold_value; int ret;
@@ -72,8 +70,6 @@ int sys_timerfd_settime(int fd, int flags, __nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value); } return ret; -#else - return __nolibc_enosys(__func__, fd, flags, new_value, old_value); #endif }
diff --git a/tools/include/nolibc/time.h b/tools/include/nolibc/time.h index e9c1b976791a65c0d73268bebbcfd4f2a57a47ee..6c276b8d646a4e8fd84162b6cb74c73649a092c2 100644 --- a/tools/include/nolibc/time.h +++ b/tools/include/nolibc/time.h @@ -45,7 +45,7 @@ int sys_clock_getres(clockid_t clockid, struct timespec *res) { #if defined(__NR_clock_getres) return my_syscall2(__NR_clock_getres, clockid, res); -#elif defined(__NR_clock_getres_time64) +#else struct __kernel_timespec kres; int ret;
@@ -53,8 +53,6 @@ int sys_clock_getres(clockid_t clockid, struct timespec *res) if (res) __nolibc_timespec_kernel_to_user(&kres, res); return ret; -#else - return __nolibc_enosys(__func__, clockid, res); #endif }
@@ -69,7 +67,7 @@ int sys_clock_gettime(clockid_t clockid, struct timespec *tp) { #if defined(__NR_clock_gettime) return my_syscall2(__NR_clock_gettime, clockid, tp); -#elif defined(__NR_clock_gettime64) +#else struct __kernel_timespec ktp; int ret;
@@ -77,8 +75,6 @@ int sys_clock_gettime(clockid_t clockid, struct timespec *tp) if (tp) __nolibc_timespec_kernel_to_user(&ktp, tp); return ret; -#else - return __nolibc_enosys(__func__, clockid, tp); #endif }
All architectures have had one of the real functions available since Linux 2.6.12. The additional fallback to __nolibc_enosys() is superfluous.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/sys.h | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-)
diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 4e5389edda03a61e76ad0377213e8ef0a621d300..2b9c3bf697e74e80016606814fe21929512ca007 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -142,10 +142,8 @@ int sys_chmod(const char *path, mode_t mode) { #if defined(__NR_fchmodat) return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0); -#elif defined(__NR_chmod) - return my_syscall2(__NR_chmod, path, mode); #else - return __nolibc_enosys(__func__, path, mode); + return my_syscall2(__NR_chmod, path, mode); #endif }
@@ -165,10 +163,8 @@ int sys_chown(const char *path, uid_t owner, gid_t group) { #if defined(__NR_fchownat) return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0); -#elif defined(__NR_chown) - return my_syscall3(__NR_chown, path, owner, group); #else - return __nolibc_enosys(__func__, path, owner, group); + return my_syscall3(__NR_chown, path, owner, group); #endif }
@@ -569,10 +565,8 @@ int sys_link(const char *old, const char *new) { #if defined(__NR_linkat) return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); -#elif defined(__NR_link) - return my_syscall2(__NR_link, old, new); #else - return __nolibc_enosys(__func__, old, new); + return my_syscall2(__NR_link, old, new); #endif }
@@ -640,10 +634,8 @@ int sys_mkdir(const char *path, mode_t mode) { #if defined(__NR_mkdirat) return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); -#elif defined(__NR_mkdir) - return my_syscall2(__NR_mkdir, path, mode); #else - return __nolibc_enosys(__func__, path, mode); + return my_syscall2(__NR_mkdir, path, mode); #endif }
@@ -662,10 +654,8 @@ int sys_rmdir(const char *path) { #if defined(__NR_rmdir) return my_syscall1(__NR_rmdir, path); -#elif defined(__NR_unlinkat) - return my_syscall3(__NR_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); #else - return __nolibc_enosys(__func__, path); + return my_syscall3(__NR_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); #endif }
@@ -685,10 +675,8 @@ long sys_mknod(const char *path, mode_t mode, dev_t dev) { #if defined(__NR_mknodat) return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); -#elif defined(__NR_mknod) - return my_syscall3(__NR_mknod, path, mode, dev); #else - return __nolibc_enosys(__func__, path, mode, dev); + return my_syscall3(__NR_mknod, path, mode, dev); #endif }
@@ -872,10 +860,8 @@ int sys_symlink(const char *old, const char *new) { #if defined(__NR_symlinkat) return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); -#elif defined(__NR_symlink) - return my_syscall2(__NR_symlink, old, new); #else - return __nolibc_enosys(__func__, old, new); + return my_syscall2(__NR_symlink, old, new); #endif }
@@ -929,10 +915,8 @@ int sys_unlink(const char *path) { #if defined(__NR_unlinkat) return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); -#elif defined(__NR_unlink) - return my_syscall1(__NR_unlink, path); #else - return __nolibc_enosys(__func__, path); + return my_syscall1(__NR_unlink, path); #endif }
All architectures have one of the real functions available. The additional fallback to __nolibc_enosys() is superfluous.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/sys.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 2b9c3bf697e74e80016606814fe21929512ca007..9c4fa7efc1d606f18a5a92b0a3dd9ad7b9b4521b 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -235,10 +235,8 @@ int sys_dup2(int old, int new) { #if defined(__NR_dup3) return my_syscall3(__NR_dup3, old, new, 0); -#elif defined(__NR_dup2) - return my_syscall2(__NR_dup2, old, new); #else - return __nolibc_enosys(__func__, old, new); + return my_syscall2(__NR_dup2, old, new); #endif }
All architectures have one of the real functions available. The additional fallback to __nolibc_enosys() is superfluous.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/sys.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 9c4fa7efc1d606f18a5a92b0a3dd9ad7b9b4521b..fc3c8a3d02e9a031aad2229a430c232eb60065b1 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -321,10 +321,8 @@ pid_t sys_fork(void) * will not use the rest with no other flag. */ return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0); -#elif defined(__NR_fork) - return my_syscall0(__NR_fork); #else - return __nolibc_enosys(__func__); + return my_syscall0(__NR_fork); #endif } #endif @@ -341,7 +339,7 @@ pid_t sys_vfork(void) { #if defined(__NR_vfork) return my_syscall0(__NR_vfork); -#elif defined(__NR_clone3) +#else /* * clone() could be used but has different argument orders per * architecture. @@ -352,8 +350,6 @@ pid_t sys_vfork(void) };
return my_syscall2(__NR_clone3, &args, sizeof(args)); -#else - return __nolibc_enosys(__func__); #endif } #endif
Align the implementation of the fallback handling inside sys_lseek() with the rest of nolibc.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/sys.h | 42 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 28 deletions(-)
diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index fc3c8a3d02e9a031aad2229a430c232eb60065b1..f31db0f471131f82389129989054e2b55a41a7cb 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -581,41 +581,27 @@ off_t sys_lseek(int fd, off_t offset, int whence) #if defined(__NR_lseek) return my_syscall3(__NR_lseek, fd, offset, whence); #else - return __nolibc_enosys(__func__, fd, offset, whence); -#endif -} + __kernel_loff_t loff = 0; + off_t result; + int ret;
-static __attribute__((unused)) -int sys_llseek(int fd, unsigned long offset_high, unsigned long offset_low, - __kernel_loff_t *result, int whence) -{ -#if defined(__NR_llseek) - return my_syscall5(__NR_llseek, fd, offset_high, offset_low, result, whence); -#else - return __nolibc_enosys(__func__, fd, offset_high, offset_low, result, whence); + /* Only exists on 32bit where nolibc off_t is also 32bit */ + ret = my_syscall5(__NR_llseek, fd, 0, offset, &loff, whence); + if (ret < 0) + result = ret; + else if (loff != (off_t)loff) + result = -EOVERFLOW; + else + result = loff; + + return result; #endif }
static __attribute__((unused)) off_t lseek(int fd, off_t offset, int whence) { - __kernel_loff_t loff = 0; - off_t result; - int ret; - - result = sys_lseek(fd, offset, whence); - if (result == -ENOSYS) { - /* Only exists on 32bit where nolibc off_t is also 32bit */ - ret = sys_llseek(fd, 0, offset, &loff, whence); - if (ret < 0) - result = ret; - else if (loff != (off_t)loff) - result = -EOVERFLOW; - else - result = loff; - } - - return __sysret(result); + return __sysret(sys_lseek(fd, offset, whence)); }
wait4() is deprecated, non-standard and about to be removed from nolibc.
Switch to the equivalent waitpid() call.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/testing/selftests/arm64/abi/tpidr2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/arm64/abi/tpidr2.c b/tools/testing/selftests/arm64/abi/tpidr2.c index f58a9f89b952c42c5393b93a2db4fefe3f335e5a..3b520b7efa49e0058616c04fcdc0222bd8b03d8a 100644 --- a/tools/testing/selftests/arm64/abi/tpidr2.c +++ b/tools/testing/selftests/arm64/abi/tpidr2.c @@ -182,16 +182,16 @@ static int write_clone_read(void) }
for (;;) { - waiting = wait4(ret, &status, __WCLONE, NULL); + waiting = waitpid(ret, &status, __WCLONE);
if (waiting < 0) { if (errno == EINTR) continue; - ksft_print_msg("wait4() failed: %d\n", errno); + ksft_print_msg("waitpid() failed: %d\n", errno); return 0; } if (waiting != ret) { - ksft_print_msg("wait4() returned wrong PID %d\n", + ksft_print_msg("waitpid() returned wrong PID %d\n", waiting); return 0; }
On Thu, Aug 21, 2025 at 05:40:37PM +0200, Thomas Weißschuh wrote:
wait4() is deprecated, non-standard and about to be removed from nolibc.
Switch to the equivalent waitpid() call.
Reviewed-by: Mark Brown broonie@kernel.org
Not all architectures implement the wait4() syscall. It can be implemented in terms of the waitid() syscall, but that would require some rework of the other wait-related functions in wait.h.
As wait4() is non-standard and deprecated, remove it.
Signed-off-by: Thomas Weißschuh linux@weissschuh.net --- tools/include/nolibc/sys/wait.h | 17 ----------------- 1 file changed, 17 deletions(-)
diff --git a/tools/include/nolibc/sys/wait.h b/tools/include/nolibc/sys/wait.h index 56ddb806da7f2466be5523b52fd01480b711daec..4e66e1f7a03e4585c91ec4ea68333b910600239a 100644 --- a/tools/include/nolibc/sys/wait.h +++ b/tools/include/nolibc/sys/wait.h @@ -16,27 +16,10 @@
/* * pid_t wait(int *status); - * pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage); * pid_t waitpid(pid_t pid, int *status, int options); * int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options); */
-static __attribute__((unused)) -pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage) -{ -#ifdef __NR_wait4 - return my_syscall4(__NR_wait4, pid, status, options, rusage); -#else - return __nolibc_enosys(__func__, pid, status, options, rusage); -#endif -} - -static __attribute__((unused)) -pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) -{ - return __sysret(sys_wait4(pid, status, options, rusage)); -} - static __attribute__((unused)) int sys_waitid(int which, pid_t pid, siginfo_t *infop, int options, struct rusage *rusage) {
linux-kselftest-mirror@lists.linaro.org