* [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types
@ 2025-11-22 16:59 Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 01/13] tools/nolibc/poll: use kernel types for system call invocations Thomas Weißschuh
` (13 more replies)
0 siblings, 14 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
nolibc currently uses 32-bit types for various APIs. These are
problematic as their reduced value range can lead to truncated values.
Intended for 6.19.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
Changes in v2:
- Drop already applied ino_t and off_t patches.
- Also handle 'struct timeval'.
- Make the progression of the series a bit clearer.
- Add compatibility assertions.
- Link to v1: https://lore.kernel.org/r/20251029-nolibc-uapi-types-v1-0-e79de3b215d8@weissschuh.net
---
Thomas Weißschuh (13):
tools/nolibc/poll: use kernel types for system call invocations
tools/nolibc/poll: drop __NR_poll fallback
tools/nolibc/select: drop non-pselect based implementations
tools/nolibc/time: drop invocation of gettimeofday system call
tools/nolibc: prefer explicit 64-bit time-related system calls
tools/nolibc/gettimeofday: avoid libgcc 64-bit divisions
tools/nolibc/select: avoid libgcc 64-bit multiplications
tools/nolibc: use custom structs timespec and timeval
tools/nolibc: always use 64-bit time types
selftests/nolibc: test compatibility of nolibc and kernel time types
tools/nolibc: remove time conversions
tools/nolibc: add __nolibc_static_assert()
selftests/nolibc: add static assertions around time types handling
tools/include/nolibc/arch-s390.h | 3 +
tools/include/nolibc/compiler.h | 2 +
tools/include/nolibc/poll.h | 14 ++--
tools/include/nolibc/std.h | 2 +-
tools/include/nolibc/sys/select.h | 25 ++-----
tools/include/nolibc/sys/time.h | 6 +-
tools/include/nolibc/sys/timerfd.h | 32 +++------
tools/include/nolibc/time.h | 102 +++++++++------------------
tools/include/nolibc/types.h | 17 ++++-
tools/testing/selftests/nolibc/nolibc-test.c | 27 +++++++
10 files changed, 107 insertions(+), 123 deletions(-)
---
base-commit: 586e8d5137dfcddfccca44c3b992b92d2be79347
change-id: 20251001-nolibc-uapi-types-1c072d10fcc7
Best regards,
--
Thomas Weißschuh <linux@weissschuh.net>
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v2 01/13] tools/nolibc/poll: use kernel types for system call invocations
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 02/13] tools/nolibc/poll: drop __NR_poll fallback Thomas Weißschuh
` (12 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
The system calls expect 'struct __kernel_old_timespec'.
While currently 'struct __kernel_old_timespec' and 'struct timespec' are
compatible, this is confusing. Especially as future patches will change
the definition of 'struct timespec'.
Use the correct kernel type instead.
Suggested-by: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/lkml/fbca1d3e-12e4-4c4e-8091-87464035fe39@app.fastmail.com/
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/include/nolibc/poll.h | 2 +-
tools/include/nolibc/sys/select.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/include/nolibc/poll.h b/tools/include/nolibc/poll.h
index 0d053f93ea99..df952bcf0905 100644
--- a/tools/include/nolibc/poll.h
+++ b/tools/include/nolibc/poll.h
@@ -24,7 +24,7 @@ static __attribute__((unused))
int sys_poll(struct pollfd *fds, int nfds, int timeout)
{
#if defined(__NR_ppoll)
- struct timespec t;
+ struct __kernel_old_timespec t;
if (timeout >= 0) {
t.tv_sec = timeout / 1000;
diff --git a/tools/include/nolibc/sys/select.h b/tools/include/nolibc/sys/select.h
index 2a5619c01277..9a29e5b98a3c 100644
--- a/tools/include/nolibc/sys/select.h
+++ b/tools/include/nolibc/sys/select.h
@@ -75,7 +75,7 @@ int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeva
#elif defined(__NR_select)
return my_syscall5(__NR_select, nfds, rfds, wfds, efds, timeout);
#elif defined(__NR_pselect6)
- struct timespec t;
+ struct __kernel_old_timespec t;
if (timeout) {
t.tv_sec = timeout->tv_sec;
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 02/13] tools/nolibc/poll: drop __NR_poll fallback
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 01/13] tools/nolibc/poll: use kernel types for system call invocations Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 03/13] tools/nolibc/select: drop non-pselect based implementations Thomas Weißschuh
` (11 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
This fallback is never used, remove it.
Suggested-by: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/lkml/fbca1d3e-12e4-4c4e-8091-87464035fe39@app.fastmail.com/
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/include/nolibc/poll.h | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/tools/include/nolibc/poll.h b/tools/include/nolibc/poll.h
index df952bcf0905..5b4fa339fbb5 100644
--- a/tools/include/nolibc/poll.h
+++ b/tools/include/nolibc/poll.h
@@ -31,7 +31,7 @@ int sys_poll(struct pollfd *fds, int nfds, int timeout)
t.tv_nsec = (timeout % 1000) * 1000000;
}
return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
-#elif defined(__NR_ppoll_time64)
+#else
struct __kernel_timespec t;
if (timeout >= 0) {
@@ -39,8 +39,6 @@ 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);
-#else
- return my_syscall3(__NR_poll, fds, nfds, timeout);
#endif
}
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 03/13] tools/nolibc/select: drop non-pselect based implementations
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 01/13] tools/nolibc/poll: use kernel types for system call invocations Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 02/13] tools/nolibc/poll: drop __NR_poll fallback Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 04/13] tools/nolibc/time: drop invocation of gettimeofday system call Thomas Weißschuh
` (10 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
These implementations use the libc 'struct timeval' with system calls
which can lead to type mismatches. Currently this is fine, but will
break with upcoming changes to 'struct timeval'.
If the structure needs to be converted anyways, the implementations
based on pselect can be used for all architectures. This simplifies the
logic.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/include/nolibc/sys/select.h | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/tools/include/nolibc/sys/select.h b/tools/include/nolibc/sys/select.h
index 9a29e5b98a3c..50b77dace7ef 100644
--- a/tools/include/nolibc/sys/select.h
+++ b/tools/include/nolibc/sys/select.h
@@ -63,18 +63,7 @@ typedef struct {
static __attribute__((unused))
int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
{
-#if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect)
- struct sel_arg_struct {
- unsigned long n;
- fd_set *r, *w, *e;
- struct timeval *t;
- } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout };
- return my_syscall1(__NR_select, &arg);
-#elif defined(__NR__newselect)
- return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout);
-#elif defined(__NR_select)
- return my_syscall5(__NR_select, nfds, rfds, wfds, efds, timeout);
-#elif defined(__NR_pselect6)
+#if defined(__NR_pselect6)
struct __kernel_old_timespec t;
if (timeout) {
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 04/13] tools/nolibc/time: drop invocation of gettimeofday system call
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
` (2 preceding siblings ...)
2025-11-22 16:59 ` [PATCH v2 03/13] tools/nolibc/select: drop non-pselect based implementations Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-30 10:42 ` Willy Tarreau
2025-11-22 16:59 ` [PATCH v2 05/13] tools/nolibc: prefer explicit 64-bit time-related system calls Thomas Weißschuh
` (9 subsequent siblings)
13 siblings, 1 reply; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
This invocation uses libc types with a system call. While this works
now, upcoming changes to 'struct timeval' would require type
conversions. If types are converted anyways, the clock_gettime() based
fallback can be used everywhere, simplifying the code.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/include/nolibc/sys/time.h | 4 ----
1 file changed, 4 deletions(-)
diff --git a/tools/include/nolibc/sys/time.h b/tools/include/nolibc/sys/time.h
index 33782a19aae9..171187836e6d 100644
--- a/tools/include/nolibc/sys/time.h
+++ b/tools/include/nolibc/sys/time.h
@@ -22,9 +22,6 @@ static int sys_clock_gettime(clockid_t clockid, struct timespec *tp);
static __attribute__((unused))
int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
{
-#ifdef __NR_gettimeofday
- return my_syscall2(__NR_gettimeofday, tv, tz);
-#else
(void) tz; /* Non-NULL tz is undefined behaviour */
struct timespec tp;
@@ -37,7 +34,6 @@ int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
}
return ret;
-#endif
}
static __attribute__((unused))
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 05/13] tools/nolibc: prefer explicit 64-bit time-related system calls
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
` (3 preceding siblings ...)
2025-11-22 16:59 ` [PATCH v2 04/13] tools/nolibc/time: drop invocation of gettimeofday system call Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 06/13] tools/nolibc/gettimeofday: avoid libgcc 64-bit divisions Thomas Weißschuh
` (8 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
Make sure to always use the 64-bit safe system calls
in preparation for 64-bit time_t on 32-bit architectures.
Also prevent issues on kernels which disable CONFIG_COMPAT_32BIT_TIME
and therefore don't provide the 32-bit system calls anymore.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/include/nolibc/poll.h | 10 +++++-----
tools/include/nolibc/sys/select.h | 10 +++++-----
tools/include/nolibc/sys/timerfd.h | 12 ++++++------
tools/include/nolibc/time.h | 36 ++++++++++++++++++------------------
4 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/tools/include/nolibc/poll.h b/tools/include/nolibc/poll.h
index 5b4fa339fbb5..e854c94647b1 100644
--- a/tools/include/nolibc/poll.h
+++ b/tools/include/nolibc/poll.h
@@ -23,22 +23,22 @@
static __attribute__((unused))
int sys_poll(struct pollfd *fds, int nfds, int timeout)
{
-#if defined(__NR_ppoll)
- struct __kernel_old_timespec t;
+#if defined(__NR_ppoll_time64)
+ struct __kernel_timespec t;
if (timeout >= 0) {
t.tv_sec = timeout / 1000;
t.tv_nsec = (timeout % 1000) * 1000000;
}
- return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
+ return my_syscall5(__NR_ppoll_time64, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
#else
- struct __kernel_timespec t;
+ struct __kernel_old_timespec t;
if (timeout >= 0) {
t.tv_sec = timeout / 1000;
t.tv_nsec = (timeout % 1000) * 1000000;
}
- return my_syscall5(__NR_ppoll_time64, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
+ return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
#endif
}
diff --git a/tools/include/nolibc/sys/select.h b/tools/include/nolibc/sys/select.h
index 50b77dace7ef..f8870ad49687 100644
--- a/tools/include/nolibc/sys/select.h
+++ b/tools/include/nolibc/sys/select.h
@@ -63,22 +63,22 @@ typedef struct {
static __attribute__((unused))
int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
{
-#if defined(__NR_pselect6)
- struct __kernel_old_timespec t;
+#if defined(__NR_pselect6_time64)
+ struct __kernel_timespec t;
if (timeout) {
t.tv_sec = timeout->tv_sec;
t.tv_nsec = timeout->tv_usec * 1000;
}
- return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
+ return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
#else
- struct __kernel_timespec t;
+ struct __kernel_old_timespec t;
if (timeout) {
t.tv_sec = timeout->tv_sec;
t.tv_nsec = timeout->tv_usec * 1000;
}
- return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
+ return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
#endif
}
diff --git a/tools/include/nolibc/sys/timerfd.h b/tools/include/nolibc/sys/timerfd.h
index 5dd61030c991..66f779553d31 100644
--- a/tools/include/nolibc/sys/timerfd.h
+++ b/tools/include/nolibc/sys/timerfd.h
@@ -32,9 +32,7 @@ int timerfd_create(int clockid, int flags)
static __attribute__((unused))
int sys_timerfd_gettime(int fd, struct itimerspec *curr_value)
{
-#if defined(__NR_timerfd_gettime)
- return my_syscall2(__NR_timerfd_gettime, fd, curr_value);
-#else
+#if defined(__NR_timerfd_gettime64)
struct __kernel_itimerspec kcurr_value;
int ret;
@@ -42,6 +40,8 @@ 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 my_syscall2(__NR_timerfd_gettime, fd, curr_value);
#endif
}
@@ -56,9 +56,7 @@ static __attribute__((unused))
int sys_timerfd_settime(int fd, int flags,
const struct itimerspec *new_value, struct itimerspec *old_value)
{
-#if defined(__NR_timerfd_settime)
- return my_syscall4(__NR_timerfd_settime, fd, flags, new_value, old_value);
-#else
+#if defined(__NR_timerfd_settime64)
struct __kernel_itimerspec knew_value, kold_value;
int ret;
@@ -70,6 +68,8 @@ 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 my_syscall4(__NR_timerfd_settime, fd, flags, new_value, old_value);
#endif
}
diff --git a/tools/include/nolibc/time.h b/tools/include/nolibc/time.h
index 48e78f8becf9..45df9b09d7b6 100644
--- a/tools/include/nolibc/time.h
+++ b/tools/include/nolibc/time.h
@@ -43,9 +43,7 @@ void __nolibc_timespec_kernel_to_user(const struct __kernel_timespec *kts, struc
static __attribute__((unused))
int sys_clock_getres(clockid_t clockid, struct timespec *res)
{
-#if defined(__NR_clock_getres)
- return my_syscall2(__NR_clock_getres, clockid, res);
-#else
+#if defined(__NR_clock_getres_time64)
struct __kernel_timespec kres;
int ret;
@@ -53,6 +51,8 @@ int sys_clock_getres(clockid_t clockid, struct timespec *res)
if (res)
__nolibc_timespec_kernel_to_user(&kres, res);
return ret;
+#else
+ return my_syscall2(__NR_clock_getres, clockid, res);
#endif
}
@@ -65,9 +65,7 @@ int clock_getres(clockid_t clockid, struct timespec *res)
static __attribute__((unused))
int sys_clock_gettime(clockid_t clockid, struct timespec *tp)
{
-#if defined(__NR_clock_gettime)
- return my_syscall2(__NR_clock_gettime, clockid, tp);
-#else
+#if defined(__NR_clock_gettime64)
struct __kernel_timespec ktp;
int ret;
@@ -75,6 +73,8 @@ int sys_clock_gettime(clockid_t clockid, struct timespec *tp)
if (tp)
__nolibc_timespec_kernel_to_user(&ktp, tp);
return ret;
+#else
+ return my_syscall2(__NR_clock_gettime, clockid, tp);
#endif
}
@@ -87,13 +87,13 @@ int clock_gettime(clockid_t clockid, struct timespec *tp)
static __attribute__((unused))
int sys_clock_settime(clockid_t clockid, struct timespec *tp)
{
-#if defined(__NR_clock_settime)
- return my_syscall2(__NR_clock_settime, clockid, tp);
-#else
+#if defined(__NR_clock_settime64)
struct __kernel_timespec ktp;
__nolibc_timespec_user_to_kernel(tp, &ktp);
return my_syscall2(__NR_clock_settime64, clockid, &ktp);
+#else
+ return my_syscall2(__NR_clock_settime, clockid, tp);
#endif
}
@@ -107,9 +107,7 @@ static __attribute__((unused))
int sys_clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp,
struct timespec *rmtp)
{
-#if defined(__NR_clock_nanosleep)
- return my_syscall4(__NR_clock_nanosleep, clockid, flags, rqtp, rmtp);
-#else
+#if defined(__NR_clock_nanosleep_time64)
struct __kernel_timespec krqtp, krmtp;
int ret;
@@ -118,6 +116,8 @@ int sys_clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqt
if (rmtp)
__nolibc_timespec_kernel_to_user(&krmtp, rmtp);
return ret;
+#else
+ return my_syscall4(__NR_clock_nanosleep, clockid, flags, rqtp, rmtp);
#endif
}
@@ -189,9 +189,7 @@ int timer_delete(timer_t timerid)
static __attribute__((unused))
int sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value)
{
-#if defined(__NR_timer_gettime)
- return my_syscall2(__NR_timer_gettime, timerid, curr_value);
-#else
+#if defined(__NR_timer_gettime64)
struct __kernel_itimerspec kcurr_value;
int ret;
@@ -199,6 +197,8 @@ int sys_timer_gettime(timer_t timerid, 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 my_syscall2(__NR_timer_gettime, timerid, curr_value);
#endif
}
@@ -212,9 +212,7 @@ static __attribute__((unused))
int sys_timer_settime(timer_t timerid, int flags,
const struct itimerspec *new_value, struct itimerspec *old_value)
{
-#if defined(__NR_timer_settime)
- return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value);
-#else
+#if defined(__NR_timer_settime64)
struct __kernel_itimerspec knew_value, kold_value;
int ret;
@@ -226,6 +224,8 @@ int sys_timer_settime(timer_t timerid, int flags,
__nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value);
}
return ret;
+#else
+ return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value);
#endif
}
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 06/13] tools/nolibc/gettimeofday: avoid libgcc 64-bit divisions
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
` (4 preceding siblings ...)
2025-11-22 16:59 ` [PATCH v2 05/13] tools/nolibc: prefer explicit 64-bit time-related system calls Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 07/13] tools/nolibc/select: avoid libgcc 64-bit multiplications Thomas Weißschuh
` (7 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
timespec::tv_nsec is going to be 64-bit wide even on 32-bit
architectures. As not all architectures support 64-bit division
instructions, calls to libgcc (__divdi3()) may be emitted by the
compiler which are not provided by nolibc.
As tv_nsec is guaranteed to always fit into an uint32_t, perform a
32-bit division instead.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Willy Tarreau <w@1wt.eu>
---
tools/include/nolibc/sys/time.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/include/nolibc/sys/time.h b/tools/include/nolibc/sys/time.h
index 171187836e6d..afdb7e326df1 100644
--- a/tools/include/nolibc/sys/time.h
+++ b/tools/include/nolibc/sys/time.h
@@ -30,7 +30,7 @@ int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
ret = sys_clock_gettime(CLOCK_REALTIME, &tp);
if (!ret && tv) {
tv->tv_sec = tp.tv_sec;
- tv->tv_usec = tp.tv_nsec / 1000;
+ tv->tv_usec = (uint32_t)tp.tv_nsec / 1000;
}
return ret;
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 07/13] tools/nolibc/select: avoid libgcc 64-bit multiplications
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
` (5 preceding siblings ...)
2025-11-22 16:59 ` [PATCH v2 06/13] tools/nolibc/gettimeofday: avoid libgcc 64-bit divisions Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 08/13] tools/nolibc: use custom structs timespec and timeval Thomas Weißschuh
` (6 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
timeval::tv_usec is going to be 64-bit wide even on 32-bit
architectures. As not all architectures support 64-bit multiplications
instructions, calls to libgcc (__multi3()) may be emitted by the
compiler which are not provided by nolibc.
As tv_usec and tv_nsec are guaranteed to always fit into an uint32_t,
perform a 32-bit multiplication instead.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/include/nolibc/sys/select.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/include/nolibc/sys/select.h b/tools/include/nolibc/sys/select.h
index f8870ad49687..80cb3755ba18 100644
--- a/tools/include/nolibc/sys/select.h
+++ b/tools/include/nolibc/sys/select.h
@@ -68,7 +68,7 @@ int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeva
if (timeout) {
t.tv_sec = timeout->tv_sec;
- t.tv_nsec = timeout->tv_usec * 1000;
+ t.tv_nsec = (uint32_t)timeout->tv_usec * 1000;
}
return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
#else
@@ -76,7 +76,7 @@ int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeva
if (timeout) {
t.tv_sec = timeout->tv_sec;
- t.tv_nsec = timeout->tv_usec * 1000;
+ t.tv_nsec = (uint32_t)timeout->tv_usec * 1000;
}
return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
#endif
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 08/13] tools/nolibc: use custom structs timespec and timeval
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
` (6 preceding siblings ...)
2025-11-22 16:59 ` [PATCH v2 07/13] tools/nolibc/select: avoid libgcc 64-bit multiplications Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 09/13] tools/nolibc: always use 64-bit time types Thomas Weißschuh
` (5 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
A custom 'struct timespec' and 'struct timeval' will be necessary for
64-bit time types on 32-bit architectures. <linux/time.h> will define
other time-related types in terms of the custom 'struct timespec'.
Add custom struct definitions which for now mirror exactly the ones from
the UAPI headers, but provide the foundation for further changes.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/include/nolibc/arch-s390.h | 3 +++
tools/include/nolibc/types.h | 16 +++++++++++++++-
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/tools/include/nolibc/arch-s390.h b/tools/include/nolibc/arch-s390.h
index 6237211385c0..1e87ac42ab9c 100644
--- a/tools/include/nolibc/arch-s390.h
+++ b/tools/include/nolibc/arch-s390.h
@@ -5,6 +5,9 @@
#ifndef _NOLIBC_ARCH_S390_H
#define _NOLIBC_ARCH_S390_H
+
+#include "types.h"
+
#include <linux/signal.h>
#include <linux/unistd.h>
diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h
index 470a5f77bc0f..5d180ffabcb6 100644
--- a/tools/include/nolibc/types.h
+++ b/tools/include/nolibc/types.h
@@ -13,9 +13,23 @@
#include "std.h"
#include <linux/mman.h>
#include <linux/stat.h>
-#include <linux/time.h>
+#include <linux/time_types.h>
#include <linux/wait.h>
+struct timespec {
+ __kernel_old_time_t tv_sec;
+ long tv_nsec;
+};
+#define _STRUCT_TIMESPEC
+
+struct timeval {
+ __kernel_old_time_t tv_sec;
+ __kernel_suseconds_t tv_usec;
+};
+
+#define timeval __nolibc_kernel_timeval
+#include <linux/time.h>
+#undef timeval
/* Only the generic macros and types may be defined here. The arch-specific
* ones such as the O_RDONLY and related macros used by fcntl() and open()
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 09/13] tools/nolibc: always use 64-bit time types
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
` (7 preceding siblings ...)
2025-11-22 16:59 ` [PATCH v2 08/13] tools/nolibc: use custom structs timespec and timeval Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-30 10:58 ` Willy Tarreau
2025-11-22 16:59 ` [PATCH v2 10/13] selftests/nolibc: test compatibility of nolibc and kernel " Thomas Weißschuh
` (4 subsequent siblings)
13 siblings, 1 reply; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
32-bit time types will stop working in 2038.
Switch to 64-bit time types everywhere.
Suggested-by: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/lkml/cec27d94-c99d-4c57-9a12-275ea663dda8@app.fastmail.com/
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/include/nolibc/std.h | 2 +-
tools/include/nolibc/types.h | 9 +++++----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/tools/include/nolibc/std.h b/tools/include/nolibc/std.h
index 392f4dd94158..b9a116123902 100644
--- a/tools/include/nolibc/std.h
+++ b/tools/include/nolibc/std.h
@@ -29,6 +29,6 @@ typedef unsigned long nlink_t;
typedef int64_t off_t;
typedef signed long blksize_t;
typedef signed long blkcnt_t;
-typedef __kernel_time_t time_t;
+typedef __kernel_time64_t time_t;
#endif /* _NOLIBC_STD_H */
diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h
index 5d180ffabcb6..8f3cb18df7f1 100644
--- a/tools/include/nolibc/types.h
+++ b/tools/include/nolibc/types.h
@@ -17,14 +17,15 @@
#include <linux/wait.h>
struct timespec {
- __kernel_old_time_t tv_sec;
- long tv_nsec;
+ time_t tv_sec;
+ int64_t tv_nsec;
};
#define _STRUCT_TIMESPEC
+/* Never use with system calls */
struct timeval {
- __kernel_old_time_t tv_sec;
- __kernel_suseconds_t tv_usec;
+ time_t tv_sec;
+ int64_t tv_usec;
};
#define timeval __nolibc_kernel_timeval
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 10/13] selftests/nolibc: test compatibility of nolibc and kernel time types
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
` (8 preceding siblings ...)
2025-11-22 16:59 ` [PATCH v2 09/13] tools/nolibc: always use 64-bit time types Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 11/13] tools/nolibc: remove time conversions Thomas Weißschuh
` (3 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
Keeping 'struct timespec' and 'struct __kernel_timespec' compatible
allows the source code to stay simple.
Validate that the types stay compatible.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/testing/selftests/nolibc/nolibc-test.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
index 3c5a226dad3a..3446d76a984e 100644
--- a/tools/testing/selftests/nolibc/nolibc-test.c
+++ b/tools/testing/selftests/nolibc/nolibc-test.c
@@ -1428,6 +1428,32 @@ int test_difftime(void)
return 0;
}
+int test_time_types(void)
+{
+ struct __kernel_timespec kts;
+ struct timespec ts;
+
+ if (!__builtin_types_compatible_p(time_t, __kernel_time64_t))
+ return 1;
+
+ if (sizeof(ts) != sizeof(kts))
+ return 1;
+
+ if (!__builtin_types_compatible_p(__typeof__(ts.tv_sec), __typeof__(kts.tv_sec)))
+ return 1;
+
+ if (!__builtin_types_compatible_p(__typeof__(ts.tv_nsec), __typeof__(kts.tv_nsec)))
+ return 1;
+
+ if (offsetof(__typeof__(ts), tv_sec) != offsetof(__typeof__(kts), tv_sec))
+ return 1;
+
+ if (offsetof(__typeof__(ts), tv_nsec) != offsetof(__typeof__(kts), tv_nsec))
+ return 1;
+
+ return 0;
+}
+
int run_stdlib(int min, int max)
{
int test;
@@ -1553,6 +1579,7 @@ int run_stdlib(int min, int max)
CASE_TEST(difftime); EXPECT_ZR(1, test_difftime()); break;
CASE_TEST(memchr_foobar6_o); EXPECT_STREQ(1, memchr("foobar", 'o', 6), "oobar"); break;
CASE_TEST(memchr_foobar3_b); EXPECT_STRZR(1, memchr("foobar", 'b', 3)); break;
+ CASE_TEST(time_types); EXPECT_ZR(1, test_time_types()); break;
case __LINE__:
return ret; /* must be last */
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 11/13] tools/nolibc: remove time conversions
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
` (9 preceding siblings ...)
2025-11-22 16:59 ` [PATCH v2 10/13] selftests/nolibc: test compatibility of nolibc and kernel " Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 12/13] tools/nolibc: add __nolibc_static_assert() Thomas Weißschuh
` (2 subsequent siblings)
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
Now that 'struct timespec' and 'struct __kernel_timespec' are
compatible, the conversions are not necessary anymore.
The same holds true for 'struct itimerspec' and 'struct
__kernel_itimerspec'.
Remove the conversions.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/include/nolibc/sys/timerfd.h | 20 ++----------
tools/include/nolibc/time.h | 64 ++++----------------------------------
2 files changed, 8 insertions(+), 76 deletions(-)
diff --git a/tools/include/nolibc/sys/timerfd.h b/tools/include/nolibc/sys/timerfd.h
index 66f779553d31..616fcfb416a9 100644
--- a/tools/include/nolibc/sys/timerfd.h
+++ b/tools/include/nolibc/sys/timerfd.h
@@ -33,13 +33,7 @@ static __attribute__((unused))
int sys_timerfd_gettime(int fd, struct itimerspec *curr_value)
{
#if defined(__NR_timerfd_gettime64)
- struct __kernel_itimerspec kcurr_value;
- int ret;
-
- ret = my_syscall2(__NR_timerfd_gettime64, fd, &kcurr_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;
+ return my_syscall2(__NR_timerfd_gettime64, fd, curr_value);
#else
return my_syscall2(__NR_timerfd_gettime, fd, curr_value);
#endif
@@ -57,17 +51,7 @@ int sys_timerfd_settime(int fd, int flags,
const struct itimerspec *new_value, struct itimerspec *old_value)
{
#if defined(__NR_timerfd_settime64)
- struct __kernel_itimerspec knew_value, kold_value;
- int ret;
-
- __nolibc_timespec_user_to_kernel(&new_value->it_value, &knew_value.it_value);
- __nolibc_timespec_user_to_kernel(&new_value->it_interval, &knew_value.it_interval);
- ret = my_syscall4(__NR_timerfd_settime64, fd, flags, &knew_value, &kold_value);
- if (old_value) {
- __nolibc_timespec_kernel_to_user(&kold_value.it_interval, &old_value->it_interval);
- __nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value);
- }
- return ret;
+ return my_syscall4(__NR_timerfd_settime64, fd, flags, new_value, old_value);
#else
return my_syscall4(__NR_timerfd_settime, fd, flags, new_value, old_value);
#endif
diff --git a/tools/include/nolibc/time.h b/tools/include/nolibc/time.h
index 45df9b09d7b6..ab67f209c99f 100644
--- a/tools/include/nolibc/time.h
+++ b/tools/include/nolibc/time.h
@@ -18,20 +18,6 @@
#include <linux/signal.h>
#include <linux/time.h>
-static __inline__
-void __nolibc_timespec_user_to_kernel(const struct timespec *ts, struct __kernel_timespec *kts)
-{
- kts->tv_sec = ts->tv_sec;
- kts->tv_nsec = ts->tv_nsec;
-}
-
-static __inline__
-void __nolibc_timespec_kernel_to_user(const struct __kernel_timespec *kts, struct timespec *ts)
-{
- ts->tv_sec = kts->tv_sec;
- ts->tv_nsec = kts->tv_nsec;
-}
-
/*
* int clock_getres(clockid_t clockid, struct timespec *res);
* int clock_gettime(clockid_t clockid, struct timespec *tp);
@@ -44,13 +30,7 @@ static __attribute__((unused))
int sys_clock_getres(clockid_t clockid, struct timespec *res)
{
#if defined(__NR_clock_getres_time64)
- struct __kernel_timespec kres;
- int ret;
-
- ret = my_syscall2(__NR_clock_getres_time64, clockid, &kres);
- if (res)
- __nolibc_timespec_kernel_to_user(&kres, res);
- return ret;
+ return my_syscall2(__NR_clock_getres_time64, clockid, res);
#else
return my_syscall2(__NR_clock_getres, clockid, res);
#endif
@@ -66,13 +46,7 @@ static __attribute__((unused))
int sys_clock_gettime(clockid_t clockid, struct timespec *tp)
{
#if defined(__NR_clock_gettime64)
- struct __kernel_timespec ktp;
- int ret;
-
- ret = my_syscall2(__NR_clock_gettime64, clockid, &ktp);
- if (tp)
- __nolibc_timespec_kernel_to_user(&ktp, tp);
- return ret;
+ return my_syscall2(__NR_clock_gettime64, clockid, tp);
#else
return my_syscall2(__NR_clock_gettime, clockid, tp);
#endif
@@ -88,10 +62,7 @@ static __attribute__((unused))
int sys_clock_settime(clockid_t clockid, struct timespec *tp)
{
#if defined(__NR_clock_settime64)
- struct __kernel_timespec ktp;
-
- __nolibc_timespec_user_to_kernel(tp, &ktp);
- return my_syscall2(__NR_clock_settime64, clockid, &ktp);
+ return my_syscall2(__NR_clock_settime64, clockid, tp);
#else
return my_syscall2(__NR_clock_settime, clockid, tp);
#endif
@@ -108,14 +79,7 @@ int sys_clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqt
struct timespec *rmtp)
{
#if defined(__NR_clock_nanosleep_time64)
- struct __kernel_timespec krqtp, krmtp;
- int ret;
-
- __nolibc_timespec_user_to_kernel(rqtp, &krqtp);
- ret = my_syscall4(__NR_clock_nanosleep_time64, clockid, flags, &krqtp, &krmtp);
- if (rmtp)
- __nolibc_timespec_kernel_to_user(&krmtp, rmtp);
- return ret;
+ return my_syscall4(__NR_clock_nanosleep_time64, clockid, flags, rqtp, rmtp);
#else
return my_syscall4(__NR_clock_nanosleep, clockid, flags, rqtp, rmtp);
#endif
@@ -190,13 +154,7 @@ static __attribute__((unused))
int sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value)
{
#if defined(__NR_timer_gettime64)
- struct __kernel_itimerspec kcurr_value;
- int ret;
-
- ret = my_syscall2(__NR_timer_gettime64, timerid, &kcurr_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;
+ return my_syscall2(__NR_timer_gettime64, timerid, curr_value);
#else
return my_syscall2(__NR_timer_gettime, timerid, curr_value);
#endif
@@ -213,17 +171,7 @@ int sys_timer_settime(timer_t timerid, int flags,
const struct itimerspec *new_value, struct itimerspec *old_value)
{
#if defined(__NR_timer_settime64)
- struct __kernel_itimerspec knew_value, kold_value;
- int ret;
-
- __nolibc_timespec_user_to_kernel(&new_value->it_value, &knew_value.it_value);
- __nolibc_timespec_user_to_kernel(&new_value->it_interval, &knew_value.it_interval);
- ret = my_syscall4(__NR_timer_settime64, timerid, flags, &knew_value, &kold_value);
- if (old_value) {
- __nolibc_timespec_kernel_to_user(&kold_value.it_interval, &old_value->it_interval);
- __nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value);
- }
- return ret;
+ return my_syscall4(__NR_timer_settime64, timerid, flags, new_value, old_value);
#else
return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value);
#endif
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 12/13] tools/nolibc: add __nolibc_static_assert()
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
` (10 preceding siblings ...)
2025-11-22 16:59 ` [PATCH v2 11/13] tools/nolibc: remove time conversions Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-30 11:08 ` Willy Tarreau
2025-11-22 16:59 ` [PATCH v2 13/13] selftests/nolibc: add static assertions around time types handling Thomas Weißschuh
2025-11-30 11:10 ` [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Willy Tarreau
13 siblings, 1 reply; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
Add a wrapper for _Static_assert() to use within nolibc.
While _Static_assert() itself was only standardized in C11,
in GCC and clang dialects it is also available in older standards.
If it turns out that _Static_assert can't be used in some contexts,
this wrapper can be adapted.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/include/nolibc/compiler.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/include/nolibc/compiler.h b/tools/include/nolibc/compiler.h
index 87090bbc53e0..ef247e916552 100644
--- a/tools/include/nolibc/compiler.h
+++ b/tools/include/nolibc/compiler.h
@@ -47,4 +47,6 @@
# define __nolibc_fallthrough do { } while (0)
#endif /* __nolibc_has_attribute(fallthrough) */
+#define __nolibc_static_assert(_t) _Static_assert(_t, "")
+
#endif /* _NOLIBC_COMPILER_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v2 13/13] selftests/nolibc: add static assertions around time types handling
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
` (11 preceding siblings ...)
2025-11-22 16:59 ` [PATCH v2 12/13] tools/nolibc: add __nolibc_static_assert() Thomas Weißschuh
@ 2025-11-22 16:59 ` Thomas Weißschuh
2025-11-30 11:10 ` [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Willy Tarreau
13 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-11-22 16:59 UTC (permalink / raw)
To: Willy Tarreau, Shuah Khan
Cc: Arnd Bergmann, linux-kernel, linux-kselftest,
Thomas Weißschuh
The nolibc system call wrappers expect the libc types to be compatible
to the kernel types.
Make sure these expectations hold at compile-time.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/include/nolibc/sys/timerfd.h | 4 ++++
tools/include/nolibc/time.h | 18 ++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/tools/include/nolibc/sys/timerfd.h b/tools/include/nolibc/sys/timerfd.h
index 616fcfb416a9..29fd92bd47d2 100644
--- a/tools/include/nolibc/sys/timerfd.h
+++ b/tools/include/nolibc/sys/timerfd.h
@@ -33,8 +33,10 @@ static __attribute__((unused))
int sys_timerfd_gettime(int fd, struct itimerspec *curr_value)
{
#if defined(__NR_timerfd_gettime64)
+ __nolibc_assert_time64_type(curr_value->it_value.tv_sec);
return my_syscall2(__NR_timerfd_gettime64, fd, curr_value);
#else
+ __nolibc_assert_native_time64();
return my_syscall2(__NR_timerfd_gettime, fd, curr_value);
#endif
}
@@ -51,8 +53,10 @@ int sys_timerfd_settime(int fd, int flags,
const struct itimerspec *new_value, struct itimerspec *old_value)
{
#if defined(__NR_timerfd_settime64)
+ __nolibc_assert_time64_type(new_value->it_value.tv_sec);
return my_syscall4(__NR_timerfd_settime64, fd, flags, new_value, old_value);
#else
+ __nolibc_assert_native_time64();
return my_syscall4(__NR_timerfd_settime, fd, flags, new_value, old_value);
#endif
}
diff --git a/tools/include/nolibc/time.h b/tools/include/nolibc/time.h
index ab67f209c99f..f9257d6a7878 100644
--- a/tools/include/nolibc/time.h
+++ b/tools/include/nolibc/time.h
@@ -18,6 +18,12 @@
#include <linux/signal.h>
#include <linux/time.h>
+#define __nolibc_assert_time64_type(t) \
+ __nolibc_static_assert(sizeof(t) == 8)
+
+#define __nolibc_assert_native_time64() \
+ __nolibc_assert_time64_type(__kernel_old_time_t)
+
/*
* int clock_getres(clockid_t clockid, struct timespec *res);
* int clock_gettime(clockid_t clockid, struct timespec *tp);
@@ -30,8 +36,10 @@ static __attribute__((unused))
int sys_clock_getres(clockid_t clockid, struct timespec *res)
{
#if defined(__NR_clock_getres_time64)
+ __nolibc_assert_time64_type(res->tv_sec);
return my_syscall2(__NR_clock_getres_time64, clockid, res);
#else
+ __nolibc_assert_native_time64();
return my_syscall2(__NR_clock_getres, clockid, res);
#endif
}
@@ -46,8 +54,10 @@ static __attribute__((unused))
int sys_clock_gettime(clockid_t clockid, struct timespec *tp)
{
#if defined(__NR_clock_gettime64)
+ __nolibc_assert_time64_type(tp->tv_sec);
return my_syscall2(__NR_clock_gettime64, clockid, tp);
#else
+ __nolibc_assert_native_time64();
return my_syscall2(__NR_clock_gettime, clockid, tp);
#endif
}
@@ -62,8 +72,10 @@ static __attribute__((unused))
int sys_clock_settime(clockid_t clockid, struct timespec *tp)
{
#if defined(__NR_clock_settime64)
+ __nolibc_assert_time64_type(tp->tv_sec);
return my_syscall2(__NR_clock_settime64, clockid, tp);
#else
+ __nolibc_assert_native_time64();
return my_syscall2(__NR_clock_settime, clockid, tp);
#endif
}
@@ -79,8 +91,10 @@ int sys_clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqt
struct timespec *rmtp)
{
#if defined(__NR_clock_nanosleep_time64)
+ __nolibc_assert_time64_type(rqtp->tv_sec);
return my_syscall4(__NR_clock_nanosleep_time64, clockid, flags, rqtp, rmtp);
#else
+ __nolibc_assert_native_time64();
return my_syscall4(__NR_clock_nanosleep, clockid, flags, rqtp, rmtp);
#endif
}
@@ -154,8 +168,10 @@ static __attribute__((unused))
int sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value)
{
#if defined(__NR_timer_gettime64)
+ __nolibc_assert_time64_type(curr_value->it_value.tv_sec);
return my_syscall2(__NR_timer_gettime64, timerid, curr_value);
#else
+ __nolibc_assert_native_time64();
return my_syscall2(__NR_timer_gettime, timerid, curr_value);
#endif
}
@@ -171,8 +187,10 @@ int sys_timer_settime(timer_t timerid, int flags,
const struct itimerspec *new_value, struct itimerspec *old_value)
{
#if defined(__NR_timer_settime64)
+ __nolibc_assert_time64_type(new_value->it_value.tv_sec);
return my_syscall4(__NR_timer_settime64, timerid, flags, new_value, old_value);
#else
+ __nolibc_assert_native_time64();
return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value);
#endif
}
--
2.52.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH v2 04/13] tools/nolibc/time: drop invocation of gettimeofday system call
2025-11-22 16:59 ` [PATCH v2 04/13] tools/nolibc/time: drop invocation of gettimeofday system call Thomas Weißschuh
@ 2025-11-30 10:42 ` Willy Tarreau
0 siblings, 0 replies; 24+ messages in thread
From: Willy Tarreau @ 2025-11-30 10:42 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Shuah Khan, Arnd Bergmann, linux-kernel, linux-kselftest
On Sat, Nov 22, 2025 at 05:59:10PM +0100, Thomas Weißschuh wrote:
> This invocation uses libc types with a system call. While this works
> now, upcoming changes to 'struct timeval' would require type
> conversions. If types are converted anyways, the clock_gettime() based
> fallback can be used everywhere, simplifying the code.
I must confess I'm not happy to see the simple, lightweight and efficient
gettimeofday() quit, with the alternative being a bit bigger, but after
enough testing, aside the code size increase I cannot spot any problem.
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Acked-by: Willy Tarreau <w@1wt.eu>
Willy
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 09/13] tools/nolibc: always use 64-bit time types
2025-11-22 16:59 ` [PATCH v2 09/13] tools/nolibc: always use 64-bit time types Thomas Weißschuh
@ 2025-11-30 10:58 ` Willy Tarreau
2025-12-01 7:45 ` Arnd Bergmann
0 siblings, 1 reply; 24+ messages in thread
From: Willy Tarreau @ 2025-11-30 10:58 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Shuah Khan, Arnd Bergmann, linux-kernel, linux-kselftest
Hi Thomas,
On Sat, Nov 22, 2025 at 05:59:15PM +0100, Thomas Weißschuh wrote:
> 32-bit time types will stop working in 2038.
>
> Switch to 64-bit time types everywhere.
>
> Suggested-by: Arnd Bergmann <arnd@arndb.de>
> Link: https://lore.kernel.org/lkml/cec27d94-c99d-4c57-9a12-275ea663dda8@app.fastmail.com/
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> tools/include/nolibc/std.h | 2 +-
> tools/include/nolibc/types.h | 9 +++++----
> 2 files changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/tools/include/nolibc/std.h b/tools/include/nolibc/std.h
> index 392f4dd94158..b9a116123902 100644
> --- a/tools/include/nolibc/std.h
> +++ b/tools/include/nolibc/std.h
> @@ -29,6 +29,6 @@ typedef unsigned long nlink_t;
> typedef int64_t off_t;
> typedef signed long blksize_t;
> typedef signed long blkcnt_t;
> -typedef __kernel_time_t time_t;
> +typedef __kernel_time64_t time_t;
>
> #endif /* _NOLIBC_STD_H */
> diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h
> index 5d180ffabcb6..8f3cb18df7f1 100644
> --- a/tools/include/nolibc/types.h
> +++ b/tools/include/nolibc/types.h
> @@ -17,14 +17,15 @@
> #include <linux/wait.h>
>
> struct timespec {
> - __kernel_old_time_t tv_sec;
> - long tv_nsec;
> + time_t tv_sec;
> + int64_t tv_nsec;
> };
> #define _STRUCT_TIMESPEC
>
> +/* Never use with system calls */
> struct timeval {
> - __kernel_old_time_t tv_sec;
> - __kernel_suseconds_t tv_usec;
> + time_t tv_sec;
> + int64_t tv_usec;
> };
It seems to me that glibc continues to make the effort of using a long
for tv_usec and tv_nsec. At least I'm seeing how that can make a
difference for application code given that these fields are constantly
multiplied or divided, forcing them to 64-bit when we know they'll never
be larger than 1 billion is extra burden for the application. Another
reason might be that the definition really changed from long to suseconds_t
in timeval a while ago, it's possible that it's used as a long in various
APIs (or even just printf formats).
IMHO it would be cleaner to keep it as a long here, or do you have a
particular reason for wanting int64_t (which BTW already forced a cast
in sys_gettimeofday()) ?
Thanks,
Willy
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 12/13] tools/nolibc: add __nolibc_static_assert()
2025-11-22 16:59 ` [PATCH v2 12/13] tools/nolibc: add __nolibc_static_assert() Thomas Weißschuh
@ 2025-11-30 11:08 ` Willy Tarreau
2025-12-03 19:19 ` Thomas Weißschuh
0 siblings, 1 reply; 24+ messages in thread
From: Willy Tarreau @ 2025-11-30 11:08 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Shuah Khan, Arnd Bergmann, linux-kernel, linux-kselftest
On Sat, Nov 22, 2025 at 05:59:18PM +0100, Thomas Weißschuh wrote:
> Add a wrapper for _Static_assert() to use within nolibc.
> While _Static_assert() itself was only standardized in C11,
> in GCC and clang dialects it is also available in older standards.
>
> If it turns out that _Static_assert can't be used in some contexts,
> this wrapper can be adapted.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> tools/include/nolibc/compiler.h | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/tools/include/nolibc/compiler.h b/tools/include/nolibc/compiler.h
> index 87090bbc53e0..ef247e916552 100644
> --- a/tools/include/nolibc/compiler.h
> +++ b/tools/include/nolibc/compiler.h
> @@ -47,4 +47,6 @@
> # define __nolibc_fallthrough do { } while (0)
> #endif /* __nolibc_has_attribute(fallthrough) */
>
> +#define __nolibc_static_assert(_t) _Static_assert(_t, "")
I'm not super fan of raising the bar to adoption by introducing forced
C11-isms, especially when they're only used to perform extra safety
checks that likely remain fine after you've checked them once. What
about instead:
+#if __STDC_VERSION__ >= 201112L
+# define __nolibc_static_assert(_t) _Static_assert(_t, "")
+#endif
+# define __nolibc_static_assert(_t) do { } while (0)
+#else
Note that this won't work out of code blocks but we very likely don't
care. And if we'd care, we could always switch to __asm__("") which
works everywhere.
What do you think ?
Thanks,
Willy
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
` (12 preceding siblings ...)
2025-11-22 16:59 ` [PATCH v2 13/13] selftests/nolibc: add static assertions around time types handling Thomas Weißschuh
@ 2025-11-30 11:10 ` Willy Tarreau
13 siblings, 0 replies; 24+ messages in thread
From: Willy Tarreau @ 2025-11-30 11:10 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Shuah Khan, Arnd Bergmann, linux-kernel, linux-kselftest
On Sat, Nov 22, 2025 at 05:59:06PM +0100, Thomas Weißschuh wrote:
> nolibc currently uses 32-bit types for various APIs. These are
> problematic as their reduced value range can lead to truncated values.
>
> Intended for 6.19.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
So overall I'm generally fine with the series, with some minor
reserves that can be dealt with later if needed.
Acked-by: Willy Tarreau <w@1wt.eu>
Thanks!
Willy
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 09/13] tools/nolibc: always use 64-bit time types
2025-11-30 10:58 ` Willy Tarreau
@ 2025-12-01 7:45 ` Arnd Bergmann
2025-12-01 10:35 ` Willy Tarreau
0 siblings, 1 reply; 24+ messages in thread
From: Arnd Bergmann @ 2025-12-01 7:45 UTC (permalink / raw)
To: Willy Tarreau, Thomas Weißschuh; +Cc: shuah, linux-kernel, linux-kselftest
On Sun, Nov 30, 2025, at 11:58, Willy Tarreau wrote:
> On Sat, Nov 22, 2025 at 05:59:15PM +0100, Thomas Weißschuh wrote:
>> struct timespec {
>> - __kernel_old_time_t tv_sec;
>> - long tv_nsec;
>> + time_t tv_sec;
>> + int64_t tv_nsec;
>> };
>> #define _STRUCT_TIMESPEC
>>
>> +/* Never use with system calls */
>> struct timeval {
>> - __kernel_old_time_t tv_sec;
>> - __kernel_suseconds_t tv_usec;
>> + time_t tv_sec;
>> + int64_t tv_usec;
>> };
>
> It seems to me that glibc continues to make the effort of using a long
> for tv_usec and tv_nsec. At least I'm seeing how that can make a
> difference for application code given that these fields are constantly
> multiplied or divided, forcing them to 64-bit when we know they'll never
> be larger than 1 billion is extra burden for the application. Another
> reason might be that the definition really changed from long to suseconds_t
> in timeval a while ago, it's possible that it's used as a long in various
> APIs (or even just printf formats).
>
> IMHO it would be cleaner to keep it as a long here, or do you have a
> particular reason for wanting int64_t (which BTW already forced a cast
> in sys_gettimeofday()) ?
As far as I can tell, it's the other way round for suseconds_t,
which in glibc is defined as
#if __TIMESIZE == 64 && __WORDSIZE == 32
# define __TIME_T_TYPE __SQUAD_TYPE
# define __SUSECONDS_T_TYPE __SQUAD_TYPE
#else
# define __TIME_T_TYPE __SLONGWORD_TYPE
# define __SUSECONDS_T_TYPE __SLONGWORD_TYPE
#endif
so this one is explicitly the same width as tv_sec, which has all
the issues you listed, but avoids the need for padding.
As far as I remember, the one reason for having a 'long tv_nsec'
with complex padding in glibc and musl is that this is actually
required by both Unix[1] and C11/C11 [2] standards.
C23 has updated the definition and does allow int64_t tv_nsec.
I think it makes sense for nolibc to just follow the kernel's
definition here.
Arnd
[1] https://pubs.opengroup.org/onlinepubs/009695399/basedefs/time.h.html
[2] https://en.cppreference.com/w/c/chrono/timespec.html
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 09/13] tools/nolibc: always use 64-bit time types
2025-12-01 7:45 ` Arnd Bergmann
@ 2025-12-01 10:35 ` Willy Tarreau
2025-12-01 10:53 ` Arnd Bergmann
0 siblings, 1 reply; 24+ messages in thread
From: Willy Tarreau @ 2025-12-01 10:35 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: Thomas Weißschuh, shuah, linux-kernel, linux-kselftest
Hi Arnd,
On Mon, Dec 01, 2025 at 08:45:00AM +0100, Arnd Bergmann wrote:
> On Sun, Nov 30, 2025, at 11:58, Willy Tarreau wrote:
> > On Sat, Nov 22, 2025 at 05:59:15PM +0100, Thomas Weißschuh wrote:
>
> >> struct timespec {
> >> - __kernel_old_time_t tv_sec;
> >> - long tv_nsec;
> >> + time_t tv_sec;
> >> + int64_t tv_nsec;
> >> };
> >> #define _STRUCT_TIMESPEC
> >>
> >> +/* Never use with system calls */
> >> struct timeval {
> >> - __kernel_old_time_t tv_sec;
> >> - __kernel_suseconds_t tv_usec;
> >> + time_t tv_sec;
> >> + int64_t tv_usec;
> >> };
> >
> > It seems to me that glibc continues to make the effort of using a long
> > for tv_usec and tv_nsec. At least I'm seeing how that can make a
> > difference for application code given that these fields are constantly
> > multiplied or divided, forcing them to 64-bit when we know they'll never
> > be larger than 1 billion is extra burden for the application. Another
> > reason might be that the definition really changed from long to suseconds_t
> > in timeval a while ago, it's possible that it's used as a long in various
> > APIs (or even just printf formats).
> >
> > IMHO it would be cleaner to keep it as a long here, or do you have a
> > particular reason for wanting int64_t (which BTW already forced a cast
> > in sys_gettimeofday()) ?
>
> As far as I can tell, it's the other way round for suseconds_t,
> which in glibc is defined as
>
> #if __TIMESIZE == 64 && __WORDSIZE == 32
> # define __TIME_T_TYPE __SQUAD_TYPE
> # define __SUSECONDS_T_TYPE __SQUAD_TYPE
> #else
> # define __TIME_T_TYPE __SLONGWORD_TYPE
> # define __SUSECONDS_T_TYPE __SLONGWORD_TYPE
> #endif
>
> so this one is explicitly the same width as tv_sec, which has all
> the issues you listed, but avoids the need for padding.
Ah we seem to just have checked different versions then,
as in mine there was still some extra padding left depending
on the endianness :-)
> As far as I remember, the one reason for having a 'long tv_nsec'
> with complex padding in glibc and musl is that this is actually
> required by both Unix[1] and C11/C11 [2] standards.
That's what I found as well and was my initial compatibility
concern (e.g. referencing &tv->tv_nsec as a long).
> C23 has updated the definition and does allow int64_t tv_nsec.
So it purposely breaks existing apps or does it apply only to those
compiled with -mstd=c23 ?
> I think it makes sense for nolibc to just follow the kernel's
> definition here.
Given the very narrow range of existing code that can be impacted,
I'm fine, but in general I try to remain extremely cautious about
portability: as a general rule, ifdefs needed to address possible
incompatibilities, if any, should rather be in the libc code itself
and not in the user application. I just ran a quick check and don't
have code using &tv_usec nor &tv_nsec so here the risk remains quite
low.
Thanks,
Willy
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 09/13] tools/nolibc: always use 64-bit time types
2025-12-01 10:35 ` Willy Tarreau
@ 2025-12-01 10:53 ` Arnd Bergmann
0 siblings, 0 replies; 24+ messages in thread
From: Arnd Bergmann @ 2025-12-01 10:53 UTC (permalink / raw)
To: Willy Tarreau; +Cc: Thomas Weißschuh, shuah, linux-kernel, linux-kselftest
On Mon, Dec 1, 2025, at 11:35, Willy Tarreau wrote:
> On Mon, Dec 01, 2025 at 08:45:00AM +0100, Arnd Bergmann wrote:
>> On Sun, Nov 30, 2025, at 11:58, Willy Tarreau wrote:
>>
>> #if __TIMESIZE == 64 && __WORDSIZE == 32
>> # define __TIME_T_TYPE __SQUAD_TYPE
>> # define __SUSECONDS_T_TYPE __SQUAD_TYPE
>> #else
>> # define __TIME_T_TYPE __SLONGWORD_TYPE
>> # define __SUSECONDS_T_TYPE __SLONGWORD_TYPE
>> #endif
>>
>> so this one is explicitly the same width as tv_sec, which has all
>> the issues you listed, but avoids the need for padding.
>
> Ah we seem to just have checked different versions then,
> as in mine there was still some extra padding left depending
> on the endianness :-)
The padding is definitely there in timespec around tv_nsec,
just not in timeval.
Oddly, the version I quoted is from my arm64 /usr/include/
installation and looks different from what I see in the glibc
history, though that also uses a 64-bit tv_usec:
bits/typesizes.h:#define __SUSECONDS64_T_TYPE __SQUAD_TYPE
posix/bits/types.h:__STD_TYPE __SUSECONDS64_T_TYPE __suseconds64_t;
struct timeval
{
#ifdef __USE_TIME64_REDIRECTS
__time64_t tv_sec; /* Seconds. */
__suseconds64_t tv_usec; /* Microseconds. */
#else
__time_t tv_sec; /* Seconds. */
__suseconds_t tv_usec; /* Microseconds. */
#endif
};
>> C23 has updated the definition and does allow int64_t tv_nsec.
>
> So it purposely breaks existing apps or does it apply only to those
> compiled with -mstd=c23 ?
Neither, it's just that nolibc with a 64-bit tv_nsec would
be compliant with c23, just not earlier versions.
I expect glibc to stick with 32-bit timespec and padding, which
is still compliant with the new definition of
| The type of tv_nsec is an implementation-defined signed integer type
| that can represent integers in [0, 999999999].
>> I think it makes sense for nolibc to just follow the kernel's
>> definition here.
>
> Given the very narrow range of existing code that can be impacted,
> I'm fine, but in general I try to remain extremely cautious about
> portability: as a general rule, ifdefs needed to address possible
> incompatibilities, if any, should rather be in the libc code itself
> and not in the user application. I just ran a quick check and don't
> have code using &tv_usec nor &tv_nsec so here the risk remains quite
> low.
Ok
ARnd
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 12/13] tools/nolibc: add __nolibc_static_assert()
2025-11-30 11:08 ` Willy Tarreau
@ 2025-12-03 19:19 ` Thomas Weißschuh
2025-12-03 19:23 ` Willy Tarreau
0 siblings, 1 reply; 24+ messages in thread
From: Thomas Weißschuh @ 2025-12-03 19:19 UTC (permalink / raw)
To: Willy Tarreau; +Cc: Shuah Khan, Arnd Bergmann, linux-kernel, linux-kselftest
On 2025-11-30 12:08:56+0100, Willy Tarreau wrote:
> On Sat, Nov 22, 2025 at 05:59:18PM +0100, Thomas Weißschuh wrote:
> > Add a wrapper for _Static_assert() to use within nolibc.
> > While _Static_assert() itself was only standardized in C11,
> > in GCC and clang dialects it is also available in older standards.
> >
> > If it turns out that _Static_assert can't be used in some contexts,
> > this wrapper can be adapted.
> >
> > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> > ---
> > tools/include/nolibc/compiler.h | 2 ++
> > 1 file changed, 2 insertions(+)
> >
> > diff --git a/tools/include/nolibc/compiler.h b/tools/include/nolibc/compiler.h
> > index 87090bbc53e0..ef247e916552 100644
> > --- a/tools/include/nolibc/compiler.h
> > +++ b/tools/include/nolibc/compiler.h
> > @@ -47,4 +47,6 @@
> > # define __nolibc_fallthrough do { } while (0)
> > #endif /* __nolibc_has_attribute(fallthrough) */
> >
> > +#define __nolibc_static_assert(_t) _Static_assert(_t, "")
>
> I'm not super fan of raising the bar to adoption by introducing forced
> C11-isms, especially when they're only used to perform extra safety
> checks that likely remain fine after you've checked them once. What
> about instead:
>
> +#if __STDC_VERSION__ >= 201112L
> +# define __nolibc_static_assert(_t) _Static_assert(_t, "")
> +#endif
> +# define __nolibc_static_assert(_t) do { } while (0)
> +#else
>
> Note that this won't work out of code blocks but we very likely don't
> care. And if we'd care, we could always switch to __asm__("") which
> works everywhere.
>
> What do you think ?
That works. But it won't be evaluated when not building with C11.
Which would not make it trigger when building nolibc-test.
So I don't want to guard it behind __STDC_VERSION__. But so far I was
not able to find a better, more dynamic guard. I'll look again.
Non-standard _Static_assert() is supported since GCC 4.6 and clang 3.0.
Thomas
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 12/13] tools/nolibc: add __nolibc_static_assert()
2025-12-03 19:19 ` Thomas Weißschuh
@ 2025-12-03 19:23 ` Willy Tarreau
2025-12-03 20:08 ` Thomas Weißschuh
0 siblings, 1 reply; 24+ messages in thread
From: Willy Tarreau @ 2025-12-03 19:23 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Shuah Khan, Arnd Bergmann, linux-kernel, linux-kselftest
On Wed, Dec 03, 2025 at 08:19:13PM +0100, Thomas Weißschuh wrote:
> On 2025-11-30 12:08:56+0100, Willy Tarreau wrote:
> > On Sat, Nov 22, 2025 at 05:59:18PM +0100, Thomas Weißschuh wrote:
> > > Add a wrapper for _Static_assert() to use within nolibc.
> > > While _Static_assert() itself was only standardized in C11,
> > > in GCC and clang dialects it is also available in older standards.
> > >
> > > If it turns out that _Static_assert can't be used in some contexts,
> > > this wrapper can be adapted.
> > >
> > > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> > > ---
> > > tools/include/nolibc/compiler.h | 2 ++
> > > 1 file changed, 2 insertions(+)
> > >
> > > diff --git a/tools/include/nolibc/compiler.h b/tools/include/nolibc/compiler.h
> > > index 87090bbc53e0..ef247e916552 100644
> > > --- a/tools/include/nolibc/compiler.h
> > > +++ b/tools/include/nolibc/compiler.h
> > > @@ -47,4 +47,6 @@
> > > # define __nolibc_fallthrough do { } while (0)
> > > #endif /* __nolibc_has_attribute(fallthrough) */
> > >
> > > +#define __nolibc_static_assert(_t) _Static_assert(_t, "")
> >
> > I'm not super fan of raising the bar to adoption by introducing forced
> > C11-isms, especially when they're only used to perform extra safety
> > checks that likely remain fine after you've checked them once. What
> > about instead:
> >
> > +#if __STDC_VERSION__ >= 201112L
> > +# define __nolibc_static_assert(_t) _Static_assert(_t, "")
> > +#endif
> > +# define __nolibc_static_assert(_t) do { } while (0)
> > +#else
> >
> > Note that this won't work out of code blocks but we very likely don't
> > care. And if we'd care, we could always switch to __asm__("") which
> > works everywhere.
> >
> > What do you think ?
>
> That works. But it won't be evaluated when not building with C11.
> Which would not make it trigger when building nolibc-test.
> So I don't want to guard it behind __STDC_VERSION__. But so far I was
> not able to find a better, more dynamic guard. I'll look again.
> Non-standard _Static_assert() is supported since GCC 4.6 and clang 3.0.
Fine, then we can just have a compiler version check as well, even a rough
one, since we don't reallly care about static asserts for pretty old or
uncommon versions, but for the modern ones that are used by developers
and test systems.
I'd suggest going the easy route for now by checking for GCC major >= 5
or clang major >= 3 and be done with it.
Willy
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v2 12/13] tools/nolibc: add __nolibc_static_assert()
2025-12-03 19:23 ` Willy Tarreau
@ 2025-12-03 20:08 ` Thomas Weißschuh
0 siblings, 0 replies; 24+ messages in thread
From: Thomas Weißschuh @ 2025-12-03 20:08 UTC (permalink / raw)
To: Willy Tarreau; +Cc: Shuah Khan, Arnd Bergmann, linux-kernel, linux-kselftest
On 2025-12-03 20:23:30+0100, Willy Tarreau wrote:
> On Wed, Dec 03, 2025 at 08:19:13PM +0100, Thomas Weißschuh wrote:
> > On 2025-11-30 12:08:56+0100, Willy Tarreau wrote:
> > > On Sat, Nov 22, 2025 at 05:59:18PM +0100, Thomas Weißschuh wrote:
> > > > Add a wrapper for _Static_assert() to use within nolibc.
> > > > While _Static_assert() itself was only standardized in C11,
> > > > in GCC and clang dialects it is also available in older standards.
> > > >
> > > > If it turns out that _Static_assert can't be used in some contexts,
> > > > this wrapper can be adapted.
> > > >
> > > > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> > > > ---
> > > > tools/include/nolibc/compiler.h | 2 ++
> > > > 1 file changed, 2 insertions(+)
> > > >
> > > > diff --git a/tools/include/nolibc/compiler.h b/tools/include/nolibc/compiler.h
> > > > index 87090bbc53e0..ef247e916552 100644
> > > > --- a/tools/include/nolibc/compiler.h
> > > > +++ b/tools/include/nolibc/compiler.h
> > > > @@ -47,4 +47,6 @@
> > > > # define __nolibc_fallthrough do { } while (0)
> > > > #endif /* __nolibc_has_attribute(fallthrough) */
> > > >
> > > > +#define __nolibc_static_assert(_t) _Static_assert(_t, "")
> > >
> > > I'm not super fan of raising the bar to adoption by introducing forced
> > > C11-isms, especially when they're only used to perform extra safety
> > > checks that likely remain fine after you've checked them once. What
> > > about instead:
> > >
> > > +#if __STDC_VERSION__ >= 201112L
> > > +# define __nolibc_static_assert(_t) _Static_assert(_t, "")
> > > +#endif
> > > +# define __nolibc_static_assert(_t) do { } while (0)
> > > +#else
> > >
> > > Note that this won't work out of code blocks but we very likely don't
> > > care. And if we'd care, we could always switch to __asm__("") which
> > > works everywhere.
> > >
> > > What do you think ?
> >
> > That works. But it won't be evaluated when not building with C11.
> > Which would not make it trigger when building nolibc-test.
> > So I don't want to guard it behind __STDC_VERSION__. But so far I was
> > not able to find a better, more dynamic guard. I'll look again.
> > Non-standard _Static_assert() is supported since GCC 4.6 and clang 3.0.
>
> Fine, then we can just have a compiler version check as well, even a rough
> one, since we don't reallly care about static asserts for pretty old or
> uncommon versions, but for the modern ones that are used by developers
> and test systems.
>
> I'd suggest going the easy route for now by checking for GCC major >= 5
> or clang major >= 3 and be done with it.
Ack. Let's do that.
Thomas
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2025-12-03 20:08 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-22 16:59 [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 01/13] tools/nolibc/poll: use kernel types for system call invocations Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 02/13] tools/nolibc/poll: drop __NR_poll fallback Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 03/13] tools/nolibc/select: drop non-pselect based implementations Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 04/13] tools/nolibc/time: drop invocation of gettimeofday system call Thomas Weißschuh
2025-11-30 10:42 ` Willy Tarreau
2025-11-22 16:59 ` [PATCH v2 05/13] tools/nolibc: prefer explicit 64-bit time-related system calls Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 06/13] tools/nolibc/gettimeofday: avoid libgcc 64-bit divisions Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 07/13] tools/nolibc/select: avoid libgcc 64-bit multiplications Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 08/13] tools/nolibc: use custom structs timespec and timeval Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 09/13] tools/nolibc: always use 64-bit time types Thomas Weißschuh
2025-11-30 10:58 ` Willy Tarreau
2025-12-01 7:45 ` Arnd Bergmann
2025-12-01 10:35 ` Willy Tarreau
2025-12-01 10:53 ` Arnd Bergmann
2025-11-22 16:59 ` [PATCH v2 10/13] selftests/nolibc: test compatibility of nolibc and kernel " Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 11/13] tools/nolibc: remove time conversions Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 12/13] tools/nolibc: add __nolibc_static_assert() Thomas Weißschuh
2025-11-30 11:08 ` Willy Tarreau
2025-12-03 19:19 ` Thomas Weißschuh
2025-12-03 19:23 ` Willy Tarreau
2025-12-03 20:08 ` Thomas Weißschuh
2025-11-22 16:59 ` [PATCH v2 13/13] selftests/nolibc: add static assertions around time types handling Thomas Weißschuh
2025-11-30 11:10 ` [PATCH v2 00/13] tools/nolibc: always use 64-bit time-related types Willy Tarreau
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox