Commit bbd11b1a authored by Philippe Gerum's avatar Philippe Gerum Committed by Jan Kiszka

cobalt/thread: handle case of invalid domain migration over non-rt CPU

Attempting to migrate to the head domain while running on a CPU which
is not in part of the real-time set is a bug, and must be detected by
the core.

Furthermore, for this detection to work, the I-pipe must not BUG()
unconditionally when failing to schedule out such thread in
__ipipe_migrate_head(), but rather let the real-time core handle the
situation (i.e. Xenomai in xnthread_harden()).

Until both changes are in place, running a thread issuing a real-time
call over a non-RT CPU would trigger a BUG() assertion, e.g.:

With kernel parameter "xenomai.supported_cpus=2", running:

$ switchtest --cpu-affinity=0

would lead to:

[   11.681486] kernel BUG at kernel/sched/core.c:5816!
[   11.686343] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
Signed-off-by: Philippe Gerum's avatarPhilippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka's avatarJan Kiszka <jan.kiszka@siemens.com>
parent 5750102b
...@@ -856,7 +856,7 @@ static int handle_setaffinity_event(struct ipipe_cpu_migration_data *d) ...@@ -856,7 +856,7 @@ static int handle_setaffinity_event(struct ipipe_cpu_migration_data *d)
* take place on behalf of the target thread itself while * take place on behalf of the target thread itself while
* running in secondary mode. Therefore, that thread needs to * running in secondary mode. Therefore, that thread needs to
* go through secondary mode first, then move back to primary * go through secondary mode first, then move back to primary
* mode, so that check_affinity() does the fixup work. * mode, so that affinity_ok() does the fixup work.
* *
* We force this by sending a SIGSHADOW signal to the migrated * We force this by sending a SIGSHADOW signal to the migrated
* thread, asking it to switch back to primary mode from the * thread, asking it to switch back to primary mode from the
...@@ -873,7 +873,7 @@ static int handle_setaffinity_event(struct ipipe_cpu_migration_data *d) ...@@ -873,7 +873,7 @@ static int handle_setaffinity_event(struct ipipe_cpu_migration_data *d)
return KEVENT_PROPAGATE; return KEVENT_PROPAGATE;
} }
static inline void check_affinity(struct task_struct *p) /* nklocked, IRQs off */ static inline bool affinity_ok(struct task_struct *p) /* nklocked, IRQs off */
{ {
struct xnthread *thread = xnthread_from_task(p); struct xnthread *thread = xnthread_from_task(p);
struct xnsched *sched; struct xnsched *sched;
...@@ -912,12 +912,12 @@ static inline void check_affinity(struct task_struct *p) /* nklocked, IRQs off * ...@@ -912,12 +912,12 @@ static inline void check_affinity(struct task_struct *p) /* nklocked, IRQs off *
* in xnthread_harden(). * in xnthread_harden().
*/ */
xnthread_set_info(thread, XNCANCELD); xnthread_set_info(thread, XNCANCELD);
return; return false;
} }
sched = xnsched_struct(cpu); sched = xnsched_struct(cpu);
if (sched == thread->sched) if (sched == thread->sched)
return; return true;
/* /*
* The current thread moved to a supported real-time CPU, * The current thread moved to a supported real-time CPU,
...@@ -929,6 +929,8 @@ static inline void check_affinity(struct task_struct *p) /* nklocked, IRQs off * ...@@ -929,6 +929,8 @@ static inline void check_affinity(struct task_struct *p) /* nklocked, IRQs off *
xnthread_run_handler_stack(thread, move_thread, cpu); xnthread_run_handler_stack(thread, move_thread, cpu);
xnthread_migrate_passive(thread, sched); xnthread_migrate_passive(thread, sched);
return true;
} }
#else /* !CONFIG_SMP */ #else /* !CONFIG_SMP */
...@@ -940,7 +942,10 @@ static int handle_setaffinity_event(struct ipipe_cpu_migration_data *d) ...@@ -940,7 +942,10 @@ static int handle_setaffinity_event(struct ipipe_cpu_migration_data *d)
return KEVENT_PROPAGATE; return KEVENT_PROPAGATE;
} }
static inline void check_affinity(struct task_struct *p) { } static inline bool affinity_ok(struct task_struct *p)
{
return true;
}
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
...@@ -955,8 +960,8 @@ void ipipe_migration_hook(struct task_struct *p) /* hw IRQs off */ ...@@ -955,8 +960,8 @@ void ipipe_migration_hook(struct task_struct *p) /* hw IRQs off */
*/ */
xnlock_get(&nklock); xnlock_get(&nklock);
xnthread_run_handler_stack(thread, harden_thread); xnthread_run_handler_stack(thread, harden_thread);
check_affinity(p); if (affinity_ok(p))
xnthread_resume(thread, XNRELAX); xnthread_resume(thread, XNRELAX);
xnlock_put(&nklock); xnlock_put(&nklock);
xnsched_run(); xnsched_run();
......
...@@ -1945,6 +1945,7 @@ int xnthread_harden(void) ...@@ -1945,6 +1945,7 @@ int xnthread_harden(void)
ret = __ipipe_migrate_head(); ret = __ipipe_migrate_head();
if (ret) { if (ret) {
xnthread_test_cancel();
xnthread_set_sync_window(thread, XNRELAX); xnthread_set_sync_window(thread, XNRELAX);
return ret; return ret;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment