[Xenomai-git] Philippe Gerum : cobalt/thread: fix leakage of XNKICKED status

2014-05-13 Thread git repository hosting
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

2014-05-08 Thread git repository hosting
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