From 556fb7131e03b0283672fb40f6dc2d151752aaa7 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 15 Aug 2023 13:55:23 +0200 Subject: [PATCH] tools/nolibc: avoid undesired casts in the __sysret() macro MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Having __sysret() as an inline function has the unfortunate effect of adding casts and large constants comparisons after the syscall returns that significantly inflate some light code that's otherwise syscall- heavy. Even nolibc-test grew by ~1%. Let's switch back to a macro for this, and use it only with signed arguments. Note that it is also possible to design a slightly more complex macro covering unsigned and pointers but we only have 3 such syscalls so it is pointless, and these were just addressed not to use this macro anymore. Now for the argument (the local variable containing the syscall return value), any negative value is an error, that results in -1 being returned and errno to be assigned the opposite value. This may be revisited again in the future if really needed but for now let's get back to something sane. Fixes: 428905da6ec4 ("tools/nolibc: sys.h: add a syscall return helper") Link: https://lore.kernel.org/lkml/20230806095846.GB10627@1wt.eu/ Link: https://lore.kernel.org/lkml/ZNKOJY+g66nkIyvv@1wt.eu/ Cc: Zhangjin Wu Cc: David Laight Cc: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/include/nolibc/sys.h | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index bfe1647..fdb6bd6 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -28,22 +28,21 @@ #include "types.h" -/* Syscall return helper for library routines, set errno as -ret when ret is in - * range of [-MAX_ERRNO, -1] - * - * Note, No official reference states the errno range here aligns with musl - * (src/internal/syscall_ret.c) and glibc (sysdeps/unix/sysv/linux/sysdep.h) +/* Syscall return helper: takes the syscall value in argument and checks for an + * error in it. This may only be used with signed returns (int or long), but + * not with pointers. An error is any value < 0. When an error is encountered, + * -ret is set into errno and -1 is returned. Otherwise the returned value is + * passed as-is with its type preserved. */ -static __inline__ __attribute__((unused, always_inline)) -long __sysret(unsigned long ret) -{ - if (ret >= (unsigned long)-MAX_ERRNO) { - SET_ERRNO(-(long)ret); - return -1; - } - return ret; -} +#define __sysret(arg) \ +({ \ + __typeof__(arg) __sysret_arg = (arg); \ + (__sysret_arg < 0) /* error ? */ \ + ? (({ SET_ERRNO(-__sysret_arg); }), -1) /* ret -1 with errno = -arg */ \ + : __sysret_arg; /* return original value */ \ +}) + /* Functions in this file only describe syscalls. They're declared static so * that the compiler usually decides to inline them while still being allowed -- 2.7.4