Module: xenomai-forge
Branch: next
Commit: b9f4fd82c32bd0dfa6d720003df0c327a62a0f42
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=b9f4fd82c32bd0dfa6d720003df0c327a62a0f42

Author: Philippe Gerum <r...@xenomai.org>
Date:   Mon Apr 28 13:29:22 2014 +0200

cobalt/posix/sem: move copy_from_user out of atomic section

---

 kernel/cobalt/posix/sem.c |   29 ++++++++++++++++++-----------
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
index 9bca743..718618c 100644
--- a/kernel/cobalt/posix/sem.c
+++ b/kernel/cobalt/posix/sem.c
@@ -402,14 +402,14 @@ static inline int
 sem_wait_inner(xnhandle_t handle, int timed,
               const struct timespec __user *u_ts)
 {
+       int pull_ts = 1, ret, info;
        struct cobalt_sem *sem;
        struct timespec ts;
        xntmode_t tmode;
-       int ret, info;
        spl_t s;
 
        xnlock_get_irqsave(&nklock, s);
-
+redo:
        sem = xnregistry_lookup(handle, NULL);
 
        ret = sem_trywait_inner(sem);
@@ -419,15 +419,20 @@ sem_wait_inner(xnhandle_t handle, int timed,
        }
 
        if (timed) {
-               if (u_ts == NULL ||
-                       __xn_safe_copy_from_user(&ts, u_ts, sizeof(ts))) {
-                       ret = -EFAULT;
-                       goto fail;
-               }
-
-               if (ts.tv_nsec >= ONE_BILLION) {
-                       ret = -EINVAL;
-                       goto fail;
+               if (pull_ts) {
+                       if (u_ts == NULL)
+                               goto efault;
+                       xnlock_put_irqrestore(&nklock, s);
+                       ret =__xn_safe_copy_from_user(&ts, u_ts, sizeof(ts));
+                       xnlock_get_irqsave(&nklock, s);
+                       if (ret)
+                               goto efault;
+                       if (ts.tv_nsec >= ONE_BILLION) {
+                               ret = -EINVAL;
+                               goto fail;
+                       }
+                       pull_ts = 0;
+                       goto redo;
                }
 
                tmode = sem->flags & SEM_RAWCLOCK ? XN_ABSOLUTE : XN_REALTIME;
@@ -448,6 +453,8 @@ out:
        xnlock_put_irqrestore(&nklock, s);
 
        return ret;
+efault:
+       ret = -EFAULT;
 fail:
        atomic_long_inc(&sem->datp->value);
        goto out;


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to