Module: xenomai-3 Branch: stable-3.0.x Commit: a96a6d8e2816914aea7580bfd1ca969487bf2b01 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=a96a6d8e2816914aea7580bfd1ca969487bf2b01
Author: Philippe Gerum <r...@xenomai.org> Date: Thu Jul 7 18:35:47 2016 +0200 cobalt/rtdm: leave mode selection to I/O syscall handlers We don't want requests bearing invalid file descriptors (RTDM-wise) to trigger any mode switch, so that RTDM requests on regular fildes can be rejected with little overhead. Tell the core to hand over mode selection to RTDM I/O syscall handlers, which now check the file descriptor prior to triggering any mode transition. --- kernel/cobalt/posix/io.c | 10 +-- kernel/cobalt/posix/syscall32.c | 4 +- kernel/cobalt/rtdm/fd.c | 144 +++++++++++++++++++++++---------------- 3 files changed, 92 insertions(+), 66 deletions(-) diff --git a/kernel/cobalt/posix/io.c b/kernel/cobalt/posix/io.c index 7110d21..42b7b00 100644 --- a/kernel/cobalt/posix/io.c +++ b/kernel/cobalt/posix/io.c @@ -58,25 +58,25 @@ COBALT_SYSCALL(fcntl, current, (int fd, int cmd, int arg)) return rtdm_fd_fcntl(fd, cmd, arg); } -COBALT_SYSCALL(ioctl, probing, +COBALT_SYSCALL(ioctl, handover, (int fd, unsigned int request, void __user *arg)) { return rtdm_fd_ioctl(fd, request, arg); } -COBALT_SYSCALL(read, probing, +COBALT_SYSCALL(read, handover, (int fd, void __user *buf, size_t size)) { return rtdm_fd_read(fd, buf, size); } -COBALT_SYSCALL(write, probing, +COBALT_SYSCALL(write, handover, (int fd, const void __user *buf, size_t size)) { return rtdm_fd_write(fd, buf, size); } -COBALT_SYSCALL(recvmsg, probing, +COBALT_SYSCALL(recvmsg, handover, (int fd, struct user_msghdr __user *umsg, int flags)) { struct user_msghdr m; @@ -93,7 +93,7 @@ COBALT_SYSCALL(recvmsg, probing, return cobalt_copy_to_user(umsg, &m, sizeof(*umsg)) ?: ret; } -COBALT_SYSCALL(sendmsg, probing, +COBALT_SYSCALL(sendmsg, handover, (int fd, struct user_msghdr __user *umsg, int flags)) { struct user_msghdr m; diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c index 0576b37..bc8b9d9 100644 --- a/kernel/cobalt/posix/syscall32.c +++ b/kernel/cobalt/posix/syscall32.c @@ -766,7 +766,7 @@ COBALT_SYSCALL32emu(select, nonrestartable, return err; } -COBALT_SYSCALL32emu(recvmsg, probing, +COBALT_SYSCALL32emu(recvmsg, handover, (int fd, struct compat_msghdr __user *umsg, int flags)) { @@ -784,7 +784,7 @@ COBALT_SYSCALL32emu(recvmsg, probing, return sys32_put_msghdr(umsg, &m) ?: ret; } -COBALT_SYSCALL32emu(sendmsg, probing, +COBALT_SYSCALL32emu(sendmsg, handover, (int fd, struct compat_msghdr __user *umsg, int flags)) { struct user_msghdr m; diff --git a/kernel/cobalt/rtdm/fd.c b/kernel/cobalt/rtdm/fd.c index d82cfe4..3381dea 100644 --- a/kernel/cobalt/rtdm/fd.c +++ b/kernel/cobalt/rtdm/fd.c @@ -392,6 +392,44 @@ int rtdm_fd_fcntl(int ufd, int cmd, ...) } EXPORT_SYMBOL_GPL(rtdm_fd_fcntl); +static struct rtdm_fd *get_fd_fixup_mode(int ufd) +{ + struct xnthread *thread; + struct rtdm_fd *fd; + + fd = rtdm_fd_get(ufd, 0); + if (IS_ERR(fd)) + return fd; + + /* + * Mode is selected according to the following convention: + * + * - Cobalt threads must try running the syscall from primary + * mode as a first attempt, regardless of their scheduling + * class. The driver handler may ask for demoting the caller + * to secondary mode by returning -ENOSYS. + * + * - Regular threads (i.e. not bound to Cobalt) may only run + * the syscall from secondary mode. + */ + thread = xnthread_current(); + if (unlikely(ipipe_root_p)) { + if (thread == NULL || + xnthread_test_localinfo(thread, XNDESCENT)) + return fd; + } else if (likely(thread)) + return fd; + + /* + * We need to switch to the converse mode. Since all callers + * bear the "adaptive" tag, we just pass -ENOSYS back to the + * syscall dispatcher to get switched to the next mode. + */ + rtdm_fd_put(fd); + + return ERR_PTR(-ENOSYS); +} + int rtdm_fd_ioctl(int ufd, unsigned int request, ...) { struct rtdm_fd *fd; @@ -399,16 +437,14 @@ int rtdm_fd_ioctl(int ufd, unsigned int request, ...) va_list args; int err, ret; + fd = get_fd_fixup_mode(ufd); + if (IS_ERR(fd)) + return PTR_ERR(fd); + va_start(args, request); arg = va_arg(args, void __user *); va_end(args); - fd = rtdm_fd_get(ufd, 0); - if (IS_ERR(fd)) { - err = PTR_ERR(fd); - goto out; - } - set_compat_bit(fd); trace_cobalt_fd_ioctl(current, fd, ufd, request); @@ -419,7 +455,7 @@ int rtdm_fd_ioctl(int ufd, unsigned int request, ...) err = fd->ops->ioctl_rt(fd, request, arg); if (!XENO_ASSERT(COBALT, !spltest())) - splnone(); + splnone(); if (err < 0) { ret = __rtdm_dev_ioctl_core(fd, request, arg); @@ -428,7 +464,7 @@ int rtdm_fd_ioctl(int ufd, unsigned int request, ...) } rtdm_fd_put(fd); - out: + if (err < 0) trace_cobalt_fd_ioctl_status(current, fd, ufd, err); @@ -440,130 +476,120 @@ ssize_t rtdm_fd_read(int ufd, void __user *buf, size_t size) { struct rtdm_fd *fd; - ssize_t err; + ssize_t ret; - fd = rtdm_fd_get(ufd, 0); - if (IS_ERR(fd)) { - err = PTR_ERR(fd); - goto out; - } + fd = get_fd_fixup_mode(ufd); + if (IS_ERR(fd)) + return PTR_ERR(fd); set_compat_bit(fd); trace_cobalt_fd_read(current, fd, ufd, size); if (ipipe_root_p) - err = fd->ops->read_nrt(fd, buf, size); + ret = fd->ops->read_nrt(fd, buf, size); else - err = fd->ops->read_rt(fd, buf, size); + ret = fd->ops->read_rt(fd, buf, size); if (!XENO_ASSERT(COBALT, !spltest())) - splnone(); + splnone(); rtdm_fd_put(fd); - out: - if (err < 0) - trace_cobalt_fd_read_status(current, fd, ufd, err); + if (ret < 0) + trace_cobalt_fd_read_status(current, fd, ufd, ret); - return err; + return ret; } EXPORT_SYMBOL_GPL(rtdm_fd_read); ssize_t rtdm_fd_write(int ufd, const void __user *buf, size_t size) { struct rtdm_fd *fd; - ssize_t err; + ssize_t ret; - fd = rtdm_fd_get(ufd, 0); - if (IS_ERR(fd)) { - err = PTR_ERR(fd); - goto out; - } + fd = get_fd_fixup_mode(ufd); + if (IS_ERR(fd)) + return PTR_ERR(fd); set_compat_bit(fd); trace_cobalt_fd_write(current, fd, ufd, size); if (ipipe_root_p) - err = fd->ops->write_nrt(fd, buf, size); + ret = fd->ops->write_nrt(fd, buf, size); else - err = fd->ops->write_rt(fd, buf, size); + ret = fd->ops->write_rt(fd, buf, size); if (!XENO_ASSERT(COBALT, !spltest())) - splnone(); + splnone(); rtdm_fd_put(fd); - out: - if (err < 0) - trace_cobalt_fd_write_status(current, fd, ufd, err); + if (ret < 0) + trace_cobalt_fd_write_status(current, fd, ufd, ret); - return err; + return ret; } EXPORT_SYMBOL_GPL(rtdm_fd_write); ssize_t rtdm_fd_recvmsg(int ufd, struct user_msghdr *msg, int flags) { struct rtdm_fd *fd; - ssize_t err; + ssize_t ret; - fd = rtdm_fd_get(ufd, 0); - if (IS_ERR(fd)) { - err = PTR_ERR(fd); - goto out; - } + fd = get_fd_fixup_mode(ufd); + if (IS_ERR(fd)) + return PTR_ERR(fd); set_compat_bit(fd); trace_cobalt_fd_recvmsg(current, fd, ufd, flags); if (ipipe_root_p) - err = fd->ops->recvmsg_nrt(fd, msg, flags); + ret = fd->ops->recvmsg_nrt(fd, msg, flags); else - err = fd->ops->recvmsg_rt(fd, msg, flags); + ret = fd->ops->recvmsg_rt(fd, msg, flags); if (!XENO_ASSERT(COBALT, !spltest())) splnone(); rtdm_fd_put(fd); -out: - if (err < 0) - trace_cobalt_fd_recvmsg_status(current, fd, ufd, err); - return err; + if (ret < 0) + trace_cobalt_fd_recvmsg_status(current, fd, ufd, ret); + + return ret; } EXPORT_SYMBOL_GPL(rtdm_fd_recvmsg); ssize_t rtdm_fd_sendmsg(int ufd, const struct user_msghdr *msg, int flags) { struct rtdm_fd *fd; - ssize_t err; + ssize_t ret; - fd = rtdm_fd_get(ufd, 0); - if (IS_ERR(fd)) { - err = PTR_ERR(fd); - goto out; - } + fd = get_fd_fixup_mode(ufd); + if (IS_ERR(fd)) + return PTR_ERR(fd); set_compat_bit(fd); trace_cobalt_fd_sendmsg(current, fd, ufd, flags); if (ipipe_root_p) - err = fd->ops->sendmsg_nrt(fd, msg, flags); + ret = fd->ops->sendmsg_nrt(fd, msg, flags); else - err = fd->ops->sendmsg_rt(fd, msg, flags); + ret = fd->ops->sendmsg_rt(fd, msg, flags); if (!XENO_ASSERT(COBALT, !spltest())) - splnone(); + splnone(); rtdm_fd_put(fd); -out: - if (err < 0) - trace_cobalt_fd_sendmsg_status(current, fd, ufd, err); - return err; + if (ret < 0) + trace_cobalt_fd_sendmsg_status(current, fd, ufd, ret); + + return ret; } EXPORT_SYMBOL_GPL(rtdm_fd_sendmsg); _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org https://xenomai.org/mailman/listinfo/xenomai-git