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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Thu Oct 16 14:40:45 2014 +0200

cobalt/posix/signal: prepare for 32bit syscall emulation

---

 kernel/cobalt/posix/extension.h |    2 +-
 kernel/cobalt/posix/signal.c    |  154 ++++++++++++++++++++++++---------------
 kernel/cobalt/posix/signal.h    |   17 +++++
 3 files changed, 115 insertions(+), 58 deletions(-)

diff --git a/kernel/cobalt/posix/extension.h b/kernel/cobalt/posix/extension.h
index 47c44f8..b831a3a 100644
--- a/kernel/cobalt/posix/extension.h
+++ b/kernel/cobalt/posix/extension.h
@@ -51,7 +51,7 @@ struct cobalt_extension {
                int (*signal_queue)(struct cobalt_extref *refthread,
                                    struct cobalt_sigpending *sigp);
                int (*signal_copyinfo)(struct cobalt_extref *refthread,
-                                      struct siginfo __user *u_si,
+                                      void __user *u_si,
                                       const struct siginfo *si,
                                       int overrun);
                int (*sched_yield)(struct cobalt_extref *curref);
diff --git a/kernel/cobalt/posix/signal.c b/kernel/cobalt/posix/signal.c
index 1259cc4..94d87d6 100644
--- a/kernel/cobalt/posix/signal.c
+++ b/kernel/cobalt/posix/signal.c
@@ -201,12 +201,15 @@ void cobalt_signal_flush(struct cobalt_thread *thread)
 }
 
 static int signal_wait(sigset_t *set, xnticks_t timeout,
-                      struct siginfo __user *u_si)
+                      void __user *u_si,
+                      int (*put_siginfo)(void __user *u_si,
+                                         const struct siginfo *si,
+                                         int overrun))
 {
        struct cobalt_sigpending *sigp = NULL;
        struct cobalt_sigwait_context swc;
-       int ret, sig, n, code, overrun;
        struct cobalt_thread *curr;
+       int ret, sig, n, overrun;
        unsigned long *p, *t, m;
        struct siginfo si, *sip;
        struct list_head *sigq;
@@ -303,37 +306,13 @@ done:
        if (u_si == NULL)
                goto out;       /* Return signo only. */
 
-       /* Translate kernel codes for userland. */
-       code = sip->si_code;
-       if (code & __SI_MASK)
-               code |= __SI_MASK;
-
-       ret = __xn_put_user(sip->si_signo, &u_si->si_signo);
-       ret |= __xn_put_user(sip->si_errno, &u_si->si_errno);
-       ret |= __xn_put_user(code, &u_si->si_code);
-
-       /*
-        * Copy the generic/standard siginfo bits to userland.
-        */
-       switch (sip->si_code) {
-       case SI_TIMER:
-               ret |= __xn_put_user(sip->si_tid, &u_si->si_tid);
-               ret |= __xn_put_user(sip->si_ptr, &u_si->si_ptr);
-               ret |= __xn_put_user(overrun, &u_si->si_overrun);
-               break;
-       case SI_QUEUE:
-       case SI_MESGQ:
-               ret |= __xn_put_user(sip->si_ptr, &u_si->si_ptr);
-               /* falldown wanted. */
-       case SI_USER:
-               ret |= __xn_put_user(sip->si_pid, &u_si->si_pid);
-               ret |= __xn_put_user(sip->si_uid, &u_si->si_uid);
-       }
+       ret = put_siginfo(u_si, sip, overrun);
+       if (ret)
+               goto out;
 
        /* Allow an extended target to receive more data. */
-       if (ret == 0)
-               cobalt_call_extension(signal_copyinfo, &curr->extref,
-                                     ret, u_si, sip, overrun);
+       cobalt_call_extension(signal_copyinfo, &curr->extref,
+                             ret, u_si, sip, overrun);
 out:
        /*
         * If we pulled the signal information from a sigpending
@@ -355,6 +334,47 @@ fail:
        return ret;
 }
 
+static int signal_put_siginfo(void __user *u_si, const struct siginfo *si,
+                             int overrun)
+{
+       struct siginfo __user *u_p = u_si;
+       int code, ret;
+
+       /* Translate kernel codes for userland. */
+       code = si->si_code;
+       if (code & __SI_MASK)
+               code |= __SI_MASK;
+
+       ret = __xn_put_user(si->si_signo, &u_p->si_signo);
+       ret |= __xn_put_user(si->si_errno, &u_p->si_errno);
+       ret |= __xn_put_user(code, &u_p->si_code);
+
+       /*
+        * Copy the generic/standard siginfo bits to userland.
+        */
+       switch (si->si_code) {
+       case SI_TIMER:
+               ret |= __xn_put_user(si->si_tid, &u_p->si_tid);
+               ret |= __xn_put_user(si->si_ptr, &u_p->si_ptr);
+               ret |= __xn_put_user(overrun, &u_p->si_overrun);
+               break;
+       case SI_QUEUE:
+       case SI_MESGQ:
+               ret |= __xn_put_user(si->si_ptr, &u_p->si_ptr);
+               /* falldown wanted. */
+       case SI_USER:
+               ret |= __xn_put_user(si->si_pid, &u_p->si_pid);
+               ret |= __xn_put_user(si->si_uid, &u_p->si_uid);
+       }
+
+       return ret;
+}
+
+int __cobalt_sigwait(sigset_t *set)
+{
+       return signal_wait(set, XN_INFINITE, NULL, NULL);
+}
+
 COBALT_SYSCALL(sigwait, primary,
               int, (const sigset_t __user *u_set, int __user *u_sig))
 {
@@ -364,7 +384,7 @@ COBALT_SYSCALL(sigwait, primary,
        if (__xn_safe_copy_from_user(&set, u_set, sizeof(set)))
                return -EFAULT;
 
-       sig = signal_wait(&set, XN_INFINITE, NULL);
+       sig = signal_wait(&set, XN_INFINITE, NULL, NULL);
        if (sig < 0)
                return sig;
 
@@ -374,13 +394,31 @@ COBALT_SYSCALL(sigwait, primary,
        return 0;
 }
 
+int __cobalt_sigtimedwait(sigset_t *set,
+                         const struct timespec *timeout,
+                         void __user *u_si,
+                         int (*put_siginfo)(void __user *u_si,
+                                            const struct siginfo *si,
+                                            int overrun))
+{
+       xnticks_t ticks;
+
+       if ((unsigned long)timeout->tv_nsec >= ONE_BILLION)
+               return -EINVAL;
+
+       ticks = ts2ns(timeout);
+       if (ticks++ == 0)
+               ticks = XN_NONBLOCK;
+
+       return signal_wait(set, ticks, u_si, put_siginfo);
+}
+
 COBALT_SYSCALL(sigtimedwait, nonrestartable,
               int, (const sigset_t __user *u_set,
                     struct siginfo __user *u_si,
                     const struct timespec __user *u_timeout))
 {
        struct timespec timeout;
-       xnticks_t ticks;
        sigset_t set;
 
        if (__xn_safe_copy_from_user(&set, u_set, sizeof(set)))
@@ -389,14 +427,16 @@ COBALT_SYSCALL(sigtimedwait, nonrestartable,
        if (__xn_safe_copy_from_user(&timeout, u_timeout, sizeof(timeout)))
                return -EFAULT;
 
-       if ((unsigned long)timeout.tv_nsec >= ONE_BILLION)
-               return -EINVAL;
-
-       ticks = ts2ns(&timeout);
-       if (ticks++ == 0)
-               ticks = XN_NONBLOCK;
+       return __cobalt_sigtimedwait(&set, &timeout, u_si, signal_put_siginfo);
+}
 
-       return signal_wait(&set, ticks, u_si);
+int __cobalt_sigwaitinfo(sigset_t *set,
+                        void __user *u_si,
+                        int (*put_siginfo)(void __user *u_si,
+                                           const struct siginfo *si,
+                                           int overrun))
+{
+       return signal_wait(set, XN_INFINITE, u_si, put_siginfo);
 }
 
 COBALT_SYSCALL(sigwaitinfo, nonrestartable,
@@ -408,20 +448,14 @@ COBALT_SYSCALL(sigwaitinfo, nonrestartable,
        if (__xn_safe_copy_from_user(&set, u_set, sizeof(set)))
                return -EFAULT;
 
-       return signal_wait(&set, XN_INFINITE, u_si);
+       return __cobalt_sigwaitinfo(&set, u_si, signal_put_siginfo);
 }
 
 COBALT_SYSCALL(sigpending, primary, int, (sigset_t __user *u_set))
 {
-       struct cobalt_thread *curr;
-
-       curr = cobalt_current_thread();
-       XENO_BUGON(COBALT, curr == NULL);
+       struct cobalt_thread *curr = cobalt_current_thread();
        
-       if (__xn_safe_copy_to_user(u_set, &curr->sigpending, sizeof(*u_set)))
-               return -EFAULT;
-
-       return 0;
+       return __xn_safe_copy_to_user(u_set, &curr->sigpending, sizeof(*u_set));
 }
 
 int __cobalt_kill(struct cobalt_thread *thread, int sig, int group) /* 
nklocked, IRQs off */
@@ -503,19 +537,13 @@ COBALT_SYSCALL(kill, conforming, int, (pid_t pid, int 
sig))
        return ret;
 }
 
-COBALT_SYSCALL(sigqueue, conforming,
-              int, (pid_t pid, int sig,
-                    const union sigval __user *u_value))
+int __cobalt_sigqueue(pid_t pid, int sig, const union sigval *value)
 {
        struct cobalt_sigpending *sigp;
        struct cobalt_thread *thread;
-       union sigval val;
        int ret = 0;
        spl_t s;
 
-       if (__xn_safe_copy_from_user(&val, u_value, sizeof(val)))
-               return -EFAULT;
-
        xnlock_get_irqsave(&nklock, s);
 
        thread = cobalt_thread_find(pid);
@@ -536,7 +564,7 @@ COBALT_SYSCALL(sigqueue, conforming,
                        sigp->si.si_code = SI_QUEUE;
                        sigp->si.si_pid = current->pid;
                        sigp->si.si_uid = get_current_uuid();
-                       sigp->si.si_value = val;
+                       sigp->si.si_value = *value;
                        if (cobalt_signal_send(thread, sigp, 1) <= 0)
                                cobalt_signal_free(sigp);
                        else
@@ -553,6 +581,18 @@ out:
        return ret;
 }
 
+COBALT_SYSCALL(sigqueue, conforming,
+              int, (pid_t pid, int sig,
+                    const union sigval __user *u_value))
+{
+       union sigval val;
+       int ret;
+
+       ret = __xn_safe_copy_from_user(&val, u_value, sizeof(val));
+
+       return ret ?: __cobalt_sigqueue(pid, sig, &val);
+}
+
 int cobalt_signal_pkg_init(void)
 {
        struct cobalt_sigpending *sigp;
diff --git a/kernel/cobalt/posix/signal.h b/kernel/cobalt/posix/signal.h
index 5c4e682..9f4c972 100644
--- a/kernel/cobalt/posix/signal.h
+++ b/kernel/cobalt/posix/signal.h
@@ -56,6 +56,23 @@ void cobalt_copy_siginfo(int code,
        }
 }
 
+int __cobalt_sigwait(sigset_t *set);
+
+int __cobalt_sigtimedwait(sigset_t *set,
+                         const struct timespec *timeout,
+                         void __user *u_si,
+                         int (*put_siginfo)(void __user *u_si,
+                                            const struct siginfo *si,
+                                            int overrun));
+
+int __cobalt_sigwaitinfo(sigset_t *set,
+                        void __user *u_si,
+                        int (*put_siginfo)(void __user *u_si,
+                                           const struct siginfo *si,
+                                           int overrun));
+
+int __cobalt_sigqueue(pid_t pid, int sig, const union sigval *value);
+
 int cobalt_signal_send(struct cobalt_thread *thread,
                       struct cobalt_sigpending *sigp,
                       int group);


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

Reply via email to