Module: xenomai-forge Branch: next 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