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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Tue May  6 18:28:49 2014 +0200

cobalt/signal: implement sigqueue service

---

 include/cobalt/uapi/syscall.h |    2 +-
 kernel/cobalt/posix/signal.c  |   49 +++++++++++++++++++++++++++++++++++++++++
 kernel/cobalt/posix/signal.h  |    4 ++++
 kernel/cobalt/posix/syscall.c |    1 +
 4 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
index eb7e38c..1254ce5 100644
--- a/include/cobalt/uapi/syscall.h
+++ b/include/cobalt/uapi/syscall.h
@@ -80,7 +80,7 @@
 #define sc_cobalt_kill                 57
 #define sc_cobalt_sem_inquire           58
 #define sc_cobalt_event_inquire         59
-/* 60 unimplemented */
+#define sc_cobalt_sigqueue             60
 #define sc_cobalt_mutexattr_init        61
 #define sc_cobalt_mutexattr_destroy     62
 #define sc_cobalt_mutexattr_gettype     63
diff --git a/kernel/cobalt/posix/signal.c b/kernel/cobalt/posix/signal.c
index 93a1dda..15171e1 100644
--- a/kernel/cobalt/posix/signal.c
+++ b/kernel/cobalt/posix/signal.c
@@ -284,6 +284,7 @@ done:
                break;
        case SI_USER:
        case SI_MESGQ:
+       case SI_QUEUE:
                overrun = 0;
                break;
        default:
@@ -315,6 +316,7 @@ done:
                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. */
@@ -490,6 +492,53 @@ int cobalt_kill(pid_t pid, int sig)
        return ret;
 }
 
+int cobalt_sigqueue(pid_t pid, int sig,
+                   const union sigval __user *u_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);
+       if (thread == NULL) {
+               ret = -ESRCH;
+               goto out;
+       }
+
+       switch(sig) {
+       case 0:
+               /* Check for existence only. */
+               break;
+       case 1 ... _NSIG:
+               sigp = cobalt_signal_alloc();
+               if (sigp) {
+                       sigp->si.si_signo = sig;
+                       sigp->si.si_errno = 0;
+                       sigp->si.si_code = SI_QUEUE;
+                       sigp->si.si_pid = current->pid;
+                       sigp->si.si_uid = get_current_uuid();
+                       sigp->si.si_value = val;
+                       cobalt_signal_send(thread, sigp, 1);
+                       xnsched_run();
+               }
+               break;
+       default:
+               /* Cobalt pseudo-signals are never process-directed. */
+               ret = __cobalt_kill(thread, sig, 0);
+       }
+out:
+       xnlock_put_irqrestore(&nklock, s);
+
+       return ret;
+}
+
 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 26260a4..9ad3c9e 100644
--- a/kernel/cobalt/posix/signal.h
+++ b/kernel/cobalt/posix/signal.h
@@ -44,6 +44,7 @@ void cobalt_copy_siginfo(int code,
                dst->si_overrun = src->si_overrun;
                dst->si_value = src->si_value;
                break;
+       case SI_QUEUE:
        case SI_MESGQ:
                dst->si_value = src->si_value;
                /* falldown wanted. */
@@ -83,6 +84,9 @@ int __cobalt_kill(struct cobalt_thread *thread,
 
 int cobalt_kill(pid_t pid, int sig);
 
+int cobalt_sigqueue(pid_t pid, int sig,
+                   const union sigval __user *u_value);
+
 int cobalt_signal_pkg_init(void);
 
 void cobalt_signal_pkg_cleanup(void);
diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
index 4bec72b..6800855 100644
--- a/kernel/cobalt/posix/syscall.c
+++ b/kernel/cobalt/posix/syscall.c
@@ -136,6 +136,7 @@ static struct xnsyscall cobalt_syscalls[] = {
        SKINCALL_DEF(sc_cobalt_sigtimedwait, cobalt_sigtimedwait, 
nonrestartable),
        SKINCALL_DEF(sc_cobalt_sigpending, cobalt_sigpending, primary),
        SKINCALL_DEF(sc_cobalt_kill, cobalt_kill, conforming),
+       SKINCALL_DEF(sc_cobalt_sigqueue, cobalt_sigqueue, conforming),
        SKINCALL_DEF(sc_cobalt_timer_create, cobalt_timer_create, any),
        SKINCALL_DEF(sc_cobalt_timer_delete, cobalt_timer_delete, any),
        SKINCALL_DEF(sc_cobalt_timer_settime, cobalt_timer_settime, primary),


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

Reply via email to