Module: xenomai-jki
Branch: for-upstream
Commit: 056aef63dfda607050abcecf0b9212591f140255
URL:    
http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=056aef63dfda607050abcecf0b9212591f140255

Author: Jan Kiszka <jan.kis...@siemens.com>
Date:   Tue Mar  2 16:24:59 2010 +0100

Native: Work around for error code corruption in rt_cond_wait[_until]

User space suffers from losing the error code of the cond wait prologue.
We would actually have to return the prologue error to user space and
use that one after the epilogue succeeded, but the existing kernel ABI
does not allow this nor is existing user space prepared for it.

As a workaround, keep the prologue error code in xnthread's errcode and
restore it from there when user space re-enters the kernel for the
epilogue. This requires no ABI changes, but suffers from potential
overwriting if the same or some other errcode touching service is called
from a user space signal handler in between the calls. Moreover, current
user space also prevents that we can return -EINTR on interruption while
blocked on the condition variable, which was possible before.

A true fix will require a new syscall and updated user space libs.

Signed-off-by: Jan Kiszka <jan.kis...@siemens.com>

---

 ksrc/skins/native/syscall.c |   26 ++++++++++++++++++++++----
 1 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/ksrc/skins/native/syscall.c b/ksrc/skins/native/syscall.c
index 462ee7e..ee6c829 100644
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -1841,7 +1841,7 @@ static int __rt_cond_wait_prologue(struct pt_regs *regs)
        RT_MUTEX *mutex;
        RT_COND *cond;
        RTIME timeout;
-       int err;
+       int err, epilogue_err;
 
        if (__xn_safe_copy_from_user(&cph, (void __user *)__xn_reg_arg1(regs),
                                     sizeof(cph)))
@@ -1869,10 +1869,21 @@ static int __rt_cond_wait_prologue(struct pt_regs *regs)
 
        err = rt_cond_wait_prologue(cond, mutex, &lockcnt, timeout_mode, 
timeout);
 
+       /* Old user space prevents that we can return -EINTR (it would loop
+          forever if we did). So drop this error. */
+       xnpod_current_thread()->errcode = err != -EINTR ? err : 0;
+
        /* Reacquire the mutex if it was unlocked in the prologue and we were
           not interrupted. */
-       if (lockcnt && err != -EINTR)
-               err = rt_cond_wait_epilogue(mutex, lockcnt);
+       if (lockcnt && err != -EINTR) {
+               epilogue_err = rt_cond_wait_epilogue(mutex, lockcnt);
+
+               /* Only overwrite the prologue if we need to signal -EINTR or
+                  the previous error was "less fatal". */
+               if (epilogue_err < 0 &&
+                   (epilogue_err == -EINTR || err != -EIDRM))
+                       err = epilogue_err;
+       }
 
        if (err == -EINTR && __xn_reg_arg3(regs)
            && __xn_safe_copy_to_user((void __user *)__xn_reg_arg3(regs),
@@ -1891,6 +1902,7 @@ static int __rt_cond_wait_epilogue(struct pt_regs *regs)
        RT_COND_PLACEHOLDER mph;
        unsigned lockcnt;
        RT_MUTEX *mutex;
+       int prologue_err, err;
 
        if (__xn_safe_copy_from_user(&mph, (void __user *)__xn_reg_arg1(regs),
                                     sizeof(mph)))
@@ -1903,7 +1915,13 @@ static int __rt_cond_wait_epilogue(struct pt_regs *regs)
 
        lockcnt = __xn_reg_arg2(regs);
 
-       return rt_cond_wait_epilogue(mutex, lockcnt);
+       err = rt_cond_wait_epilogue(mutex, lockcnt);
+       if (err == -EINTR)
+               return err;
+
+       prologue_err = xnpod_current_thread()->errcode;
+
+       return (err < 0 && prologue_err != -EIDRM) ? err : prologue_err;
 }
 
 /*


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to