All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/5] Allow changing CPU affinity of RTDM tasks
@ 2026-01-28 11:28 Richard Weinberger
  2026-01-28 11:28 ` [PATCH 2/5] Make RTDM tasks behave, part I Richard Weinberger
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Richard Weinberger @ 2026-01-28 11:28 UTC (permalink / raw)
  To: xenomai; +Cc: upstream+xenomai, Richard Weinberger

Currently, calling sched_affinity() on an RTDM task has no effect
on the Xenomai side, even though the shadow task reflects the desired
affinity. This discrepancy causes confusion because the failure is not
immediately visible.
A cryptic WARN_ON() triggers only when CONFIG_XENO_OPT_DEBUG_COBALT is
enabled.

This change addresses the issue by implementing an approach similar to
that used for userspace tasks: forcing a relaxation and hardening cycle
to apply the new affinity upon receiving SIGSHADOW.

A new helper, rtdm_task_test_sigshadow(), checks whether SIGSHADOW is
pending for the shadow task. If so, the signal is consumed, and a
relax/harden cycle is performed. This works because signal_pending()
only checks a flag and does not cause a domain switch. The new helper
is integrated into rtdm_task_should_stop(), so existing RTDM tasks utilize
it automatically.

Sending SIGSHADOW to a kernel task causes blocking functions to return
-EINTR. Currently, almost all RT kernel tasks treat
non-zero returns from functions like rtdm_event_wait() as fatal errors
and terminate. With this change, blocking functions that return -EINTR
require restarting (continuing the thread loop).

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 include/cobalt/kernel/rtdm/driver.h | 21 +++++++++++++++++++++
 kernel/cobalt/rtdm/drvlib.c         |  4 ++++
 kernel/cobalt/thread.c              | 10 ++++++++--
 3 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h
index 604d54b2b..3fc5573cb 100644
--- a/include/cobalt/kernel/rtdm/driver.h
+++ b/include/cobalt/kernel/rtdm/driver.h
@@ -34,6 +34,7 @@
 #include <linux/cdev.h>
 #include <linux/wait.h>
 #include <linux/notifier.h>
+#include <linux/sched/signal.h>
 #include <pipeline/lock.h>
 #include <xenomai/version.h>
 #include <cobalt/kernel/heap.h>
@@ -1043,8 +1044,28 @@ static inline void rtdm_task_destroy(rtdm_task_t *task)
 	xnthread_join(task, true);
 }
 
+static inline int __rtdm_task_should_stop(void)
+{
+	return xnthread_test_info(xnthread_current(), XNCANCELD);
+}
+
+static inline void rtdm_task_test_sigshadow(void)
+{
+	int sig;
+
+	if (signal_pending(current)) {
+		if (!xnthread_test_state(xnthread_current(), XNRELAX))
+			xnthread_relax(0, 0);
+		sig = kernel_dequeue_signal();
+		XENO_WARN_ON(COBALT, sig != SIGSHADOW);
+		xnthread_harden();
+	}
+}
+
 static inline int rtdm_task_should_stop(void)
 {
+	rtdm_task_test_sigshadow();
+
 	return xnthread_test_info(xnthread_current(), XNCANCELD);
 }
 
diff --git a/kernel/cobalt/rtdm/drvlib.c b/kernel/cobalt/rtdm/drvlib.c
index 86788743f..08e113904 100644
--- a/kernel/cobalt/rtdm/drvlib.c
+++ b/kernel/cobalt/rtdm/drvlib.c
@@ -90,6 +90,10 @@ nanosecs_abs_t rtdm_clock_read_monotonic(void);
  * After initialising a task, the task handle remains valid and can be
  * passed to RTDM services until either rtdm_task_destroy() or
  * rtdm_task_join() was invoked.
+ * RTDM tasks are required to use rtdm_task_should_stop() in their thread loop
+ * and must handle interrupted RTDM services, such as rtdm_event_wait().
+ * The -EINTR return code is not a fatal error. It should simply trigger a
+ * continuation of the thread loop.
  *
  * @param[in,out] task Task handle
  * @param[in] name Optional task name
diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
index 607f115a7..3f0ed98ef 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -204,6 +204,8 @@ static int kthread_trampoline(void *arg)
 		return ret;
 	}
 
+	allow_signal(SIGSHADOW);
+
 	trace_cobalt_shadow_entry(thread);
 
 	thread->entry(thread->cookie);
@@ -2373,8 +2375,12 @@ void __xnthread_signal(struct xnthread *thread, int sig, int arg)
 	struct lostage_signal *sigwork;
 	int slot;
 
-	if (XENO_WARN_ON(COBALT, !xnthread_test_state(thread, XNUSER)))
-		return;
+	if (!xnthread_test_state(thread, XNUSER)) {
+		if (sig != SIGSHADOW) {
+			XENO_WARN(COBALT, 1, "unexpected signal: %i", sig);
+			return;
+		}
+	}
 
 	slot = get_slot_index_from_sig(sig, arg);
 	if (WARN_ON_ONCE(slot < 0))
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/5] Make RTDM tasks behave, part I
  2026-01-28 11:28 [PATCH 1/5] Allow changing CPU affinity of RTDM tasks Richard Weinberger
@ 2026-01-28 11:28 ` Richard Weinberger
  2026-01-28 13:23   ` Philippe Gerum
  2026-01-28 11:28 ` [PATCH 3/5] Make RTDM tasks behave, part II Richard Weinberger
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Richard Weinberger @ 2026-01-28 11:28 UTC (permalink / raw)
  To: xenomai; +Cc: upstream+xenomai, Richard Weinberger

RTDM tasks must now utilize rtdm_task_should_stop() to ensure proper
cleanup and SIGSHADOW detection.
Also, handle -EINTR gracefully, rather than exiting immediately on
interruption, the task should loop and re-check rtdm_task_should_stop()
to decide if termination is actually required.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 kernel/drivers/autotune/autotune.c              | 17 ++++++++++-------
 kernel/drivers/net/addons/proxy.c               |  6 +++++-
 kernel/drivers/net/stack/ipv4/tcp/timerwheel.c  |  6 ++++--
 kernel/drivers/net/stack/rtcfg/rtcfg_frame.c    |  6 +++++-
 .../drivers/net/stack/rtmac/nomac/nomac_proto.c |  6 +++++-
 .../drivers/net/stack/rtmac/tdma/tdma_worker.c  |  4 +++-
 kernel/drivers/net/stack/rtnet_rtpc.c           |  5 ++++-
 kernel/drivers/net/stack/stack_mgr.c            |  6 +++++-
 kernel/drivers/testing/rtdmtest.c               |  9 ++++-----
 kernel/drivers/testing/timerbench.c             |  2 +-
 10 files changed, 46 insertions(+), 21 deletions(-)

diff --git a/kernel/drivers/autotune/autotune.c b/kernel/drivers/autotune/autotune.c
index 03fd688de..c11d18057 100644
--- a/kernel/drivers/autotune/autotune.c
+++ b/kernel/drivers/autotune/autotune.c
@@ -248,22 +248,25 @@ static void task_handler(void *arg)
 	xnticks_t now;
 	int ret = 0;
 
-	for (;;) {
-		if (rtdm_task_should_stop())
-			break;
-
+	while (!rtdm_task_should_stop()) {
 		ret = rtdm_event_wait(&k_tuner->barrier);
-		if (ret)
+		if (ret == -EINTR)
+			continue;
+		else if (ret)
 			break;
 
 		ret = rtdm_task_set_period(&k_tuner->task, k_tuner->start_time,
 					   k_tuner->interval);
-		if (ret)
+		if (ret == -EINTR)
+			continue;
+		else if (ret)
 			break;
 
 		for (;;) {
 			ret = rtdm_task_wait_period(NULL);
-			if (ret && ret != -ETIMEDOUT)
+			if (ret == -EINTR)
+				break;
+			else if (ret && ret != -ETIMEDOUT)
 				goto out;
 
 			now = xnclock_read_raw(&nkclock);
diff --git a/kernel/drivers/net/addons/proxy.c b/kernel/drivers/net/addons/proxy.c
index d63bb13bc..e9956cd33 100644
--- a/kernel/drivers/net/addons/proxy.c
+++ b/kernel/drivers/net/addons/proxy.c
@@ -103,9 +103,13 @@ static void rtnetproxy_tx_loop(void *arg)
 {
 	struct rtnet_device *rtdev;
 	struct rtskb *rtskb;
+	int ret;
 
 	while (!rtdm_task_should_stop()) {
-		if (rtdm_event_wait(&rtnetproxy_tx_event) < 0)
+		ret = rtdm_event_wait(&rtnetproxy_tx_event);
+		if (ret == -EINTR)
+			continue;
+		else if (ret < 0)
 			break;
 
 		while ((rtskb = rtskb_dequeue(&tx_queue)) != NULL) {
diff --git a/kernel/drivers/net/stack/ipv4/tcp/timerwheel.c b/kernel/drivers/net/stack/ipv4/tcp/timerwheel.c
index 6c8bf7e66..209e45924 100644
--- a/kernel/drivers/net/stack/ipv4/tcp/timerwheel.c
+++ b/kernel/drivers/net/stack/ipv4/tcp/timerwheel.c
@@ -124,9 +124,11 @@ static void timerwheel_pivot(void *arg)
 	struct timerwheel_timer *timer;
 	int ret;
 
-	while (1) {
+	while (!rtdm_task_should_stop()) {
 		ret = timerwheel_sleep();
-		if (ret < 0) {
+		if (ret == -EINTR)
+			continue;
+		else if (ret < 0) {
 			pr_err("timerwheel_pivot interrupted %d\n", -ret);
 			break;
 		}
diff --git a/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c b/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
index ca6c130b5..c7babb6d1 100644
--- a/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
+++ b/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
@@ -61,9 +61,13 @@ static void rtcfg_rx_task(void *arg)
 	struct rtskb *rtskb;
 	struct rtcfg_frm_head *frm_head;
 	struct rtnet_device *rtdev;
+	int ret;
 
 	while (!rtdm_task_should_stop()) {
-		if (rtdm_event_wait(&rx_event) < 0)
+		ret = rtdm_event_wait(&rx_event);
+		if (ret == -EINTR)
+			continue;
+		else if (ret < 0)
 			break;
 
 		while ((rtskb = rtskb_dequeue(&rx_queue))) {
diff --git a/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c b/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
index e9842ac5e..84317697b 100644
--- a/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
+++ b/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
@@ -80,9 +80,13 @@ static void nrt_xmit_task(void *arg)
 {
 	struct rtskb *rtskb;
 	struct rtnet_device *rtdev;
+	int ret;
 
 	while (!rtdm_task_should_stop()) {
-		if (rtdm_event_wait(&wakeup_sem) < 0)
+		ret = rtdm_event_wait(&wakeup_sem);
+		if (ret == -EINTR)
+			continue;
+		else if (ret < 0)
 			break;
 
 		while ((rtskb = rtskb_dequeue(&nrt_rtskb_queue))) {
diff --git a/kernel/drivers/net/stack/rtmac/tdma/tdma_worker.c b/kernel/drivers/net/stack/rtmac/tdma/tdma_worker.c
index e3c60cd9a..c1235e3cc 100644
--- a/kernel/drivers/net/stack/rtmac/tdma/tdma_worker.c
+++ b/kernel/drivers/net/stack/rtmac/tdma/tdma_worker.c
@@ -193,7 +193,9 @@ void tdma_worker(void *arg)
 		case WAIT_ON_SYNC:
 			rtdm_lock_put_irqrestore(&tdma->lock, lockctx);
 			ret = rtdm_event_wait(&tdma->sync_event);
-			if (ret)
+			if (ret == -EINTR)
+				continue;
+			else if (ret)
 				return;
 			rtdm_lock_get_irqsave(&tdma->lock, lockctx);
 			break;
diff --git a/kernel/drivers/net/stack/rtnet_rtpc.c b/kernel/drivers/net/stack/rtnet_rtpc.c
index cd5f0546d..fe60209f2 100644
--- a/kernel/drivers/net/stack/rtnet_rtpc.c
+++ b/kernel/drivers/net/stack/rtnet_rtpc.c
@@ -178,7 +178,10 @@ static void rtpc_dispatch_handler(void *arg)
 	int ret;
 
 	while (!rtdm_task_should_stop()) {
-		if (rtdm_event_wait(&dispatch_event) < 0)
+		ret = rtdm_event_wait(&dispatch_event);
+		if (ret == -EINTR)
+			continue;
+		else if (ret < 0)
 			break;
 
 		while ((call = rtpc_dequeue_pending_call())) {
diff --git a/kernel/drivers/net/stack/stack_mgr.c b/kernel/drivers/net/stack/stack_mgr.c
index b30a74549..f4f8c7fff 100644
--- a/kernel/drivers/net/stack/stack_mgr.c
+++ b/kernel/drivers/net/stack/stack_mgr.c
@@ -196,9 +196,13 @@ static void rt_stack_mgr_task(void *arg)
 {
 	rtdm_event_t *mgr_event = &((struct rtnet_mgr *)arg)->event;
 	struct rtskb *rtskb;
+	int ret = 0;
 
 	while (!rtdm_task_should_stop()) {
-		if (rtdm_event_wait(mgr_event) < 0)
+		ret = rtdm_event_wait(mgr_event);
+		if (ret == -EINTR)
+			continue;
+		else if (ret < 0)
 			break;
 
 		/* we are the only reader => no locking required */
diff --git a/kernel/drivers/testing/rtdmtest.c b/kernel/drivers/testing/rtdmtest.c
index 87aef8ee6..ca29ec54b 100644
--- a/kernel/drivers/testing/rtdmtest.c
+++ b/kernel/drivers/testing/rtdmtest.c
@@ -138,12 +138,11 @@ static void actor_handler(void *arg)
 	struct rtdm_actor_context *ctx = arg;
 	int ret;
 
-	for (;;) {
-		if (rtdm_task_should_stop())
-			return;
-
+	while (!rtdm_task_should_stop()) {
 		ret = rtdm_event_wait(&ctx->run);
-		if (ret)
+		if (ret == -EINTR)
+			continue;
+		else if (ret)
 			break;
 
 		switch (ctx->request) {
diff --git a/kernel/drivers/testing/timerbench.c b/kernel/drivers/testing/timerbench.c
index 68e50a241..75da6bfdb 100644
--- a/kernel/drivers/testing/timerbench.c
+++ b/kernel/drivers/testing/timerbench.c
@@ -146,7 +146,7 @@ static void timer_task_proc(void *arg)
 	/* first event: one millisecond from now. */
 	ctx->date = rtdm_clock_read_monotonic() + 1000000;
 
-	while (1) {
+	while (!rtdm_task_should_stop()) {
 		for (count = 0; count < ctx->samples_per_sec; count++) {
 			cobalt_atomic_enter(s);
 			ctx->start_time = rtdm_clock_read_monotonic();
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/5] Make RTDM tasks behave, part II
  2026-01-28 11:28 [PATCH 1/5] Allow changing CPU affinity of RTDM tasks Richard Weinberger
  2026-01-28 11:28 ` [PATCH 2/5] Make RTDM tasks behave, part I Richard Weinberger
@ 2026-01-28 11:28 ` Richard Weinberger
  2026-01-29  9:45   ` Jan Kiszka
  2026-01-28 11:28 ` [PATCH 4/5] Warn on unexpected RTDM task termination Richard Weinberger
  2026-01-28 11:28 ` [PATCH 5/5] Allow specifying CPU affinity in rtdm_task_init() Richard Weinberger
  3 siblings, 1 reply; 13+ messages in thread
From: Richard Weinberger @ 2026-01-28 11:28 UTC (permalink / raw)
  To: xenomai; +Cc: upstream+xenomai, Richard Weinberger

Make sure that RTDM tasks terminate gracefully via rtdm_task_should_stop().
To achieve this, enforce the correct teardown order: always terminate and
join the thread first, and only then destroy the resources it was using.

While this change does not fix a bug, it allows us to distinguish between
expected and unexpected task termination.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 kernel/drivers/net/addons/proxy.c                  | 2 +-
 kernel/drivers/net/stack/rtcfg/rtcfg_frame.c       | 4 ++--
 kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c | 2 +-
 kernel/drivers/net/stack/rtmac/tdma/tdma_module.c  | 4 ++--
 kernel/drivers/net/stack/rtnet_rtpc.c              | 2 +-
 kernel/drivers/net/stack/stack_mgr.c               | 3 ++-
 6 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/kernel/drivers/net/addons/proxy.c b/kernel/drivers/net/addons/proxy.c
index e9956cd33..c3e5ce1c9 100644
--- a/kernel/drivers/net/addons/proxy.c
+++ b/kernel/drivers/net/addons/proxy.c
@@ -418,8 +418,8 @@ static void __exit rtnetproxy_cleanup_module(void)
 	unregister_netdev(dev_rtnetproxy);
 	free_netdev(dev_rtnetproxy);
 
-	rtdm_event_destroy(&rtnetproxy_tx_event);
 	rtdm_task_destroy(&rtnetproxy_tx_task);
+	rtdm_event_destroy(&rtnetproxy_tx_event);
 
 	/* free the non-real-time signal */
 	rtdm_nrtsig_destroy(&rtnetproxy_rx_signal);
diff --git a/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c b/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
index c7babb6d1..70318ad3c 100644
--- a/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
+++ b/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
@@ -558,8 +558,8 @@ int __init rtcfg_init_frames(void)
 	return 0;
 
 error2:
-	rtdm_event_destroy(&rx_event);
 	rtdm_task_destroy(&rx_task);
+	rtdm_event_destroy(&rx_event);
 
 error1:
 	rtskb_pool_release(&rtcfg_pool);
@@ -573,8 +573,8 @@ void rtcfg_cleanup_frames(void)
 
 	rtdev_remove_pack(&rtcfg_packet_type);
 
-	rtdm_event_destroy(&rx_event);
 	rtdm_task_destroy(&rx_task);
+	rtdm_event_destroy(&rx_event);
 
 	while ((rtskb = rtskb_dequeue(&rx_queue)) != NULL) {
 		kfree_rtskb(rtskb);
diff --git a/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c b/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
index 84317697b..6cdedae2f 100644
--- a/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
+++ b/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
@@ -127,6 +127,6 @@ int __init nomac_proto_init(void)
 
 void nomac_proto_cleanup(void)
 {
-	rtdm_event_destroy(&wakeup_sem);
 	rtdm_task_destroy(&wrapper_task);
+	rtdm_event_destroy(&wakeup_sem);
 }
diff --git a/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c b/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c
index 47c66d91f..3c516d23b 100644
--- a/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c
+++ b/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c
@@ -228,14 +228,14 @@ static int tdma_detach(struct rtnet_device *rtdev, void *priv)
 	struct tdma_priv *tdma = (struct tdma_priv *)priv;
 	struct tdma_job *job, *tmp;
 
+	rtdm_task_destroy(&tdma->worker_task);
+
 	rtdm_event_destroy(&tdma->sync_event);
 	rtdm_event_destroy(&tdma->xmit_event);
 	rtdm_event_destroy(&tdma->worker_wakeup);
 
 	tdma_dev_release(tdma);
 
-	rtdm_task_destroy(&tdma->worker_task);
-
 	list_for_each_entry_safe (job, tmp, &tdma->first_job->entry, entry) {
 		if (job->id >= 0)
 			tdma_cleanup_slot(tdma, SLOT_JOB(job));
diff --git a/kernel/drivers/net/stack/rtnet_rtpc.c b/kernel/drivers/net/stack/rtnet_rtpc.c
index fe60209f2..16dd84979 100644
--- a/kernel/drivers/net/stack/rtnet_rtpc.c
+++ b/kernel/drivers/net/stack/rtnet_rtpc.c
@@ -251,8 +251,8 @@ int __init rtpc_init(void)
 
 void rtpc_cleanup(void)
 {
-	rtdm_event_destroy(&dispatch_event);
 	rtdm_task_destroy(&dispatch_task);
+	rtdm_event_destroy(&dispatch_event);
 	rtdm_nrtsig_destroy(&rtpc_nrt_signal);
 }
 
diff --git a/kernel/drivers/net/stack/stack_mgr.c b/kernel/drivers/net/stack/stack_mgr.c
index f4f8c7fff..82e8412dc 100644
--- a/kernel/drivers/net/stack/stack_mgr.c
+++ b/kernel/drivers/net/stack/stack_mgr.c
@@ -257,6 +257,7 @@ int rt_stack_mgr_init(struct rtnet_mgr *mgr)
  */
 void rt_stack_mgr_delete(struct rtnet_mgr *mgr)
 {
-	rtdm_event_destroy(&mgr->event);
+
 	rtdm_task_destroy(&mgr->task);
+	rtdm_event_destroy(&mgr->event);
 }
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 4/5] Warn on unexpected RTDM task termination
  2026-01-28 11:28 [PATCH 1/5] Allow changing CPU affinity of RTDM tasks Richard Weinberger
  2026-01-28 11:28 ` [PATCH 2/5] Make RTDM tasks behave, part I Richard Weinberger
  2026-01-28 11:28 ` [PATCH 3/5] Make RTDM tasks behave, part II Richard Weinberger
@ 2026-01-28 11:28 ` Richard Weinberger
  2026-01-29  9:50   ` Jan Kiszka
  2026-01-28 11:28 ` [PATCH 5/5] Allow specifying CPU affinity in rtdm_task_init() Richard Weinberger
  3 siblings, 1 reply; 13+ messages in thread
From: Richard Weinberger @ 2026-01-28 11:28 UTC (permalink / raw)
  To: xenomai; +Cc: upstream+xenomai, Richard Weinberger

Now that all in-tree RTDM tasks have been updated to handle termination
correctly, introduce a check to detect unexpected task terminations.

This warning will assist authors of out-of-tree modules in identifying
tasks that do not yet properly handle interrupted function calls.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 kernel/cobalt/thread.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
index 3f0ed98ef..fb7190cf3 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -210,6 +210,12 @@ static int kthread_trampoline(void *arg)
 
 	thread->entry(thread->cookie);
 
+	/*
+	 * Warn the user if a thread chickens out.
+	 */
+	if (!xnthread_test_info(thread, XNCANCELD))
+		printk(XENO_WARNING "unexpected thread termination: %s\n", thread->name);
+
 	xnthread_cancel(thread);
 
 	return 0;
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 5/5] Allow specifying CPU affinity in rtdm_task_init()
  2026-01-28 11:28 [PATCH 1/5] Allow changing CPU affinity of RTDM tasks Richard Weinberger
                   ` (2 preceding siblings ...)
  2026-01-28 11:28 ` [PATCH 4/5] Warn on unexpected RTDM task termination Richard Weinberger
@ 2026-01-28 11:28 ` Richard Weinberger
  2026-01-29  9:53   ` Jan Kiszka
  3 siblings, 1 reply; 13+ messages in thread
From: Richard Weinberger @ 2026-01-28 11:28 UTC (permalink / raw)
  To: xenomai; +Cc: upstream+xenomai, Richard Weinberger

Previously, rtdm_task_init() did not provide a way to pin a task to a
specific CPU during initialization.

Update the function signature to accept a CPU identifier.
Passing -1 results in the default behavior, allowing the
scheduler to automatically select the CPU.

Signed-off-by: Richard Weinberger <richard@nod.at>
---
 include/cobalt/kernel/rtdm/driver.h                |  4 ++--
 kernel/cobalt/rtdm/drvlib.c                        | 14 +++++++++++---
 kernel/drivers/analogy/testing/fake.c              |  2 +-
 kernel/drivers/autotune/autotune.c                 |  2 +-
 kernel/drivers/net/addons/proxy.c                  |  2 +-
 kernel/drivers/net/stack/ipv4/tcp/timerwheel.c     |  2 +-
 kernel/drivers/net/stack/rtcfg/rtcfg_frame.c       |  2 +-
 kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c |  2 +-
 kernel/drivers/net/stack/rtmac/tdma/tdma_module.c  |  2 +-
 kernel/drivers/net/stack/rtnet_rtpc.c              |  2 +-
 kernel/drivers/net/stack/stack_mgr.c               |  2 +-
 kernel/drivers/testing/rtdmtest.c                  |  2 +-
 kernel/drivers/testing/timerbench.c                |  2 +-
 13 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h
index 3fc5573cb..dcfbccbdf 100644
--- a/include/cobalt/kernel/rtdm/driver.h
+++ b/include/cobalt/kernel/rtdm/driver.h
@@ -1032,8 +1032,8 @@ typedef void (*rtdm_task_proc_t)(void *arg);
 /** @} rtdm_task */
 
 int rtdm_task_init(rtdm_task_t *task, const char *name,
-		   rtdm_task_proc_t task_proc, void *arg,
-		   int priority, nanosecs_rel_t period);
+		   rtdm_task_proc_t task_proc, void *arg, int priority,
+		   nanosecs_rel_t period, int cpu);
 int __rtdm_task_sleep(xnticks_t timeout, xntmode_t mode);
 void rtdm_task_busy_sleep(nanosecs_rel_t delay);
 
diff --git a/kernel/cobalt/rtdm/drvlib.c b/kernel/cobalt/rtdm/drvlib.c
index 08e113904..f68b1089c 100644
--- a/kernel/cobalt/rtdm/drvlib.c
+++ b/kernel/cobalt/rtdm/drvlib.c
@@ -101,6 +101,7 @@ nanosecs_abs_t rtdm_clock_read_monotonic(void);
  * @param[in] arg Custom argument passed to @c task_proc() on entry
  * @param[in] priority Priority of the task, see also
  * @ref rtdmtaskprio "Task Priority Range"
+ * @param[in] cpu preferred CPU to run on, pass -1 for auto selection
  * @param[in] period Period in nanoseconds of a cyclic task, 0 for non-cyclic
  * mode. Waiting for the first and subsequent periodic events is
  * done using rtdm_task_wait_period().
@@ -110,8 +111,8 @@ nanosecs_abs_t rtdm_clock_read_monotonic(void);
  * @coretags{secondary-only, might-switch}
  */
 int rtdm_task_init(rtdm_task_t *task, const char *name,
-		   rtdm_task_proc_t task_proc, void *arg,
-		   int priority, nanosecs_rel_t period)
+		   rtdm_task_proc_t task_proc, void *arg, int priority,
+		   nanosecs_rel_t period, int cpu)
 {
 	union xnsched_policy_param param;
 	struct xnthread_start_attr sattr;
@@ -124,7 +125,14 @@ int rtdm_task_init(rtdm_task_t *task, const char *name,
 	iattr.name = name;
 	iattr.flags = 0;
 	iattr.personality = &xenomai_personality;
-	iattr.affinity = CPU_MASK_ALL;
+
+	if (cpu == -1) {
+		iattr.affinity = CPU_MASK_ALL;
+	} else {
+		cpumask_clear(&iattr.affinity);
+		cpumask_set_cpu(cpu, &iattr.affinity);
+	}
+
 	param.rt.prio = priority;
 
 	err = xnthread_init(task, &iattr, &xnsched_class_rt, &param);
diff --git a/kernel/drivers/analogy/testing/fake.c b/kernel/drivers/analogy/testing/fake.c
index fd88ed99f..8daba1047 100644
--- a/kernel/drivers/analogy/testing/fake.c
+++ b/kernel/drivers/analogy/testing/fake.c
@@ -637,7 +637,7 @@ static int test_attach(struct a4l_device *dev, a4l_lnkdesc_t *arg)
 
 	/* create the task */
 	ret = rtdm_task_init(&priv->task, "Fake AI task", task_proc, dev,
-		             RTDM_TASK_HIGHEST_PRIORITY, 0);
+		             RTDM_TASK_HIGHEST_PRIORITY, 0, -1);
 	if (ret)
 		a4l_dbg(1, drv_dbg, dev, "Error creating A4L task \n");
 
diff --git a/kernel/drivers/autotune/autotune.c b/kernel/drivers/autotune/autotune.c
index c11d18057..970ef6fda 100644
--- a/kernel/drivers/autotune/autotune.c
+++ b/kernel/drivers/autotune/autotune.c
@@ -291,7 +291,7 @@ static int init_kthread_tuner(struct gravity_tuner *tuner)
 
 	return rtdm_task_init(&k_tuner->task, "autotune",
 			      task_handler, k_tuner,
-			      RTDM_TASK_HIGHEST_PRIORITY, 0);
+			      RTDM_TASK_HIGHEST_PRIORITY, 0, -1);
 }
 
 static void destroy_kthread_tuner(struct gravity_tuner *tuner)
diff --git a/kernel/drivers/net/addons/proxy.c b/kernel/drivers/net/addons/proxy.c
index c3e5ce1c9..8398e4787 100644
--- a/kernel/drivers/net/addons/proxy.c
+++ b/kernel/drivers/net/addons/proxy.c
@@ -380,7 +380,7 @@ static int __init rtnetproxy_init_module(void)
 	rtdm_event_init(&rtnetproxy_tx_event, 0);
 	err = rtdm_task_init(&rtnetproxy_tx_task, "rtnetproxy",
 			     rtnetproxy_tx_loop, 0, RTDM_TASK_LOWEST_PRIORITY,
-			     0);
+			     0, -1);
 	if (err)
 		goto err4;
 
diff --git a/kernel/drivers/net/stack/ipv4/tcp/timerwheel.c b/kernel/drivers/net/stack/ipv4/tcp/timerwheel.c
index 209e45924..a7b259ffd 100644
--- a/kernel/drivers/net/stack/ipv4/tcp/timerwheel.c
+++ b/kernel/drivers/net/stack/ipv4/tcp/timerwheel.c
@@ -205,7 +205,7 @@ int __init timerwheel_init(nanosecs_rel_t timeout, unsigned int granularity)
 	rtdm_lock_init(&wheel.slot_lock);
 
 	err = rtdm_task_init(&wheel.pivot_task, "rttcp timerwheel",
-			     timerwheel_pivot, NULL, 1, 0);
+			     timerwheel_pivot, NULL, 1, 0, -1);
 	if (err) {
 		pr_err("error on pivot task initialization: %d\n", err);
 		kfree(wheel.ring);
diff --git a/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c b/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
index 70318ad3c..51cd2313e 100644
--- a/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
+++ b/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
@@ -545,7 +545,7 @@ int __init rtcfg_init_frames(void)
 	rtdm_event_init(&rx_event, 0);
 
 	ret = rtdm_task_init(&rx_task, "rtcfg-rx", rtcfg_rx_task, 0,
-			     RTDM_TASK_LOWEST_PRIORITY, 0);
+			     RTDM_TASK_LOWEST_PRIORITY, 0, -1);
 	if (ret < 0) {
 		rtdm_event_destroy(&rx_event);
 		goto error1;
diff --git a/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c b/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
index 6cdedae2f..9cf48c245 100644
--- a/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
+++ b/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
@@ -116,7 +116,7 @@ int __init nomac_proto_init(void)
 	rtdm_event_init(&wakeup_sem, 0);
 
 	ret = rtdm_task_init(&wrapper_task, "rtnet-nomac", nrt_xmit_task, 0,
-			     RTDM_TASK_LOWEST_PRIORITY, 0);
+			     RTDM_TASK_LOWEST_PRIORITY, 0, -1);
 	if (ret < 0) {
 		rtdm_event_destroy(&wakeup_sem);
 		return ret;
diff --git a/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c b/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c
index 3c516d23b..eb65f27d6 100644
--- a/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c
+++ b/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c
@@ -206,7 +206,7 @@ static int tdma_attach(struct rtnet_device *rtdev, void *priv)
 		goto err_out1;
 
 	ret = rtdm_task_init(&tdma->worker_task, "rtnet-tdma", tdma_worker,
-			     tdma, DEF_WORKER_PRIO, 0);
+			     tdma, DEF_WORKER_PRIO, 0, -1);
 	if (ret != 0)
 		goto err_out2;
 
diff --git a/kernel/drivers/net/stack/rtnet_rtpc.c b/kernel/drivers/net/stack/rtnet_rtpc.c
index 16dd84979..6d362c8d4 100644
--- a/kernel/drivers/net/stack/rtnet_rtpc.c
+++ b/kernel/drivers/net/stack/rtnet_rtpc.c
@@ -240,7 +240,7 @@ int __init rtpc_init(void)
 
 	ret = rtdm_task_init(&dispatch_task, "rtnet-rtpc",
 			     rtpc_dispatch_handler, 0,
-			     RTDM_TASK_LOWEST_PRIORITY, 0);
+			     RTDM_TASK_LOWEST_PRIORITY, 0, -1);
 	if (ret < 0) {
 		rtdm_event_destroy(&dispatch_event);
 		rtdm_nrtsig_destroy(&rtpc_nrt_signal);
diff --git a/kernel/drivers/net/stack/stack_mgr.c b/kernel/drivers/net/stack/stack_mgr.c
index 82e8412dc..eb3e720c5 100644
--- a/kernel/drivers/net/stack/stack_mgr.c
+++ b/kernel/drivers/net/stack/stack_mgr.c
@@ -249,7 +249,7 @@ int rt_stack_mgr_init(struct rtnet_mgr *mgr)
 	rtdm_event_init(&mgr->event, 0);
 
 	return rtdm_task_init(&mgr->task, "rtnet-stack", rt_stack_mgr_task, mgr,
-			      stack_mgr_prio, 0);
+			      stack_mgr_prio, 0, -1);
 }
 
 /***
diff --git a/kernel/drivers/testing/rtdmtest.c b/kernel/drivers/testing/rtdmtest.c
index ca29ec54b..cf5b6a927 100644
--- a/kernel/drivers/testing/rtdmtest.c
+++ b/kernel/drivers/testing/rtdmtest.c
@@ -167,7 +167,7 @@ static int rtdm_actor_open(struct rtdm_fd *fd, int oflags)
 
 	return rtdm_task_init(&ctx->actor_task, "rtdm_actor",
 			      actor_handler, ctx,
-			      RTDM_TASK_LOWEST_PRIORITY, 0);
+			      RTDM_TASK_LOWEST_PRIORITY, 0, -1);
 }
 
 static void rtdm_actor_close(struct rtdm_fd *fd)
diff --git a/kernel/drivers/testing/timerbench.c b/kernel/drivers/testing/timerbench.c
index 75da6bfdb..a96be5331 100644
--- a/kernel/drivers/testing/timerbench.c
+++ b/kernel/drivers/testing/timerbench.c
@@ -289,7 +289,7 @@ static int rt_tmbench_start(struct rtdm_fd *fd,
 	if (config->mode == RTTST_TMBENCH_TASK) {
 		err = rtdm_task_init(&ctx->timer_task, "timerbench",
 				timer_task_proc, ctx,
-				config->priority, 0);
+				config->priority, 0, -1);
 		if (!err)
 			ctx->mode = RTTST_TMBENCH_TASK;
 	} else {
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/5] Make RTDM tasks behave, part I
  2026-01-28 11:28 ` [PATCH 2/5] Make RTDM tasks behave, part I Richard Weinberger
@ 2026-01-28 13:23   ` Philippe Gerum
  2026-01-28 13:31     ` Richard Weinberger
  0 siblings, 1 reply; 13+ messages in thread
From: Philippe Gerum @ 2026-01-28 13:23 UTC (permalink / raw)
  To: Richard Weinberger; +Cc: xenomai, upstream+xenomai

Richard Weinberger <richard@nod.at> writes:

> RTDM tasks must now utilize rtdm_task_should_stop() to ensure proper
> cleanup and SIGSHADOW detection.
> Also, handle -EINTR gracefully, rather than exiting immediately on
> interruption, the task should loop and re-check rtdm_task_should_stop()
> to decide if termination is actually required.
>
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
>  kernel/drivers/autotune/autotune.c              | 17 ++++++++++-------
>  kernel/drivers/net/addons/proxy.c               |  6 +++++-
>  kernel/drivers/net/stack/ipv4/tcp/timerwheel.c  |  6 ++++--
>  kernel/drivers/net/stack/rtcfg/rtcfg_frame.c    |  6 +++++-
>  .../drivers/net/stack/rtmac/nomac/nomac_proto.c |  6 +++++-
>  .../drivers/net/stack/rtmac/tdma/tdma_worker.c  |  4 +++-
>  kernel/drivers/net/stack/rtnet_rtpc.c           |  5 ++++-
>  kernel/drivers/net/stack/stack_mgr.c            |  6 +++++-
>  kernel/drivers/testing/rtdmtest.c               |  9 ++++-----
>  kernel/drivers/testing/timerbench.c             |  2 +-
>  10 files changed, 46 insertions(+), 21 deletions(-)
>
> diff --git a/kernel/drivers/autotune/autotune.c b/kernel/drivers/autotune/autotune.c
> index 03fd688de..c11d18057 100644
> --- a/kernel/drivers/autotune/autotune.c
> +++ b/kernel/drivers/autotune/autotune.c
> @@ -248,22 +248,25 @@ static void task_handler(void *arg)
>  	xnticks_t now;
>  	int ret = 0;
>  
> -	for (;;) {
> -		if (rtdm_task_should_stop())
> -			break;
> -
> +	while (!rtdm_task_should_stop()) {
>  		ret = rtdm_event_wait(&k_tuner->barrier);
> -		if (ret)
> +		if (ret == -EINTR)
> +			continue;

Using -EINTR is going to be a problem if xnthread_unblock() is called to
forcibly wake up a kernel task from a sleep. In this case, you would not
be able to distinguish a signal receipt from a forcible
unblock. -ERESTARTSYS may be better for that specific purpose in the
RTDM API.

-- 
Philippe.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/5] Make RTDM tasks behave, part I
  2026-01-28 13:23   ` Philippe Gerum
@ 2026-01-28 13:31     ` Richard Weinberger
  2026-01-28 13:54       ` Richard Weinberger
  0 siblings, 1 reply; 13+ messages in thread
From: Richard Weinberger @ 2026-01-28 13:31 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: Richard Weinberger, xenomai, upstream+xenomai

On Mittwoch, 28. Jänner 2026 14:23 Philippe Gerum wrote:
> > +	while (!rtdm_task_should_stop()) {
> >  		ret = rtdm_event_wait(&k_tuner->barrier);
> > -		if (ret)
> > +		if (ret == -EINTR)
> > +			continue;
> 
> Using -EINTR is going to be a problem if xnthread_unblock() is called to
> forcibly wake up a kernel task from a sleep. In this case, you would not
> be able to distinguish a signal receipt from a forcible
> unblock. -ERESTARTSYS may be better for that specific purpose in the
> RTDM API.

What is the expected behavior of a RTDM task when xnthread_unblock() is called?
Currently, it will just terminate, which seems also odd to me.

With my changes it will at least revisit rtdm_task_should_stop() and distinguishing
between unblocking and signals is possible.
rtdm_task_should_stop() uses signal_pending().

Thanks,
//richard

-- 
​​​​​sigma star gmbh | Eduard-Bodem-Gasse 6, 6020 Innsbruck, AUT UID/VAT Nr:
ATU 66964118 | FN: 374287y



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/5] Make RTDM tasks behave, part I
  2026-01-28 13:31     ` Richard Weinberger
@ 2026-01-28 13:54       ` Richard Weinberger
  2026-01-28 16:37         ` Philippe Gerum
  0 siblings, 1 reply; 13+ messages in thread
From: Richard Weinberger @ 2026-01-28 13:54 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: Richard Weinberger, xenomai, upstream+xenomai

On Mittwoch, 28. Jänner 2026 14:31 Richard Weinberger wrote:
> > Using -EINTR is going to be a problem if xnthread_unblock() is called to
> > forcibly wake up a kernel task from a sleep. In this case, you would not
> > be able to distinguish a signal receipt from a forcible
> > unblock. -ERESTARTSYS may be better for that specific purpose in the
> > RTDM API.

Okay, I think now I got what you meant.
A blocking RTDM function such as rt_event_wait() should return something else
than EINTR upon signal reception?

Currently, these functions return EINTR when a woken up task has the XNBREAK
flag. Let me find out where in the signal reception path XNBREAK is gained.

Thanks,
//richard

-- 
​​​​​sigma star gmbh | Eduard-Bodem-Gasse 6, 6020 Innsbruck, AUT UID/VAT Nr:
ATU 66964118 | FN: 374287y



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/5] Make RTDM tasks behave, part I
  2026-01-28 13:54       ` Richard Weinberger
@ 2026-01-28 16:37         ` Philippe Gerum
  0 siblings, 0 replies; 13+ messages in thread
From: Philippe Gerum @ 2026-01-28 16:37 UTC (permalink / raw)
  To: Richard Weinberger; +Cc: Richard Weinberger, xenomai, upstream+xenomai

Richard Weinberger <richard@sigma-star.at> writes:

> On Mittwoch, 28. Jänner 2026 14:31 Richard Weinberger wrote:
>> > Using -EINTR is going to be a problem if xnthread_unblock() is called to
>> > forcibly wake up a kernel task from a sleep. In this case, you would not
>> > be able to distinguish a signal receipt from a forcible
>> > unblock. -ERESTARTSYS may be better for that specific purpose in the
>> > RTDM API.
>
> Okay, I think now I got what you meant.
> A blocking RTDM function such as rt_event_wait() should return something else
> than EINTR upon signal reception?
>
> Currently, these functions return EINTR when a woken up task has the XNBREAK
> flag. Let me find out where in the signal reception path XNBREAK is gained.
>

Yes, the fact that -EINTR is returned both for signal_pending() and
unblock is the fundamental issue, and that predates your patch set. This
is the way x3 has always dealt with inband signal receipt for userland
tasks as well, which is a problem.

-ERESTARTSYS should flow up the call stack in case signal_pending() is
detected by a sleeping out-of-band call, so that 1) we don't have to do
the prepare_for_signal() dance on our way back to user mode for
restarting a signal - which is basically about giving every syscall a
fixed "(not-)restartable" property instead of allowing the receiving
code to decide about this at the point of receipt, 2) the caller of the
interrupted call can decide what to do next on -ERESTARTSYS, including
RTDM tasks. Such a change went to x4 recently in order to align on the
regular inband handling of -ERESTARTSYS [1].

Whether an RTDM task receiving -EINTR on unblock should terminate or not
is a decision which should be taken on a case-by-case basis. Granted, we
could also ignore that condition in that particular case, because there
is no "user" to yield control back to anyway. The only requirement is to
cross rtdm_task_should_stop() soon enough to detect any pending
termination request when unblocked.

[1] https://gitlab.com/Xenomai/xenomai4/linux-evl/-/commit/51c312c6e52e2a65437a5f983e8c2d973aa8dcc1

-- 
Philippe.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/5] Make RTDM tasks behave, part II
  2026-01-28 11:28 ` [PATCH 3/5] Make RTDM tasks behave, part II Richard Weinberger
@ 2026-01-29  9:45   ` Jan Kiszka
  0 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2026-01-29  9:45 UTC (permalink / raw)
  To: Richard Weinberger, xenomai; +Cc: upstream+xenomai

On 28.01.26 12:28, Richard Weinberger wrote:
> Make sure that RTDM tasks terminate gracefully via rtdm_task_should_stop().
> To achieve this, enforce the correct teardown order: always terminate and
> join the thread first, and only then destroy the resources it was using.
> 
> While this change does not fix a bug, it allows us to distinguish between
> expected and unexpected task termination.

So far, the drivers used the resource teardown as "should stop" signal,
probably also for historical reasons (Xenomai 2, even RTAI was supported
this way).

But please write a more telling subject, rather than numbering the commits.

Jan

> 
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
>  kernel/drivers/net/addons/proxy.c                  | 2 +-
>  kernel/drivers/net/stack/rtcfg/rtcfg_frame.c       | 4 ++--
>  kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c | 2 +-
>  kernel/drivers/net/stack/rtmac/tdma/tdma_module.c  | 4 ++--
>  kernel/drivers/net/stack/rtnet_rtpc.c              | 2 +-
>  kernel/drivers/net/stack/stack_mgr.c               | 3 ++-
>  6 files changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/kernel/drivers/net/addons/proxy.c b/kernel/drivers/net/addons/proxy.c
> index e9956cd33..c3e5ce1c9 100644
> --- a/kernel/drivers/net/addons/proxy.c
> +++ b/kernel/drivers/net/addons/proxy.c
> @@ -418,8 +418,8 @@ static void __exit rtnetproxy_cleanup_module(void)
>  	unregister_netdev(dev_rtnetproxy);
>  	free_netdev(dev_rtnetproxy);
>  
> -	rtdm_event_destroy(&rtnetproxy_tx_event);
>  	rtdm_task_destroy(&rtnetproxy_tx_task);
> +	rtdm_event_destroy(&rtnetproxy_tx_event);
>  
>  	/* free the non-real-time signal */
>  	rtdm_nrtsig_destroy(&rtnetproxy_rx_signal);
> diff --git a/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c b/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
> index c7babb6d1..70318ad3c 100644
> --- a/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
> +++ b/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
> @@ -558,8 +558,8 @@ int __init rtcfg_init_frames(void)
>  	return 0;
>  
>  error2:
> -	rtdm_event_destroy(&rx_event);
>  	rtdm_task_destroy(&rx_task);
> +	rtdm_event_destroy(&rx_event);
>  
>  error1:
>  	rtskb_pool_release(&rtcfg_pool);
> @@ -573,8 +573,8 @@ void rtcfg_cleanup_frames(void)
>  
>  	rtdev_remove_pack(&rtcfg_packet_type);
>  
> -	rtdm_event_destroy(&rx_event);
>  	rtdm_task_destroy(&rx_task);
> +	rtdm_event_destroy(&rx_event);
>  
>  	while ((rtskb = rtskb_dequeue(&rx_queue)) != NULL) {
>  		kfree_rtskb(rtskb);
> diff --git a/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c b/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
> index 84317697b..6cdedae2f 100644
> --- a/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
> +++ b/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
> @@ -127,6 +127,6 @@ int __init nomac_proto_init(void)
>  
>  void nomac_proto_cleanup(void)
>  {
> -	rtdm_event_destroy(&wakeup_sem);
>  	rtdm_task_destroy(&wrapper_task);
> +	rtdm_event_destroy(&wakeup_sem);
>  }
> diff --git a/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c b/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c
> index 47c66d91f..3c516d23b 100644
> --- a/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c
> +++ b/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c
> @@ -228,14 +228,14 @@ static int tdma_detach(struct rtnet_device *rtdev, void *priv)
>  	struct tdma_priv *tdma = (struct tdma_priv *)priv;
>  	struct tdma_job *job, *tmp;
>  
> +	rtdm_task_destroy(&tdma->worker_task);
> +
>  	rtdm_event_destroy(&tdma->sync_event);
>  	rtdm_event_destroy(&tdma->xmit_event);
>  	rtdm_event_destroy(&tdma->worker_wakeup);
>  
>  	tdma_dev_release(tdma);
>  
> -	rtdm_task_destroy(&tdma->worker_task);
> -
>  	list_for_each_entry_safe (job, tmp, &tdma->first_job->entry, entry) {
>  		if (job->id >= 0)
>  			tdma_cleanup_slot(tdma, SLOT_JOB(job));
> diff --git a/kernel/drivers/net/stack/rtnet_rtpc.c b/kernel/drivers/net/stack/rtnet_rtpc.c
> index fe60209f2..16dd84979 100644
> --- a/kernel/drivers/net/stack/rtnet_rtpc.c
> +++ b/kernel/drivers/net/stack/rtnet_rtpc.c
> @@ -251,8 +251,8 @@ int __init rtpc_init(void)
>  
>  void rtpc_cleanup(void)
>  {
> -	rtdm_event_destroy(&dispatch_event);
>  	rtdm_task_destroy(&dispatch_task);
> +	rtdm_event_destroy(&dispatch_event);
>  	rtdm_nrtsig_destroy(&rtpc_nrt_signal);
>  }
>  
> diff --git a/kernel/drivers/net/stack/stack_mgr.c b/kernel/drivers/net/stack/stack_mgr.c
> index f4f8c7fff..82e8412dc 100644
> --- a/kernel/drivers/net/stack/stack_mgr.c
> +++ b/kernel/drivers/net/stack/stack_mgr.c
> @@ -257,6 +257,7 @@ int rt_stack_mgr_init(struct rtnet_mgr *mgr)
>   */
>  void rt_stack_mgr_delete(struct rtnet_mgr *mgr)
>  {
> -	rtdm_event_destroy(&mgr->event);
> +
>  	rtdm_task_destroy(&mgr->task);
> +	rtdm_event_destroy(&mgr->event);
>  }


-- 
Siemens AG, Foundational Technologies
Linux Expert Center

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/5] Warn on unexpected RTDM task termination
  2026-01-28 11:28 ` [PATCH 4/5] Warn on unexpected RTDM task termination Richard Weinberger
@ 2026-01-29  9:50   ` Jan Kiszka
  2026-01-29  9:54     ` Florian Bezdeka
  0 siblings, 1 reply; 13+ messages in thread
From: Jan Kiszka @ 2026-01-29  9:50 UTC (permalink / raw)
  To: Richard Weinberger, xenomai; +Cc: upstream+xenomai

On 28.01.26 12:28, Richard Weinberger wrote:
> Now that all in-tree RTDM tasks have been updated to handle termination
> correctly, introduce a check to detect unexpected task terminations.

They did this correctly already. Key is that semantics are changing, and
that needs adjustments.

> 
> This warning will assist authors of out-of-tree modules in identifying
> tasks that do not yet properly handle interrupted function calls.

Can you be more precise here? What are driver writers supposed to do,
what should they refrain from?

We have kernel/cobalt/rtdm/API.CHANGES, but that hasn't seen updates in
a long while. Better is likely to put the new task setup/teardown
pattern into the documentation of rtdm_task_init, also explaining when
the warning above would trigger.

Jan

> 
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
>  kernel/cobalt/thread.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
> index 3f0ed98ef..fb7190cf3 100644
> --- a/kernel/cobalt/thread.c
> +++ b/kernel/cobalt/thread.c
> @@ -210,6 +210,12 @@ static int kthread_trampoline(void *arg)
>  
>  	thread->entry(thread->cookie);
>  
> +	/*
> +	 * Warn the user if a thread chickens out.
> +	 */
> +	if (!xnthread_test_info(thread, XNCANCELD))
> +		printk(XENO_WARNING "unexpected thread termination: %s\n", thread->name);
> +
>  	xnthread_cancel(thread);
>  
>  	return 0;


-- 
Siemens AG, Foundational Technologies
Linux Expert Center

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 5/5] Allow specifying CPU affinity in rtdm_task_init()
  2026-01-28 11:28 ` [PATCH 5/5] Allow specifying CPU affinity in rtdm_task_init() Richard Weinberger
@ 2026-01-29  9:53   ` Jan Kiszka
  0 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2026-01-29  9:53 UTC (permalink / raw)
  To: Richard Weinberger, xenomai; +Cc: upstream+xenomai

On 28.01.26 12:28, Richard Weinberger wrote:
> Previously, rtdm_task_init() did not provide a way to pin a task to a
> specific CPU during initialization.
> 
> Update the function signature to accept a CPU identifier.
> Passing -1 results in the default behavior, allowing the
> scheduler to automatically select the CPU.

Please provide a telling constant for "-1" (RTDM_TASK_AFFINITY_DEFAULT
or so). Also explain what "automatic" means at this chance.

> 
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
>  include/cobalt/kernel/rtdm/driver.h                |  4 ++--
>  kernel/cobalt/rtdm/drvlib.c                        | 14 +++++++++++---
>  kernel/drivers/analogy/testing/fake.c              |  2 +-
>  kernel/drivers/autotune/autotune.c                 |  2 +-
>  kernel/drivers/net/addons/proxy.c                  |  2 +-
>  kernel/drivers/net/stack/ipv4/tcp/timerwheel.c     |  2 +-
>  kernel/drivers/net/stack/rtcfg/rtcfg_frame.c       |  2 +-
>  kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c |  2 +-
>  kernel/drivers/net/stack/rtmac/tdma/tdma_module.c  |  2 +-
>  kernel/drivers/net/stack/rtnet_rtpc.c              |  2 +-
>  kernel/drivers/net/stack/stack_mgr.c               |  2 +-
>  kernel/drivers/testing/rtdmtest.c                  |  2 +-
>  kernel/drivers/testing/timerbench.c                |  2 +-
>  13 files changed, 24 insertions(+), 16 deletions(-)
> 
> diff --git a/include/cobalt/kernel/rtdm/driver.h b/include/cobalt/kernel/rtdm/driver.h
> index 3fc5573cb..dcfbccbdf 100644
> --- a/include/cobalt/kernel/rtdm/driver.h
> +++ b/include/cobalt/kernel/rtdm/driver.h
> @@ -1032,8 +1032,8 @@ typedef void (*rtdm_task_proc_t)(void *arg);
>  /** @} rtdm_task */
>  
>  int rtdm_task_init(rtdm_task_t *task, const char *name,
> -		   rtdm_task_proc_t task_proc, void *arg,
> -		   int priority, nanosecs_rel_t period);
> +		   rtdm_task_proc_t task_proc, void *arg, int priority,
> +		   nanosecs_rel_t period, int cpu);
>  int __rtdm_task_sleep(xnticks_t timeout, xntmode_t mode);
>  void rtdm_task_busy_sleep(nanosecs_rel_t delay);
>  
> diff --git a/kernel/cobalt/rtdm/drvlib.c b/kernel/cobalt/rtdm/drvlib.c
> index 08e113904..f68b1089c 100644
> --- a/kernel/cobalt/rtdm/drvlib.c
> +++ b/kernel/cobalt/rtdm/drvlib.c
> @@ -101,6 +101,7 @@ nanosecs_abs_t rtdm_clock_read_monotonic(void);
>   * @param[in] arg Custom argument passed to @c task_proc() on entry
>   * @param[in] priority Priority of the task, see also
>   * @ref rtdmtaskprio "Task Priority Range"
> + * @param[in] cpu preferred CPU to run on, pass -1 for auto selection
>   * @param[in] period Period in nanoseconds of a cyclic task, 0 for non-cyclic
>   * mode. Waiting for the first and subsequent periodic events is
>   * done using rtdm_task_wait_period().
> @@ -110,8 +111,8 @@ nanosecs_abs_t rtdm_clock_read_monotonic(void);
>   * @coretags{secondary-only, might-switch}
>   */
>  int rtdm_task_init(rtdm_task_t *task, const char *name,
> -		   rtdm_task_proc_t task_proc, void *arg,
> -		   int priority, nanosecs_rel_t period)
> +		   rtdm_task_proc_t task_proc, void *arg, int priority,
> +		   nanosecs_rel_t period, int cpu)
>  {
>  	union xnsched_policy_param param;
>  	struct xnthread_start_attr sattr;
> @@ -124,7 +125,14 @@ int rtdm_task_init(rtdm_task_t *task, const char *name,
>  	iattr.name = name;
>  	iattr.flags = 0;
>  	iattr.personality = &xenomai_personality;
> -	iattr.affinity = CPU_MASK_ALL;
> +
> +	if (cpu == -1) {
> +		iattr.affinity = CPU_MASK_ALL;
> +	} else {
> +		cpumask_clear(&iattr.affinity);
> +		cpumask_set_cpu(cpu, &iattr.affinity);
> +	}
> +
>  	param.rt.prio = priority;
>  
>  	err = xnthread_init(task, &iattr, &xnsched_class_rt, &param);
> diff --git a/kernel/drivers/analogy/testing/fake.c b/kernel/drivers/analogy/testing/fake.c
> index fd88ed99f..8daba1047 100644
> --- a/kernel/drivers/analogy/testing/fake.c
> +++ b/kernel/drivers/analogy/testing/fake.c
> @@ -637,7 +637,7 @@ static int test_attach(struct a4l_device *dev, a4l_lnkdesc_t *arg)
>  
>  	/* create the task */
>  	ret = rtdm_task_init(&priv->task, "Fake AI task", task_proc, dev,
> -		             RTDM_TASK_HIGHEST_PRIORITY, 0);
> +		             RTDM_TASK_HIGHEST_PRIORITY, 0, -1);
>  	if (ret)
>  		a4l_dbg(1, drv_dbg, dev, "Error creating A4L task \n");
>  
> diff --git a/kernel/drivers/autotune/autotune.c b/kernel/drivers/autotune/autotune.c
> index c11d18057..970ef6fda 100644
> --- a/kernel/drivers/autotune/autotune.c
> +++ b/kernel/drivers/autotune/autotune.c
> @@ -291,7 +291,7 @@ static int init_kthread_tuner(struct gravity_tuner *tuner)
>  
>  	return rtdm_task_init(&k_tuner->task, "autotune",
>  			      task_handler, k_tuner,
> -			      RTDM_TASK_HIGHEST_PRIORITY, 0);
> +			      RTDM_TASK_HIGHEST_PRIORITY, 0, -1);
>  }
>  
>  static void destroy_kthread_tuner(struct gravity_tuner *tuner)
> diff --git a/kernel/drivers/net/addons/proxy.c b/kernel/drivers/net/addons/proxy.c
> index c3e5ce1c9..8398e4787 100644
> --- a/kernel/drivers/net/addons/proxy.c
> +++ b/kernel/drivers/net/addons/proxy.c
> @@ -380,7 +380,7 @@ static int __init rtnetproxy_init_module(void)
>  	rtdm_event_init(&rtnetproxy_tx_event, 0);
>  	err = rtdm_task_init(&rtnetproxy_tx_task, "rtnetproxy",
>  			     rtnetproxy_tx_loop, 0, RTDM_TASK_LOWEST_PRIORITY,
> -			     0);
> +			     0, -1);
>  	if (err)
>  		goto err4;
>  
> diff --git a/kernel/drivers/net/stack/ipv4/tcp/timerwheel.c b/kernel/drivers/net/stack/ipv4/tcp/timerwheel.c
> index 209e45924..a7b259ffd 100644
> --- a/kernel/drivers/net/stack/ipv4/tcp/timerwheel.c
> +++ b/kernel/drivers/net/stack/ipv4/tcp/timerwheel.c
> @@ -205,7 +205,7 @@ int __init timerwheel_init(nanosecs_rel_t timeout, unsigned int granularity)
>  	rtdm_lock_init(&wheel.slot_lock);
>  
>  	err = rtdm_task_init(&wheel.pivot_task, "rttcp timerwheel",
> -			     timerwheel_pivot, NULL, 1, 0);
> +			     timerwheel_pivot, NULL, 1, 0, -1);
>  	if (err) {
>  		pr_err("error on pivot task initialization: %d\n", err);
>  		kfree(wheel.ring);
> diff --git a/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c b/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
> index 70318ad3c..51cd2313e 100644
> --- a/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
> +++ b/kernel/drivers/net/stack/rtcfg/rtcfg_frame.c
> @@ -545,7 +545,7 @@ int __init rtcfg_init_frames(void)
>  	rtdm_event_init(&rx_event, 0);
>  
>  	ret = rtdm_task_init(&rx_task, "rtcfg-rx", rtcfg_rx_task, 0,
> -			     RTDM_TASK_LOWEST_PRIORITY, 0);
> +			     RTDM_TASK_LOWEST_PRIORITY, 0, -1);
>  	if (ret < 0) {
>  		rtdm_event_destroy(&rx_event);
>  		goto error1;
> diff --git a/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c b/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
> index 6cdedae2f..9cf48c245 100644
> --- a/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
> +++ b/kernel/drivers/net/stack/rtmac/nomac/nomac_proto.c
> @@ -116,7 +116,7 @@ int __init nomac_proto_init(void)
>  	rtdm_event_init(&wakeup_sem, 0);
>  
>  	ret = rtdm_task_init(&wrapper_task, "rtnet-nomac", nrt_xmit_task, 0,
> -			     RTDM_TASK_LOWEST_PRIORITY, 0);
> +			     RTDM_TASK_LOWEST_PRIORITY, 0, -1);
>  	if (ret < 0) {
>  		rtdm_event_destroy(&wakeup_sem);
>  		return ret;
> diff --git a/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c b/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c
> index 3c516d23b..eb65f27d6 100644
> --- a/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c
> +++ b/kernel/drivers/net/stack/rtmac/tdma/tdma_module.c
> @@ -206,7 +206,7 @@ static int tdma_attach(struct rtnet_device *rtdev, void *priv)
>  		goto err_out1;
>  
>  	ret = rtdm_task_init(&tdma->worker_task, "rtnet-tdma", tdma_worker,
> -			     tdma, DEF_WORKER_PRIO, 0);
> +			     tdma, DEF_WORKER_PRIO, 0, -1);
>  	if (ret != 0)
>  		goto err_out2;
>  
> diff --git a/kernel/drivers/net/stack/rtnet_rtpc.c b/kernel/drivers/net/stack/rtnet_rtpc.c
> index 16dd84979..6d362c8d4 100644
> --- a/kernel/drivers/net/stack/rtnet_rtpc.c
> +++ b/kernel/drivers/net/stack/rtnet_rtpc.c
> @@ -240,7 +240,7 @@ int __init rtpc_init(void)
>  
>  	ret = rtdm_task_init(&dispatch_task, "rtnet-rtpc",
>  			     rtpc_dispatch_handler, 0,
> -			     RTDM_TASK_LOWEST_PRIORITY, 0);
> +			     RTDM_TASK_LOWEST_PRIORITY, 0, -1);
>  	if (ret < 0) {
>  		rtdm_event_destroy(&dispatch_event);
>  		rtdm_nrtsig_destroy(&rtpc_nrt_signal);
> diff --git a/kernel/drivers/net/stack/stack_mgr.c b/kernel/drivers/net/stack/stack_mgr.c
> index 82e8412dc..eb3e720c5 100644
> --- a/kernel/drivers/net/stack/stack_mgr.c
> +++ b/kernel/drivers/net/stack/stack_mgr.c
> @@ -249,7 +249,7 @@ int rt_stack_mgr_init(struct rtnet_mgr *mgr)
>  	rtdm_event_init(&mgr->event, 0);
>  
>  	return rtdm_task_init(&mgr->task, "rtnet-stack", rt_stack_mgr_task, mgr,
> -			      stack_mgr_prio, 0);
> +			      stack_mgr_prio, 0, -1);
>  }
>  
>  /***
> diff --git a/kernel/drivers/testing/rtdmtest.c b/kernel/drivers/testing/rtdmtest.c
> index ca29ec54b..cf5b6a927 100644
> --- a/kernel/drivers/testing/rtdmtest.c
> +++ b/kernel/drivers/testing/rtdmtest.c
> @@ -167,7 +167,7 @@ static int rtdm_actor_open(struct rtdm_fd *fd, int oflags)
>  
>  	return rtdm_task_init(&ctx->actor_task, "rtdm_actor",
>  			      actor_handler, ctx,
> -			      RTDM_TASK_LOWEST_PRIORITY, 0);
> +			      RTDM_TASK_LOWEST_PRIORITY, 0, -1);
>  }
>  
>  static void rtdm_actor_close(struct rtdm_fd *fd)
> diff --git a/kernel/drivers/testing/timerbench.c b/kernel/drivers/testing/timerbench.c
> index 75da6bfdb..a96be5331 100644
> --- a/kernel/drivers/testing/timerbench.c
> +++ b/kernel/drivers/testing/timerbench.c
> @@ -289,7 +289,7 @@ static int rt_tmbench_start(struct rtdm_fd *fd,
>  	if (config->mode == RTTST_TMBENCH_TASK) {
>  		err = rtdm_task_init(&ctx->timer_task, "timerbench",
>  				timer_task_proc, ctx,
> -				config->priority, 0);
> +				config->priority, 0, -1);
>  		if (!err)
>  			ctx->mode = RTTST_TMBENCH_TASK;
>  	} else {


-- 
Siemens AG, Foundational Technologies
Linux Expert Center

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/5] Warn on unexpected RTDM task termination
  2026-01-29  9:50   ` Jan Kiszka
@ 2026-01-29  9:54     ` Florian Bezdeka
  0 siblings, 0 replies; 13+ messages in thread
From: Florian Bezdeka @ 2026-01-29  9:54 UTC (permalink / raw)
  To: Jan Kiszka, Richard Weinberger, xenomai; +Cc: upstream+xenomai

On Thu, 2026-01-29 at 10:50 +0100, Jan Kiszka wrote:
> On 28.01.26 12:28, Richard Weinberger wrote:
> > Now that all in-tree RTDM tasks have been updated to handle termination
> > correctly, introduce a check to detect unexpected task terminations.
> 
> They did this correctly already. Key is that semantics are changing, and
> that needs adjustments.
> 
> > 
> > This warning will assist authors of out-of-tree modules in identifying
> > tasks that do not yet properly handle interrupted function calls.
> 
> Can you be more precise here? What are driver writers supposed to do,
> what should they refrain from?
> 
> We have kernel/cobalt/rtdm/API.CHANGES, but that hasn't seen updates in
> a long while. Better is likely to put the new task setup/teardown
> pattern into the documentation of rtdm_task_init, also explaining when
> the warning above would trigger.

In addition to improving the documentation, can we somehow test that in
CI? I'm missing the testing part to avoid breaking it again.



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-01-29  9:54 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-28 11:28 [PATCH 1/5] Allow changing CPU affinity of RTDM tasks Richard Weinberger
2026-01-28 11:28 ` [PATCH 2/5] Make RTDM tasks behave, part I Richard Weinberger
2026-01-28 13:23   ` Philippe Gerum
2026-01-28 13:31     ` Richard Weinberger
2026-01-28 13:54       ` Richard Weinberger
2026-01-28 16:37         ` Philippe Gerum
2026-01-28 11:28 ` [PATCH 3/5] Make RTDM tasks behave, part II Richard Weinberger
2026-01-29  9:45   ` Jan Kiszka
2026-01-28 11:28 ` [PATCH 4/5] Warn on unexpected RTDM task termination Richard Weinberger
2026-01-29  9:50   ` Jan Kiszka
2026-01-29  9:54     ` Florian Bezdeka
2026-01-28 11:28 ` [PATCH 5/5] Allow specifying CPU affinity in rtdm_task_init() Richard Weinberger
2026-01-29  9:53   ` Jan Kiszka

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.