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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Thu Aug 29 10:00:56 2013 +0200

cobalt: introduce rt-enabled kill(2) service

---

 include/cobalt/signal.h       |    2 +
 include/cobalt/uapi/syscall.h |    3 +-
 kernel/cobalt/posix/signal.c  |   78 +++++++++++++++++++++++++++++++++++++++++
 kernel/cobalt/posix/signal.h  |    4 ++
 kernel/cobalt/posix/syscall.c |    3 +-
 kernel/cobalt/posix/thread.c  |   72 ++-----------------------------------
 lib/cobalt/cobalt.wrappers    |    1 +
 lib/cobalt/signal.c           |   21 +++++++++++
 lib/cobalt/wrappers.c         |    6 +++
 9 files changed, 120 insertions(+), 70 deletions(-)

diff --git a/include/cobalt/signal.h b/include/cobalt/signal.h
index 17d8cb7..02b6c1c 100644
--- a/include/cobalt/signal.h
+++ b/include/cobalt/signal.h
@@ -44,6 +44,8 @@ COBALT_DECL(int, sigwaitinfo(const sigset_t *set, siginfo_t 
*si));
 COBALT_DECL(int, sigtimedwait(const sigset_t *set, siginfo_t *si,
                              const struct timespec *timeout));
 
+COBALT_DECL(int, kill(pid_t pid, int sig));
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
index 43064ae..3d92f29 100644
--- a/include/cobalt/uapi/syscall.h
+++ b/include/cobalt/uapi/syscall.h
@@ -77,7 +77,8 @@
 #define sc_cobalt_sigwaitinfo          54
 #define sc_cobalt_sigtimedwait         55
 #define sc_cobalt_sigpending           56
-/* 57-60 unimplemented */
+#define sc_cobalt_kill                 57
+/* 58-60 unimplemented */
 #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 a3d443d..73a390b 100644
--- a/kernel/cobalt/posix/signal.c
+++ b/kernel/cobalt/posix/signal.c
@@ -385,6 +385,84 @@ int cobalt_sigpending(sigset_t __user *u_set)
        return 0;
 }
 
+int __cobalt_kill(struct cobalt_thread *thread, int sig) /* nklocked, IRQs off 
*/
+{
+       struct cobalt_sigpending *sigp;
+       int ret = 0;
+
+       /*
+        * We have undocumented pseudo-signals to suspend/resume/unblock
+        * threads, force them out of primary mode or even demote them
+        * to the weak scheduling class/priority. Process them early,
+        * before anyone can notice...
+        */
+       switch(sig) {
+       case 0:
+               /* Check for existence only. */
+               break;
+       case SIGSUSP:
+               /*
+                * All callers shall be tagged as conforming calls, so
+                * self-directed suspension can only happen from
+                * primary mode. Yummie.
+                */
+               xnthread_suspend(&thread->threadbase, XNSUSP,
+                                XN_INFINITE, XN_RELATIVE, NULL);
+               if (&thread->threadbase == xnsched_current_thread() &&
+                   xnthread_test_info(&thread->threadbase, XNBREAK))
+                       ret = EINTR;
+               break;
+       case SIGRESM:
+               xnthread_resume(&thread->threadbase, XNSUSP);
+               goto resched;
+       case SIGRELS:
+               xnthread_unblock(&thread->threadbase);
+               goto resched;
+       case SIGKICK:
+               xnshadow_kick(&thread->threadbase);
+               goto resched;
+       case SIGDEMT:
+               xnshadow_demote(&thread->threadbase);
+               goto resched;
+       case 1 ... _NSIG:
+               sigp = cobalt_signal_alloc();
+               if (sigp) {
+                       sigp->si.si_signo = sig;
+                       sigp->si.si_errno = 0;
+                       sigp->si.si_code = SI_USER;
+                       sigp->si.si_pid = current->pid;
+                       sigp->si.si_uid = current_uid();
+                       cobalt_signal_send(thread, sigp);
+               }
+       resched:
+               xnsched_run();
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+int cobalt_kill(pid_t pid, int sig)
+{
+       struct cobalt_thread *thread;
+       int ret;
+       spl_t s;
+
+       xnlock_get_irqsave(&nklock, s);
+
+       thread = cobalt_thread_find(pid);
+       if (thread == NULL)
+               ret = -ESRCH;
+       else
+               ret = __cobalt_kill(thread, sig);
+
+       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 ae39e7d..a3f1879 100644
--- a/kernel/cobalt/posix/signal.h
+++ b/kernel/cobalt/posix/signal.h
@@ -83,6 +83,10 @@ int cobalt_sigwaitinfo(const sigset_t __user *u_set,
 
 int cobalt_sigpending(sigset_t __user *u_set);
 
+int __cobalt_kill(struct cobalt_thread *thread, int sig);
+
+int cobalt_kill(pid_t pid, int sig);
+
 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 7123dee..7608c9e 100644
--- a/kernel/cobalt/posix/syscall.c
+++ b/kernel/cobalt/posix/syscall.c
@@ -90,7 +90,7 @@ static struct xnsyscall cobalt_syscalls[] = {
        SKINCALL_DEF(sc_cobalt_thread_set_mode, cobalt_thread_set_mode_np, 
primary),
        SKINCALL_DEF(sc_cobalt_thread_set_name, cobalt_thread_set_name_np, any),
        SKINCALL_DEF(sc_cobalt_thread_probe, cobalt_thread_probe_np, any),
-       SKINCALL_DEF(sc_cobalt_thread_kill, cobalt_thread_kill, any),
+       SKINCALL_DEF(sc_cobalt_thread_kill, cobalt_thread_kill, conforming),
        SKINCALL_DEF(sc_cobalt_thread_getstat, cobalt_thread_stat, any),
        SKINCALL_DEF(sc_cobalt_sem_init, cobalt_sem_init, any),
        SKINCALL_DEF(sc_cobalt_sem_destroy, cobalt_sem_destroy, any),
@@ -133,6 +133,7 @@ static struct xnsyscall cobalt_syscalls[] = {
        SKINCALL_DEF(sc_cobalt_sigwaitinfo, cobalt_sigwaitinfo, primary),
        SKINCALL_DEF(sc_cobalt_sigtimedwait, cobalt_sigtimedwait, primary),
        SKINCALL_DEF(sc_cobalt_sigpending, cobalt_sigpending, primary),
+       SKINCALL_DEF(sc_cobalt_kill, cobalt_kill, 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),
diff --git a/kernel/cobalt/posix/thread.c b/kernel/cobalt/posix/thread.c
index b20c2cf..342c044 100644
--- a/kernel/cobalt/posix/thread.c
+++ b/kernel/cobalt/posix/thread.c
@@ -1057,10 +1057,9 @@ int cobalt_thread_probe_np(pid_t pid)
 
 int cobalt_thread_kill(unsigned long pth, int sig)
 {
-       struct cobalt_sigpending *sigp;
        struct cobalt_local_hkey hkey;
        struct cobalt_thread *thread;
-       int ret = 0;
+       int ret;
        spl_t s;
 
        xnlock_get_irqsave(&nklock, s);
@@ -1068,74 +1067,11 @@ int cobalt_thread_kill(unsigned long pth, int sig)
        hkey.u_pth = pth;
        hkey.mm = current->mm;
        thread = thread_lookup(&hkey);
-       if (thread == NULL) {
+       if (thread == NULL)
                ret = -ESRCH;
-               goto out;
-       }
+       else
+               ret = __cobalt_kill(thread, sig);
 
-       /*
-        * We have undocumented pseudo-signals to suspend/resume/unblock
-        * threads, force them out of primary mode or even demote them
-        * to the weak scheduling class/priority. Process them early,
-        * before anyone can notice...
-        */
-       switch(sig) {
-       case 0:
-               /* Check for existence only. */
-               break;
-       case SIGSUSP:
-               /*
-                * Marking cobalt_thread_kill as __xn_exec_primary for
-                * handling self-suspension would be overkill, since
-                * no other signal would require this, so we handle
-                * that case locally here.
-                */
-               if (xnshadow_current_p(&thread->threadbase) && 
xnsched_root_p()) {
-                       /*
-                        * We won't vanish, so we may drop the lock
-                        * while hardening.
-                        */
-                       xnlock_put_irqrestore(&nklock, s);
-                       ret = xnshadow_harden();
-                       if (ret)
-                               return ret;
-                       xnlock_get_irqsave(&nklock, s);
-               }
-               xnthread_suspend(&thread->threadbase, XNSUSP,
-                                XN_INFINITE, XN_RELATIVE, NULL);
-               if (&thread->threadbase == xnsched_current_thread() &&
-                   xnthread_test_info(&thread->threadbase, XNBREAK))
-                       ret = EINTR;
-               break;
-       case SIGRESM:
-               xnthread_resume(&thread->threadbase, XNSUSP);
-               goto resched;
-       case SIGRELS:
-               xnthread_unblock(&thread->threadbase);
-               goto resched;
-       case SIGKICK:
-               xnshadow_kick(&thread->threadbase);
-               goto resched;
-       case SIGDEMT:
-               xnshadow_demote(&thread->threadbase);
-               goto resched;
-       case 1 ... _NSIG:
-               sigp = cobalt_signal_alloc();
-               if (sigp) {
-                       sigp->si.si_signo = sig;
-                       sigp->si.si_errno = 0;
-                       sigp->si.si_code = SI_USER;
-                       sigp->si.si_pid = current->pid;
-                       sigp->si.si_uid = current_uid();
-                       cobalt_signal_send(thread, sigp);
-               }
-       resched:
-               xnsched_run();
-               break;
-       default:
-               ret = -EINVAL;
-       }
-out:
        xnlock_put_irqrestore(&nklock, s);
 
        return ret;
diff --git a/lib/cobalt/cobalt.wrappers b/lib/cobalt/cobalt.wrappers
index c02ad7d..570d04e 100644
--- a/lib/cobalt/cobalt.wrappers
+++ b/lib/cobalt/cobalt.wrappers
@@ -108,3 +108,4 @@
 --wrap sigwaitinfo
 --wrap sigtimedwait
 --wrap sigpending
+--wrap kill
diff --git a/lib/cobalt/signal.c b/lib/cobalt/signal.c
index a66e035..4bc6bce 100644
--- a/lib/cobalt/signal.c
+++ b/lib/cobalt/signal.c
@@ -73,3 +73,24 @@ COBALT_IMPL(int, sigpending, (sigset_t *set))
 
        return 0;
 }
+
+COBALT_IMPL(int, kill, (pid_t pid, int sig))
+{
+       int ret;
+
+       /*
+        * Delegate processing of special pids to the regular
+        * kernel. We only deal with thread-directed signals.
+        */
+       if (pid <= 0)
+               return __real_kill(pid, sig);
+
+       ret = XENOMAI_SKINCALL2(__cobalt_muxid,
+                               sc_cobalt_kill, pid, sig);
+       if (ret) {
+               errno = -ret;
+               return -1;
+       }
+
+       return 0;
+}
diff --git a/lib/cobalt/wrappers.c b/lib/cobalt/wrappers.c
index 868aa91..6620e0b 100644
--- a/lib/cobalt/wrappers.c
+++ b/lib/cobalt/wrappers.c
@@ -426,6 +426,12 @@ int __real_sigpending(sigset_t *set)
        return sigpending(set);
 }
 
+__attribute__ ((weak))
+int __real_kill(pid_t pid, int sig)
+{
+       return kill(pid, sig);
+}
+
 #ifdef __PROVIDE_CPU_COUNT
 
 int __sched_cpucount(size_t setsize, const cpu_set_t *setp)


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

Reply via email to