[Xenomai-git] Philippe Gerum : cobalt/thread: fix leakage of XNKICKED status
Module: xenomai-forge Branch: next Commit: 7c333b78a809b78f72bfc07d05f9236a182a2b82 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=7c333b78a809b78f72bfc07d05f9236a182a2b82 Author: Philippe Gerum r...@xenomai.org Date: Thu May 8 13:09:20 2014 +0200 cobalt/thread: fix leakage of XNKICKED status Considering the following scenario, on a multi-core system: 1. kernel@CPU0 sends regular linux signal to preempted thread@CPU1 2. thread@CPU1 kicked in ready state (XNREADY|XNKICKED) in sigwake 3. thread@CPU1 regains CPU, invokes linux/lostage syscall next 4. thread@CPU1 relaxes prior to running syscall handler 5. thread@CPU1 skips prepare_for_signal() because in relaxed mode 6. thread@CPU1 handles regular signal on its way back to userland = XNKICKED set, signal_pending(thread) cleared. 7. thread@CPU1 invokes syscall requiring primary mode (hardens at first pass) 8. thread@CPU1 runs blocking Xenomai syscall, fails due to XNKICKED 9. thread@CPU1 skips prepare_for_signal() because signal_pending() false 10. goto 7 Oops. The fix is to make sure that a kicked thread about to relax (which means suspend Xenomai-wise) clears the XNKICKED bit right before suspending, since it will necessarily traverse the regular signal handling code on its way back to userland, prior to returning from a blocking Xenomai service. --- kernel/cobalt/thread.c | 20 +--- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c index 7e4c9de..5887be9 100644 --- a/kernel/cobalt/thread.c +++ b/kernel/cobalt/thread.c @@ -810,18 +810,16 @@ void xnthread_suspend(struct xnthread *thread, int mask, /* * If attempting to suspend a runnable thread which is pending -* a forced switch to secondary mode, just raise the break -* condition and return immediately. +* a forced switch to secondary mode (XNKICKED), just raise +* the XNBREAK status and return immediately, except if we +* are precisely doing such switch by applying XNRELAX. * -* We may end up suspending a kicked thread that has been -* preempted on its relaxing path, which is a perfectly valid -* situation: we just ignore the signal notification in -* primary mode, and rely on the wakeup call pending for that -* task in the root context, to collect and act upon the -* pending Linux signal (see handle_sigwake_event()). +* In the latter case, we also make sure to clear XNKICKED, +* since we won't go through prepare_for_signal() once +* relaxed. */ - if ((oldstate XNTHREAD_BLOCK_BITS) == 0) { - if ((mask XNRELAX) == 0) { + if (likely((oldstate XNTHREAD_BLOCK_BITS) == 0)) { + if (likely((mask XNRELAX) == 0)) { if (xnthread_test_info(thread, XNKICKED)) goto abort; if (thread == sched-curr @@ -829,7 +827,7 @@ void xnthread_suspend(struct xnthread *thread, int mask, goto abort; } xnthread_clear_info(thread, - XNRMID|XNTIMEO|XNBREAK|XNWAKEN|XNROBBED); + XNRMID|XNTIMEO|XNBREAK|XNWAKEN|XNROBBED|XNKICKED); } /* ___ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git
[Xenomai-git] Philippe Gerum : cobalt/thread: fix leakage of XNKICKED status
Module: xenomai-forge Branch: next Commit: 3902294054710cdbd8f766c04b565010cfd81918 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=3902294054710cdbd8f766c04b565010cfd81918 Author: Philippe Gerum r...@xenomai.org Date: Thu May 8 13:09:20 2014 +0200 cobalt/thread: fix leakage of XNKICKED status Considering the following scenario, on a multi-core system: 1. kernel@CPU0 sends regular linux signal to preempted thread@CPU1 2. thread@CPU1 kicked in ready state (XNREADY|XNKICKED) in sigwake 3. thread@CPU1 regains CPU, invokes linux/lostage syscall next 4. thread@CPU1 relaxes prior to running syscall handler 5. thread@CPU1 skips prepare_for_signal() because in relaxed mode 6. thread@CPU1 handles regular signal on its way back to userland = XNKICKED set, signal_pending(thread) cleared. 7. thread@CPU1 invokes syscall requiring primary mode (hardens at first pass) 8. thread@CPU1 runs blocking Xenomai syscall, fails due to XNKICKED 9. thread@CPU1 skips prepare_for_signal() because signal_pending() false 10. goto 7 Oops. The fix is to make sure that a kicked thread about to relax (which means suspend Xenomai-wise) clears the XNKICKED bit right before suspending, since it will necessarily traverse the regular signal handling code on its way back to userland, prior to returning from a blocking Xenomai service. --- kernel/cobalt/thread.c | 20 +--- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c index 7e4c9de..5887be9 100644 --- a/kernel/cobalt/thread.c +++ b/kernel/cobalt/thread.c @@ -810,18 +810,16 @@ void xnthread_suspend(struct xnthread *thread, int mask, /* * If attempting to suspend a runnable thread which is pending -* a forced switch to secondary mode, just raise the break -* condition and return immediately. +* a forced switch to secondary mode (XNKICKED), just raise +* the XNBREAK status and return immediately, except if we +* are precisely doing such switch by applying XNRELAX. * -* We may end up suspending a kicked thread that has been -* preempted on its relaxing path, which is a perfectly valid -* situation: we just ignore the signal notification in -* primary mode, and rely on the wakeup call pending for that -* task in the root context, to collect and act upon the -* pending Linux signal (see handle_sigwake_event()). +* In the latter case, we also make sure to clear XNKICKED, +* since we won't go through prepare_for_signal() once +* relaxed. */ - if ((oldstate XNTHREAD_BLOCK_BITS) == 0) { - if ((mask XNRELAX) == 0) { + if (likely((oldstate XNTHREAD_BLOCK_BITS) == 0)) { + if (likely((mask XNRELAX) == 0)) { if (xnthread_test_info(thread, XNKICKED)) goto abort; if (thread == sched-curr @@ -829,7 +827,7 @@ void xnthread_suspend(struct xnthread *thread, int mask, goto abort; } xnthread_clear_info(thread, - XNRMID|XNTIMEO|XNBREAK|XNWAKEN|XNROBBED); + XNRMID|XNTIMEO|XNBREAK|XNWAKEN|XNROBBED|XNKICKED); } /* ___ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git