From ad8aed4afb3ae567a91c30e257c9645617553d5a Mon Sep 17 00:00:00 2001 From: yurc Date: Wed, 14 Oct 2026 16:38:14 +0300 Subject: [PATCH 1/5] hal: hal_strerror(): texts for -EALREADY and -EBUSY hal_init_funct_to_thread() and hal_del_init_funct_from_thread() return -EALREADY once the init cycle has run, and funct_entry_release() returns -EBUSY when a function is removed from a running thread in RTAPI. Callers that report errors through hal_strerror() got "unknown error" for both. Signed-off-by: yurc --- src/hal/hal_lib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hal/hal_lib.c b/src/hal/hal_lib.c index 7961bdf32b2..227cf6ad629 100644 --- a/src/hal/hal_lib.c +++ b/src/hal/hal_lib.c @@ -777,6 +777,8 @@ const char *hal_strerror(int err) case -EPROTO: return "hal data version mismatch"; case -EPERM: return "hal is locked"; case -ENOEXEC: return "missing constructor"; + case -EALREADY: return "init cycle already executed"; + case -EBUSY: return "in use by a running thread"; default: return "unknown error"; } } From c515a1b0bb8c3ae3b2ca32e4104912cea3333ac2 Mon Sep 17 00:00:00 2001 From: yurc Date: Wed, 14 Oct 2026 16:38:14 +0300 Subject: [PATCH 2/5] halcmd: unloadrt init entry error text from hal_strerror() The message used strerror() because hal_strerror() had no text for -EALREADY ("Operation already in progress" for an init cycle that has already run). Signed-off-by: yurc --- src/hal/utils/halcmd_commands.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hal/utils/halcmd_commands.cc b/src/hal/utils/halcmd_commands.cc index 1712c9e7a12..35241919828 100644 --- a/src/hal/utils/halcmd_commands.cc +++ b/src/hal/utils/halcmd_commands.cc @@ -1210,7 +1210,7 @@ static int unloadrt_delf(const char *comp) rv = hal_del_init_funct_from_thread(e.first.c_str(), e.second.c_str()); if(0 != rv) { halcmd_error("init function '%s' not removed from thread '%s', error=%d (%s)\n", - e.first.c_str(), e.second.c_str(), rv, strerror(-rv)); + e.first.c_str(), e.second.c_str(), rv, hal_strerror(rv)); return rv; } halcmd_info("Init function '%s' removed from thread '%s'\n", From 772d526e63ae710f1c2253c956096ae821c7a38d Mon Sep 17 00:00:00 2001 From: yurc Date: Wed, 14 Oct 2026 16:38:14 +0300 Subject: [PATCH 3/5] rtapi: rtapi_delay() sleeps except in RTAI kernel modules rtapi.h and rtapi_delay(3) say it simply loops, wasting CPU cycles, and rtapi.h says user processes may not call it. Only RTAI kernel modules busy-wait (rt_busy_sleep()). uspace realtime modules sleep through the backend (clock_nanosleep() on POSIX and Xenomai, evl_sleep_until() on EVL, rt_sleep() on RTAI), and user processes have rtapi_delay() too and sleep with clock_nanosleep() (hal_lib uses it in ULAPI). Signed-off-by: yurc --- docs/src/man/man3/rtapi_delay.3.adoc | 9 +++++++-- include/rtapi.h | 13 +++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/docs/src/man/man3/rtapi_delay.3.adoc b/docs/src/man/man3/rtapi_delay.3.adoc index 760332bde96..da38ff0f416 100644 --- a/docs/src/man/man3/rtapi_delay.3.adoc +++ b/docs/src/man/man3/rtapi_delay.3.adoc @@ -4,7 +4,7 @@ == NAME -rtapi_delay, rtapi_delay_max - Busy-loop for short delays +rtapi_delay, rtapi_delay_max - Short delays == SYNTAX @@ -22,7 +22,12 @@ nsec:: == DESCRIPTION *rtapi_delay* is a simple delay. -It is intended only for short delays, since it simply loops, wasting CPU cycles. +It is intended only for short delays. +In RTAI kernel modules it busy-waits, wasting CPU cycles. +Everywhere else it sleeps: in uspace realtime modules through the realtime backend +(clock_nanosleep() on POSIX and Xenomai, evl_sleep_until() on EVL, rt_sleep() on RTAI), +in user processes with clock_nanosleep(). +The calling thread may be scheduled out and wake up later than requested. *rtapi_delay_max* returns the max delay permitted (usually approximately 1/4 of the clock period). Any call to *rtapi_delay* requesting a delay longer than the max will delay for the max time only. diff --git a/include/rtapi.h b/include/rtapi.h index dcb12486c8d..bf54340557d 100644 --- a/include/rtapi.h +++ b/include/rtapi.h @@ -244,8 +244,13 @@ RTAPI_BEGIN_DECLS #endif /* RTAPI */ /** - * @brief Simple delay, intended only for short delays, since it simply loops, - * wasting CPU cycles. + * @brief Simple delay, intended only for short delays. + * + * In RTAI kernel modules it busy-waits, wasting CPU cycles. Everywhere else + * it sleeps: in uspace realtime modules through the realtime backend + * (clock_nanosleep() on POSIX and Xenomai, evl_sleep_until() on EVL, + * rt_sleep() on RTAI), in user processes with clock_nanosleep(). The calling + * thread may be scheduled out and wake up later than requested. * * Any call to rtapi_delay() requesting a delay longer than the max will delay * for the max time only. rtapi_delay_max() should be called before using @@ -253,8 +258,6 @@ RTAPI_BEGIN_DECLS * resolution of the delay may be as good as one nano-second, or as bad as a * several microseconds. * @param nsec Desired delay in nano-seconds. - * @note This timing function is only available in realtime modules. User - * processes may not call them! */ extern void rtapi_delay(long int nsec); @@ -262,8 +265,6 @@ RTAPI_BEGIN_DECLS /** * @brief Returns the max delay permitted for rtapi_delay(). * @return Max delay permitted in nano-seconds. - * @note This timing function is only available in realtime modules. User - * processes may not call them! */ extern long int rtapi_delay_max(void); From 005609a05ec47d043c96b22978641fce99884e2b Mon Sep 17 00:00:00 2001 From: yurc Date: Wed, 14 Oct 2026 18:42:55 +0300 Subject: [PATCH 4/5] docs: rtapi_delay(3): discourage calls from realtime tasks Except in RTAI kernel modules rtapi_delay() sleeps, so a realtime task may wake up considerably later than requested and lose its timing. Keep init/cleanup code as the supported use. Signed-off-by: yurc --- docs/src/man/man3/rtapi_delay.3.adoc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/src/man/man3/rtapi_delay.3.adoc b/docs/src/man/man3/rtapi_delay.3.adoc index da38ff0f416..f72e23a7ee5 100644 --- a/docs/src/man/man3/rtapi_delay.3.adoc +++ b/docs/src/man/man3/rtapi_delay.3.adoc @@ -37,7 +37,11 @@ The actual resolution of the delay may be as good as one nano-second, or as bad == REALTIME CONSIDERATIONS -May be called from init/cleanup code, and from within realtime tasks. +May be called from init/cleanup code. + +Calling *rtapi_delay* from a realtime task, while possible, is very strongly discouraged. +Everywhere except in RTAI kernel modules it sleeps and may wake up considerably later than requested, +which throws off the realtime thread's timing. == RETURN VALUE From b26462f5fc4989aa70dedd7346cc4519f8178655 Mon Sep 17 00:00:00 2001 From: yurc Date: Thu, 15 Oct 2026 05:25:37 +0300 Subject: [PATCH 5/5] docs: rtapi_delay_max(): the value is implementation dependent 1/4 of the clock period holds only for RTAI kernel modules (rtai_rtapi.c). uspace realtime modules return a fixed 10000 ns (uspace_rtapi_main.cc), user processes 999999999 ns (uspace_ulapi.c, rtai_ulapi.c). Signed-off-by: yurc --- docs/src/man/man3/rtapi_delay.3.adoc | 4 +++- include/rtapi.h | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/src/man/man3/rtapi_delay.3.adoc b/docs/src/man/man3/rtapi_delay.3.adoc index f72e23a7ee5..ab0066fa08a 100644 --- a/docs/src/man/man3/rtapi_delay.3.adoc +++ b/docs/src/man/man3/rtapi_delay.3.adoc @@ -29,7 +29,9 @@ Everywhere else it sleeps: in uspace realtime modules through the realtime backe in user processes with clock_nanosleep(). The calling thread may be scheduled out and wake up later than requested. -*rtapi_delay_max* returns the max delay permitted (usually approximately 1/4 of the clock period). +*rtapi_delay_max* returns the max delay permitted. The value is implementation dependent: +1/4 of the clock period in RTAI kernel modules (10 µs until the clock is set), +10 µs in uspace realtime modules, just under one second in user processes. Any call to *rtapi_delay* requesting a delay longer than the max will delay for the max time only. *rtapi_delay_max* should be called before using *rtapi_delay* to make sure the required delays can be achieved. diff --git a/include/rtapi.h b/include/rtapi.h index bf54340557d..f73dd280660 100644 --- a/include/rtapi.h +++ b/include/rtapi.h @@ -264,6 +264,10 @@ RTAPI_BEGIN_DECLS /** * @brief Returns the max delay permitted for rtapi_delay(). + * + * The value is implementation dependent: 1/4 of the clock period in RTAI + * kernel modules (10 us until the clock is set), 10 us in uspace realtime + * modules, just under one second in user processes. * @return Max delay permitted in nano-seconds. */ extern long int rtapi_delay_max(void);