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