Module: xenomai-forge Branch: next Commit: 90f104d2c6a3ae9b0e65529683278bdf98b18310 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=90f104d2c6a3ae9b0e65529683278bdf98b18310
Author: Philippe Gerum <r...@xenomai.org> Date: Sat Sep 20 11:09:04 2014 +0200 cobalt/rtdm, lib/cobalt: unify file descriptor management Use regular kernel file descriptors for all kinds of connection handles, referring to regular file objects: - connection to devnode => filp on chrdev inode - socket => filp on anon inode User and kernel-originated connection handles are no more differenciated. The former procfs interface for RTDM is now entirely gone, as all file descriptors are now visible from /proc/<pid>/fd. Obtaining the list of all named devices can be done this way: $ grep named /sys/class/rtdm/*/flags Similarly, the list of all protocol devices can be obtained this way: $ grep protocol /sys/class/rtdm/*/flags Force closing a stuck file descriptor (formerly done by writing to rtdm/open_fildes) makes no sense anymore. Either the owner is a userland process and all file handles it holds will be automatically dropped at exit, or it is a kernel driver, in which case the driver direly needs fixing. --- include/cobalt/kernel/rtdm/fd.h | 11 +- include/cobalt/kernel/rtdm/rtdm.h | 12 +- kernel/cobalt/Kconfig | 10 -- kernel/cobalt/posix/io.c | 2 +- kernel/cobalt/posix/mqueue.c | 9 +- kernel/cobalt/posix/timerfd.c | 10 +- kernel/cobalt/rtdm/Makefile | 5 +- kernel/cobalt/rtdm/core.c | 157 +------------------- kernel/cobalt/rtdm/device.c | 16 +- kernel/cobalt/rtdm/fd.c | 67 +++++---- kernel/cobalt/rtdm/init.c | 58 -------- kernel/cobalt/rtdm/internal.h | 33 +---- kernel/cobalt/rtdm/proc.c | 295 ------------------------------------- lib/cobalt/mq.c | 9 +- lib/cobalt/rtdm.c | 43 +++--- 15 files changed, 106 insertions(+), 631 deletions(-) diff --git a/include/cobalt/kernel/rtdm/fd.h b/include/cobalt/kernel/rtdm/fd.h index d4a97b2..c04cd4d 100644 --- a/include/cobalt/kernel/rtdm/fd.h +++ b/include/cobalt/kernel/rtdm/fd.h @@ -302,7 +302,11 @@ struct rtdm_fd { struct list_head cleanup; }; -#define XNFD_MAGIC_ANY 0 +#define RTDM_FD_MAGIC 0x52544446 + +int __rtdm_anon_getfd(const char *name, int flags); + +void __rtdm_anon_putfd(int ufd); static inline struct xnsys_ppd *rtdm_fd_owner(struct rtdm_fd *fd) { @@ -331,9 +335,6 @@ ssize_t rtdm_fd_read(int ufd, void __user *buf, size_t size); ssize_t rtdm_fd_write(int ufd, const void __user *buf, size_t size); -int __rtdm_fd_close(struct xnsys_ppd *ppd, - int ufd, unsigned int magic); - int rtdm_fd_close(int ufd, unsigned int magic); ssize_t rtdm_fd_recvmsg(int ufd, struct msghdr *msg, int flags); @@ -353,6 +354,4 @@ void rtdm_fd_cleanup(struct xnsys_ppd *p); void rtdm_fd_init(void); -extern const struct file_operations rtdm_dumb_fops; - #endif /* _COBALT_KERNEL_FD_H */ diff --git a/include/cobalt/kernel/rtdm/rtdm.h b/include/cobalt/kernel/rtdm/rtdm.h index b1ffab3..b3a25b4 100644 --- a/include/cobalt/kernel/rtdm/rtdm.h +++ b/include/cobalt/kernel/rtdm/rtdm.h @@ -28,14 +28,12 @@ #include <cobalt/kernel/ppd.h> #include <rtdm/fd.h> -#define RTDM_FD_MAGIC 0x52544446 - typedef u32 socklen_t; -int __rtdm_dev_kopen(const char *path, int oflag); +int __rtdm_dev_open(const char *path, int oflag); -int __rtdm_dev_ksocket(int protocol_family, int socket_type, - int protocol); +int __rtdm_dev_socket(int protocol_family, + int socket_type, int protocol); int __rt_dev_ioctl_fallback(struct rtdm_fd *fd, unsigned request, void __user *arg); @@ -47,10 +45,10 @@ __rt_dev_ioctl_fallback(struct rtdm_fd *fd, unsigned request, void __user *arg); #ifndef RTDM_NO_DEFAULT_USER_API #define rt_dev_open(path, oflag, ...) \ - __rtdm_dev_kopen(path, oflag) + __rtdm_dev_open(path, oflag) #define rt_dev_socket(protocol_family, socket_type, protocol) \ - __rtdm_dev_ksocket(protocol_family, socket_type, protocol) + __rtdm_dev_socket(protocol_family, socket_type, protocol) #define rt_dev_close(fd) \ rtdm_fd_close(fd, RTDM_FD_MAGIC) diff --git a/kernel/cobalt/Kconfig b/kernel/cobalt/Kconfig index 6301437..8937d75 100644 --- a/kernel/cobalt/Kconfig +++ b/kernel/cobalt/Kconfig @@ -340,16 +340,6 @@ config XENO_OPT_NRTIMERS given time for each Cobalt process (a timer is created by a call to the timer_create() service of the Cobalt/POSIX API). -config XENO_OPT_RTDM_FILDES - int "Maximum number of RTDM file descriptors" - default 128 - help - - This option defines the system-wide maximum number of RTDM - file descriptors which can be opened at the same time (a file - descriptor is created by each successful call to the open() - service of the Cobalt/POSIX API). - config XENO_OPT_DEBUG_TRACE_LOGSZ int "Trace log size" depends on XENO_OPT_DEBUG_TRACE_RELAX diff --git a/kernel/cobalt/posix/io.c b/kernel/cobalt/posix/io.c index 7880fbc..15ff720 100644 --- a/kernel/cobalt/posix/io.c +++ b/kernel/cobalt/posix/io.c @@ -51,7 +51,7 @@ COBALT_SYSCALL(socket, lostage, COBALT_SYSCALL(close, lostage, int, (int fd)) { - return rtdm_fd_close(fd, XNFD_MAGIC_ANY); + return rtdm_fd_close(fd, 0); } COBALT_SYSCALL(ioctl, probing, diff --git a/kernel/cobalt/posix/mqueue.c b/kernel/cobalt/posix/mqueue.c index dc27b65..9727bed 100644 --- a/kernel/cobalt/posix/mqueue.c +++ b/kernel/cobalt/posix/mqueue.c @@ -17,9 +17,6 @@ */ #include <stdarg.h> -#include <linux/fs.h> -#include <linux/fdtable.h> -#include <linux/anon_inodes.h> #include <linux/slab.h> #include <linux/mm.h> #include <cobalt/kernel/select.h> @@ -789,7 +786,6 @@ COBALT_SYSCALL(mq_open, lostage, { struct mq_attr locattr, *attr; char name[COBALT_MAXNAME]; - struct xnsys_ppd *ppd; unsigned int len; mqd_t uqd; int ret; @@ -814,14 +810,13 @@ COBALT_SYSCALL(mq_open, lostage, trace_cobalt_mq_open(name, oflags, mode); - ppd = cobalt_ppd_get(0); - uqd = anon_inode_getfd("[cobalt-mq]", &rtdm_dumb_fops, ppd, oflags); + uqd = __rtdm_anon_getfd("[cobalt-mq]", oflags); if (uqd < 0) return uqd; ret = mq_open(uqd, name, oflags, mode, attr); if (ret < 0) { - __close_fd(current->files, uqd); + __rtdm_anon_putfd(uqd); return ret; } diff --git a/kernel/cobalt/posix/timerfd.c b/kernel/cobalt/posix/timerfd.c index 5cd0521..f994a22 100644 --- a/kernel/cobalt/posix/timerfd.c +++ b/kernel/cobalt/posix/timerfd.c @@ -18,8 +18,6 @@ #include <linux/timerfd.h> #include <linux/err.h> -#include <linux/fdtable.h> -#include <linux/anon_inodes.h> #include <cobalt/kernel/timer.h> #include <cobalt/kernel/select.h> #include <rtdm/fd.h> @@ -168,7 +166,6 @@ COBALT_SYSCALL(timerfd_create, lostage, { struct cobalt_tfd *tfd; struct xnthread *curr; - struct xnsys_ppd *ppd; int ret, ufd; if (clockid != CLOCK_REALTIME && clockid != CLOCK_MONOTONIC) @@ -181,9 +178,8 @@ COBALT_SYSCALL(timerfd_create, lostage, if (tfd == NULL) return -ENOMEM; - ppd = cobalt_ppd_get(0); - ufd = anon_inode_getfd("[cobalt-timerfd]", &rtdm_dumb_fops, ppd, - O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS)); + ufd = __rtdm_anon_getfd("[cobalt-timerfd]", + O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS)); if (ufd < 0) { ret = ufd; goto fail_getfd; @@ -207,7 +203,7 @@ fail: xnselect_destroy(&tfd->read_select); xnsynch_destroy(&tfd->readers); xntimer_destroy(&tfd->timer); - __close_fd(current->files, ufd); + __rtdm_anon_putfd(ufd); fail_getfd: xnfree(tfd); diff --git a/kernel/cobalt/rtdm/Makefile b/kernel/cobalt/rtdm/Makefile index 3ba1495..0f06261 100644 --- a/kernel/cobalt/rtdm/Makefile +++ b/kernel/cobalt/rtdm/Makefile @@ -4,9 +4,6 @@ obj-$(CONFIG_XENOMAI) += xenomai.o xenomai-y := core.o \ device.o \ drvlib.o \ - fd.o \ - init.o - -xenomai-$(CONFIG_PROC_FS) += proc.o + fd.o ccflags-y := -Iarch/$(SRCARCH)/xenomai/include -Iinclude/xenomai -I$(src)/.. diff --git a/kernel/cobalt/rtdm/core.c b/kernel/cobalt/rtdm/core.c index 84afc94..50b3718 100644 --- a/kernel/cobalt/rtdm/core.c +++ b/kernel/cobalt/rtdm/core.c @@ -37,12 +37,6 @@ * @{ */ -#define FD_BITMAP_SIZE ((RTDM_FD_MAX + BITS_PER_LONG-1) / BITS_PER_LONG) -static unsigned long used_fildes[FD_BITMAP_SIZE]; -int open_fildes; /* number of used descriptors */ - -DEFINE_XNLOCK(rt_fildes_lock); - static void cleanup_instance(struct rtdm_device *device, struct rtdm_dev_context *context) { @@ -64,74 +58,14 @@ void __rt_dev_close(struct rtdm_fd *fd) cleanup_instance(device, context); } -void __rt_dev_unref(struct rtdm_fd *fd, unsigned int idx) +int __rtdm_anon_getfd(const char *name, int flags) { - if (fd->magic != RTDM_FD_MAGIC) - return; - - xnlock_get(&rt_fildes_lock); - if (rtdm_fd_owner(fd) == &__xnsys_global_ppd) { - clear_bit(idx, used_fildes); - --open_fildes; - } - xnlock_put(&rt_fildes_lock); + return anon_inode_getfd(name, &rtdm_dumb_fops, NULL, flags); } -static int create_kinstance(struct rtdm_device *device, - struct rtdm_dev_context **context_ptr) +void __rtdm_anon_putfd(int ufd) { - struct rtdm_device_class *class = device->class; - struct rtdm_dev_context *context; - int ufd, ret; - spl_t s; - - /* - * Reset to NULL so that we can always use cleanup_files/instance to - * revert also partially successful allocations. - */ - *context_ptr = NULL; - - xnlock_get_irqsave(&rt_fildes_lock, s); - - if (unlikely(open_fildes >= RTDM_FD_MAX)) { - xnlock_put_irqrestore(&rt_fildes_lock, s); - return -ENFILE; - } - - ufd = find_first_zero_bit(used_fildes, RTDM_FD_MAX); - __set_bit(ufd, used_fildes); - open_fildes++; - - xnlock_put_irqrestore(&rt_fildes_lock, s); - - if ((class->device_flags & RTDM_EXCLUSIVE) != 0 && - atomic_read(&device->refcount) > 1) { - ret = -EBUSY; - goto fail; - } - - context = kmalloc(sizeof(struct rtdm_dev_context) + - class->context_size, GFP_KERNEL); - if (unlikely(context == NULL)) { - ret = -ENOMEM; - goto fail; - } - - context->device = device; - *context_ptr = context; - - ret = rtdm_fd_enter(&context->fd, ufd, RTDM_FD_MAGIC, &device->ops); - if (ret < 0) - goto fail; - - return ufd; -fail: - xnlock_get_irqsave(&rt_fildes_lock, s); - __clear_bit(ufd, used_fildes); - open_fildes--; - xnlock_put_irqrestore(&rt_fildes_lock, s); - - return ret; + __close_fd(current->files, ufd); } static int create_instance(int ufd, struct rtdm_device *device, @@ -161,46 +95,6 @@ static int create_instance(int ufd, struct rtdm_device *device, return rtdm_fd_enter(&context->fd, ufd, RTDM_FD_MAGIC, &device->ops); } -int __rtdm_dev_kopen(const char *path, int oflag) -{ - struct rtdm_dev_context *context; - struct rtdm_device *device; - int ufd, ret; - - secondary_mode_only(); - - device = __rtdm_get_namedev(path); - if (device == NULL) - return -ENODEV; - - ufd = create_kinstance(device, &context); - if (ufd < 0) { - ret = ufd; - goto fail; - } - - context->fd.minor = device->minor; - - trace_cobalt_fd_open(current, &context->fd, ufd, oflag); - - if (device->ops.open) { - ret = device->ops.open(&context->fd, oflag); - if (!XENO_ASSERT(COBALT, !spltest())) - splnone(); - if (ret < 0) - goto fail; - } - - trace_cobalt_fd_created(&context->fd, ufd); - - return ufd; -fail: - cleanup_instance(device, context); - - return ret; -} -EXPORT_SYMBOL_GPL(__rtdm_dev_kopen); - int __rtdm_dev_open(const char *path, int oflag) { struct rtdm_dev_context *context; @@ -261,51 +155,11 @@ fail_fd: } EXPORT_SYMBOL_GPL(__rtdm_dev_open); -int __rtdm_dev_ksocket(int protocol_family, int socket_type, - int protocol) -{ - struct rtdm_dev_context *context; - struct rtdm_device *device; - int ufd, ret; - - secondary_mode_only(); - - device = __rtdm_get_protodev(protocol_family, socket_type); - if (device == NULL) - return -EAFNOSUPPORT; - - ufd = create_kinstance(device, &context); - if (ufd < 0) { - ret = ufd; - goto fail; - } - - trace_cobalt_fd_socket(current, &context->fd, ufd, protocol_family); - - if (device->ops.socket) { - ret = device->ops.socket(&context->fd, protocol); - if (!XENO_ASSERT(COBALT, !spltest())) - splnone(); - if (ret < 0) - goto fail; - } - - trace_cobalt_fd_created(&context->fd, ufd); - - return ufd; -fail: - cleanup_instance(device, context); - - return ret; -} -EXPORT_SYMBOL_GPL(__rtdm_dev_ksocket); - int __rtdm_dev_socket(int protocol_family, int socket_type, int protocol) { struct rtdm_dev_context *context; struct rtdm_device *device; - struct xnsys_ppd *ppd; int ufd, ret; secondary_mode_only(); @@ -314,8 +168,7 @@ int __rtdm_dev_socket(int protocol_family, int socket_type, if (device == NULL) return -EAFNOSUPPORT; - ppd = cobalt_ppd_get(0); - ufd = anon_inode_getfd("[rtdm-proto]", &rtdm_dumb_fops, ppd, O_RDWR); + ufd = __rtdm_anon_getfd("[rtdm-socket]", O_RDWR); if (ufd < 0) { ret = ufd; goto fail_getfd; diff --git a/kernel/cobalt/rtdm/device.c b/kernel/cobalt/rtdm/device.c index 0432a7b..494de27 100644 --- a/kernel/cobalt/rtdm/device.c +++ b/kernel/cobalt/rtdm/device.c @@ -28,6 +28,18 @@ #include <trace/events/cobalt-rtdm.h> /** + * @ingroup rtdm + * @defgroup rtdm_profiles Device Profiles + * + * Pre-defined classes of real-time devices + * + * Device profiles define which operation handlers a driver of a certain class + * has to implement, which name or protocol it has to register, which IOCTLs + * it has to provide, and further details. Sub-classes can be defined in order + * to extend a device profile with more hardware-specific functions. + */ + +/** * @addtogroup rtdm_driver_interface * @{ */ @@ -444,7 +456,7 @@ EXPORT_SYMBOL_GPL(rtdm_dev_unregister); /** @} */ -int __init rtdm_dev_init(void) +int __init rtdm_init(void) { sema_init(&nrt_dev_lock, 1); @@ -462,7 +474,7 @@ int __init rtdm_dev_init(void) return 0; } -void rtdm_dev_cleanup(void) +void rtdm_cleanup(void) { class_destroy(rtdm_class); /* diff --git a/kernel/cobalt/rtdm/fd.c b/kernel/cobalt/rtdm/fd.c index c6e6cce..b911982 100644 --- a/kernel/cobalt/rtdm/fd.c +++ b/kernel/cobalt/rtdm/fd.c @@ -24,6 +24,7 @@ #include <linux/poll.h> #include <linux/kthread.h> #include <linux/semaphore.h> +#include <linux/fdtable.h> #include <cobalt/kernel/registry.h> #include <cobalt/kernel/lock.h> #include <cobalt/kernel/ppd.h> @@ -125,7 +126,7 @@ int rtdm_fd_enter(struct rtdm_fd *fd, int ufd, unsigned int magic, secondary_mode_only(); - if (magic == XNFD_MAGIC_ANY) + if (magic == 0) return -EINVAL; idx = kmalloc(sizeof(*idx), GFP_KERNEL); @@ -177,21 +178,21 @@ int rtdm_fd_enter(struct rtdm_fd *fd, int ufd, unsigned int magic, struct rtdm_fd *rtdm_fd_get(int ufd, unsigned int magic) { struct xnsys_ppd *p = cobalt_ppd_get(0); - struct rtdm_fd *res; + struct rtdm_fd *fd; spl_t s; xnlock_get_irqsave(&__rtdm_fd_lock, s); - res = fetch_fd(p, ufd); - if (res == NULL || (magic != XNFD_MAGIC_ANY && res->magic != magic)) { - res = ERR_PTR(-EBADF); - goto err_unlock; + fd = fetch_fd(p, ufd); + if (fd == NULL || (magic != 0 && fd->magic != magic)) { + fd = ERR_PTR(-EBADF); + goto out; } - ++res->refs; - err_unlock: + ++fd->refs; +out: xnlock_put_irqrestore(&__rtdm_fd_lock, s); - return res; + return fd; } EXPORT_SYMBOL_GPL(rtdm_fd_get); @@ -341,7 +342,7 @@ int rtdm_fd_ioctl(int ufd, unsigned int request, ...) arg = va_arg(args, void __user *); va_end(args); - fd = rtdm_fd_get(ufd, XNFD_MAGIC_ANY); + fd = rtdm_fd_get(ufd, 0); if (IS_ERR(fd)) { err = PTR_ERR(fd); goto out; @@ -378,7 +379,7 @@ rtdm_fd_read(int ufd, void __user *buf, size_t size) struct rtdm_fd *fd; ssize_t err; - fd = rtdm_fd_get(ufd, XNFD_MAGIC_ANY); + fd = rtdm_fd_get(ufd, 0); if (IS_ERR(fd)) { err = PTR_ERR(fd); goto out; @@ -409,7 +410,7 @@ ssize_t rtdm_fd_write(int ufd, const void __user *buf, size_t size) struct rtdm_fd *fd; ssize_t err; - fd = rtdm_fd_get(ufd, XNFD_MAGIC_ANY); + fd = rtdm_fd_get(ufd, 0); if (IS_ERR(fd)) { err = PTR_ERR(fd); goto out; @@ -440,7 +441,7 @@ ssize_t rtdm_fd_recvmsg(int ufd, struct msghdr *msg, int flags) struct rtdm_fd *fd; ssize_t err; - fd = rtdm_fd_get(ufd, XNFD_MAGIC_ANY); + fd = rtdm_fd_get(ufd, 0); if (IS_ERR(fd)) { err = PTR_ERR(fd); goto out; @@ -470,7 +471,7 @@ ssize_t rtdm_fd_sendmsg(int ufd, const struct msghdr *msg, int flags) struct rtdm_fd *fd; ssize_t err; - fd = rtdm_fd_get(ufd, XNFD_MAGIC_ANY); + fd = rtdm_fd_get(ufd, 0); if (IS_ERR(fd)) { err = PTR_ERR(fd); goto out; @@ -504,36 +505,43 @@ __fd_close(struct xnsys_ppd *p, struct rtdm_fd_index *idx, spl_t s) kfree(idx); } -int __rtdm_fd_close(struct xnsys_ppd *ppd, int ufd, unsigned int magic) +int rtdm_fd_close(int ufd, unsigned int magic) { struct rtdm_fd_index *idx; + struct xnsys_ppd *ppd; struct rtdm_fd *fd; spl_t s; + secondary_mode_only(); + + ppd = cobalt_ppd_get(0); + xnlock_get_irqsave(&__rtdm_fd_lock, s); idx = fetch_fd_index(ppd, ufd); if (idx == NULL) goto ebadf; fd = idx->fd; - if (magic != XNFD_MAGIC_ANY && fd->magic != magic) { - ebadf: + if (magic != 0 && fd->magic != magic) { +ebadf: xnlock_put_irqrestore(&__rtdm_fd_lock, s); return -EBADF; } trace_cobalt_fd_close(current, fd, ufd, fd->refs); - __rt_dev_unref(fd, xnid_key(&idx->id)); + /* + * In dual kernel mode, the linux-side fdtable and the RTDM + * ->close() handler are asynchronously managed, i.e. the + * handler execution may be deferred after the regular file + * descriptor was removed from the fdtable if some refs on + * rtdm_fd are still pending. + */ __fd_close(ppd, idx, s); + __close_fd(current->files, ufd); return 0; } - -int rtdm_fd_close(int ufd, unsigned int magic) -{ - return __rtdm_fd_close(cobalt_ppd_get(0), ufd, magic); -} EXPORT_SYMBOL_GPL(rtdm_fd_close); int rtdm_fd_mmap(int ufd, struct _rtdm_mmap_request *rma, @@ -542,7 +550,9 @@ int rtdm_fd_mmap(int ufd, struct _rtdm_mmap_request *rma, struct rtdm_fd *fd; int ret; - fd = rtdm_fd_get(ufd, XNFD_MAGIC_ANY); + secondary_mode_only(); + + fd = rtdm_fd_get(ufd, 0); if (IS_ERR(fd)) { ret = PTR_ERR(fd); goto out; @@ -603,7 +613,7 @@ int rtdm_fd_select(int ufd, struct xnselector *selector, struct rtdm_fd *fd; int rc; - fd = rtdm_fd_get(ufd, XNFD_MAGIC_ANY); + fd = rtdm_fd_get(ufd, 0); if (IS_ERR(fd)) return PTR_ERR(fd); @@ -625,11 +635,16 @@ static void destroy_fd(void *cookie, struct xnid *id) idx = container_of(id, struct rtdm_fd_index, id); xnlock_get_irqsave(&__rtdm_fd_lock, s); - __fd_close(p, idx, XNFD_MAGIC_ANY); + __fd_close(p, idx, 0); } void rtdm_fd_cleanup(struct xnsys_ppd *p) { + /* + * This is called on behalf of a (userland) task exit handler, + * so we don't have to deal with the regular file descriptors, + * we only have to empty our own index. + */ xntree_cleanup(&p->fds, p, destroy_fd); } diff --git a/kernel/cobalt/rtdm/init.c b/kernel/cobalt/rtdm/init.c deleted file mode 100644 index 50cb4ad..0000000 --- a/kernel/cobalt/rtdm/init.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Real-Time Driver Model for Xenomai - * - * Copyright (C) 2005, 2006 Jan Kiszka <jan.kis...@web.de> - * Copyright (C) 2005 Joerg Langenberg <joerg.langenb...@gmx.net> - * - * Xenomai is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Xenomai is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Xenomai; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include <linux/init.h> -#include <linux/module.h> -#include "rtdm/internal.h" - -/** - * @ingroup rtdm - * @defgroup rtdm_profiles Device Profiles - * - * Pre-defined classes of real-time devices - * - * Device profiles define which operation handlers a driver of a certain class - * has to implement, which name or protocol it has to register, which IOCTLs - * it has to provide, and further details. Sub-classes can be defined in order - * to extend a device profile with more hardware-specific functions. - */ - -void rtdm_cleanup(void) -{ - rtdm_proc_cleanup(); - rtdm_dev_cleanup(); -} - -int __init rtdm_init(void) -{ - int ret; - - ret = rtdm_dev_init(); - if (ret) - return ret; - - ret = rtdm_proc_init(); - if (ret) { - rtdm_dev_cleanup(); - return ret; - } - - return 0; -} diff --git a/kernel/cobalt/rtdm/internal.h b/kernel/cobalt/rtdm/internal.h index 016f567..e3ba70f 100644 --- a/kernel/cobalt/rtdm/internal.h +++ b/kernel/cobalt/rtdm/internal.h @@ -20,25 +20,17 @@ #ifndef _RTDM_INTERNAL_H #define _RTDM_INTERNAL_H +#include <linux/types.h> #include <linux/list.h> #include <linux/sem.h> -#include <linux/mutex.h> +#include <linux/file.h> #include <linux/atomic.h> -#include <cobalt/kernel/ppd.h> #include <cobalt/kernel/tree.h> +#include <cobalt/kernel/lock.h> #include <rtdm/driver.h> -#define RTDM_FD_MAX CONFIG_XENO_OPT_RTDM_FILDES - -#define DEF_DEVNAME_HASHTAB_SIZE 256 /* entries in name hash table */ -#define DEF_PROTO_HASHTAB_SIZE 256 /* entries in protocol hash table */ - -struct rtdm_fd; - -DECLARE_EXTERN_XNLOCK(rt_fildes_lock); DECLARE_EXTERN_XNLOCK(rt_dev_lock); -extern int open_fildes; extern struct semaphore nrt_dev_lock; extern struct list_head rtdm_named_devices; extern struct rb_root rtdm_protocol_devices; @@ -50,11 +42,6 @@ static inline void __rtdm_get_device(struct rtdm_device *device) void __rtdm_put_device(struct rtdm_device *device); -int __rtdm_dev_open(const char *path, int oflag); - -int __rtdm_dev_socket(int protocol_family, - int socket_type, int protocol); - struct rtdm_device *__rtdm_get_namedev(const char *path); struct rtdm_device *__rtdm_get_protodev(int protocol_family, @@ -65,8 +52,6 @@ void __rt_dev_close(struct rtdm_fd *fd); int __rt_dev_ioctl_fallback(struct rtdm_fd *fd, unsigned int request, void __user *arg); -void __rt_dev_unref(struct rtdm_fd *fd, unsigned int idx); - int __rtdm_mmap_from_fdop(struct rtdm_fd *fd, size_t len, off_t offset, int prot, int flags, void *__user *pptr); @@ -74,16 +59,6 @@ int rtdm_init(void); void rtdm_cleanup(void); -#ifdef CONFIG_XENO_OPT_VFILE -int rtdm_proc_init(void); -void rtdm_proc_cleanup(void); -#else -static inline int rtdm_proc_init(void) { return 0; } -static void inline rtdm_proc_cleanup(void) { } -#endif - -int __init rtdm_dev_init(void); - -void rtdm_dev_cleanup(void); +extern const struct file_operations rtdm_dumb_fops; #endif /* _RTDM_INTERNAL_H */ diff --git a/kernel/cobalt/rtdm/proc.c b/kernel/cobalt/rtdm/proc.c deleted file mode 100644 index fe635f3..0000000 --- a/kernel/cobalt/rtdm/proc.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2005 Jan Kiszka <jan.kis...@web.de>. - * Copyright (C) 2005 Joerg Langenberg <joerg.langenb...@gmx.net>. - * - * Xenomai is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Xenomai is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Xenomai; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include "rtdm/internal.h" -#include <cobalt/kernel/vfile.h> - -struct xnvfile_directory rtdm_vfroot; /* /proc/xenomai/rtdm */ - -struct vfile_device_data { - struct rtdm_device *curr; -}; - -static int get_nrt_lock(struct xnvfile *vfile) -{ - return down_interruptible(&nrt_dev_lock) ? -ERESTARTSYS : 0; -} - -static void put_nrt_lock(struct xnvfile *vfile) -{ - up(&nrt_dev_lock); -} - -static struct xnvfile_lock_ops lockops = { - .get = get_nrt_lock, - .put = put_nrt_lock, -}; - -static void *named_next(struct xnvfile_regular_iterator *it) -{ - struct vfile_device_data *priv = xnvfile_iterator_priv(it); - struct rtdm_device *device = priv->curr; - struct list_head *next; - - next = device->named.entry.next; - if (next == &rtdm_named_devices) { - priv->curr = NULL; /* all done. */ - goto out; - } - - priv->curr = list_entry(next, struct rtdm_device, named.entry); -out: - return priv->curr; -} - -static void *named_begin(struct xnvfile_regular_iterator *it) -{ - struct vfile_device_data *priv = xnvfile_iterator_priv(it); - struct rtdm_device *device; - loff_t pos = 0; - - list_for_each_entry(device, &rtdm_named_devices, named.entry) - if (pos++ >= it->pos) - break; - - if (&device->named.entry == &rtdm_named_devices) - return NULL; /* End of list. */ - - priv->curr = device; /* Skip head. */ - - if (pos == 1) - /* Output the header once, only if some device follows. */ - xnvfile_printf(it, "%-20s %s\n", "NODE", "CLASS"); - - return priv->curr; -} - -static int named_show(struct xnvfile_regular_iterator *it, void *data) -{ - struct rtdm_device *device = data; - - xnvfile_printf(it, "%-20s %s\n", - device->name, device->class->profile_info.name); - - return 0; -} - -static struct xnvfile_regular_ops named_vfile_ops = { - .begin = named_begin, - .next = named_next, - .show = named_show, -}; - -static struct xnvfile_regular named_vfile = { - .privsz = sizeof(struct vfile_device_data), - .ops = &named_vfile_ops, - .entry = { .lockops = &lockops } -}; - -struct vfile_proto_data { - struct rtdm_device *curr; -}; - -static void *proto_next(struct xnvfile_regular_iterator *it) -{ - struct vfile_proto_data *priv = xnvfile_iterator_priv(it); - - return priv->curr = xnid_next_entry(priv->curr, proto.id); -} - -static void *proto_begin(struct xnvfile_regular_iterator *it) -{ - - struct vfile_proto_data *priv = xnvfile_iterator_priv(it); - struct rtdm_device *dev = NULL; - loff_t pos = 0; - - xntree_for_each_entry(dev, &rtdm_protocol_devices, proto.id) - if (pos++ >= it->pos) - break; - - if (dev == NULL) - return NULL; /* Empty */ - - priv->curr = dev; - - if (pos == 1) - /* Output the header once, only if some device follows. */ - xnvfile_printf(it, "%-12s %s\n", "NODE", "CLASS"); - - return priv->curr; -} - -static int proto_show(struct xnvfile_regular_iterator *it, void *data) -{ - struct rtdm_device *device = data; - struct rtdm_device_class *class = device->class; - char pnum[32]; - - ksformat(pnum, sizeof(pnum), "%u:%u", - class->protocol_family, class->socket_type); - - xnvfile_printf(it, "%-12s %s\n", - pnum, class->profile_info.name); - return 0; -} - -static struct xnvfile_regular_ops proto_vfile_ops = { - .begin = proto_begin, - .next = proto_next, - .show = proto_show, -}; - -static struct xnvfile_regular proto_vfile = { - .privsz = sizeof(struct vfile_proto_data), - .ops = &proto_vfile_ops, - .entry = { .lockops = &lockops } -}; - -static void *openfd_begin(struct xnvfile_regular_iterator *it) -{ - if (it->pos == 0) - return VFILE_SEQ_START; - - return it->pos <= RTDM_FD_MAX ? it : NULL; -} - -static void *openfd_next(struct xnvfile_regular_iterator *it) -{ - if (it->pos > RTDM_FD_MAX) - return NULL; - - return it; -} - -static int openfd_show(struct xnvfile_regular_iterator *it, void *data) -{ - struct rtdm_dev_context *context; - int close_lock_count, i; - struct rtdm_fd *fd; - - if (data == NULL) { - xnvfile_puts(it, "Index\tLocked\tMinor\tDevice\n"); - return 0; - } - - i = (int)it->pos - 1; - - fd = rtdm_fd_get(i, RTDM_FD_MAGIC); - if (IS_ERR(fd)) - return VFILE_SEQ_SKIP; - - context = rtdm_fd_to_context(fd); - close_lock_count = fd->refs; - - xnvfile_printf(it, "%d\t%d\t%d\t%s\n", i, - close_lock_count, rtdm_fd_minor(fd), - context->device->name); - - rtdm_fd_put(fd); - - return 0; -} - -static ssize_t openfd_store(struct xnvfile_input *input) -{ - ssize_t ret, cret; - long val; - - ret = xnvfile_get_integer(input, &val); - if (ret < 0) - return ret; - - /* - * This ugly beast allows to force a close on a - * kernel-originated connection. - */ - cret = __rtdm_fd_close(&__xnsys_global_ppd, (int)val, RTDM_FD_MAGIC); - if (cret < 0) - return cret; - - return ret; -} - -static struct xnvfile_regular_ops openfd_vfile_ops = { - .begin = openfd_begin, - .next = openfd_next, - .show = openfd_show, - .store = openfd_store, -}; - -static struct xnvfile_regular openfd_vfile = { - .ops = &openfd_vfile_ops, - .entry = { .lockops = &lockops } -}; - -static int allfd_vfile_show(struct xnvfile_regular_iterator *it, void *data) -{ - xnvfile_printf(it, "total=%d:open=%d:free=%d\n", RTDM_FD_MAX, - open_fildes, RTDM_FD_MAX - open_fildes); - return 0; -} - -static struct xnvfile_regular_ops allfd_vfile_ops = { - .show = allfd_vfile_show, -}; - -static struct xnvfile_regular allfd_vfile = { - .ops = &allfd_vfile_ops, -}; - -int __init rtdm_proc_init(void) -{ - int ret; - - /* Initialise vfiles */ - ret = xnvfile_init_dir("rtdm", &rtdm_vfroot, &nkvfroot); - if (ret) - goto error; - - ret = xnvfile_init_regular("named_devices", &named_vfile, &rtdm_vfroot); - if (ret) - goto error; - - ret = xnvfile_init_regular("protocol_devices", &proto_vfile, &rtdm_vfroot); - if (ret) - goto error; - - ret = xnvfile_init_regular("open_fildes", &openfd_vfile, &rtdm_vfroot); - if (ret) - goto error; - - ret = xnvfile_init_regular("fildes", &allfd_vfile, &rtdm_vfroot); - if (ret) - goto error; - - return 0; - -error: - rtdm_proc_cleanup(); - return ret; -} - -void rtdm_proc_cleanup(void) -{ - xnvfile_destroy_regular(&allfd_vfile); - xnvfile_destroy_regular(&openfd_vfile); - xnvfile_destroy_regular(&proto_vfile); - xnvfile_destroy_regular(&named_vfile); - xnvfile_destroy_dir(&rtdm_vfroot); -} diff --git a/lib/cobalt/mq.c b/lib/cobalt/mq.c index 5b904b5..87b1b73 100644 --- a/lib/cobalt/mq.c +++ b/lib/cobalt/mq.c @@ -146,11 +146,12 @@ COBALT_IMPL(int, mq_close, (mqd_t mqd)) int err; err = XENOMAI_SYSCALL1(sc_cobalt_mq_close, mqd); - if (!err) - return __STD(close(mqd)); + if (err) { + errno = -err; + return -1; + } - errno = -err; - return -1; + return 0; } /** diff --git a/lib/cobalt/rtdm.c b/lib/cobalt/rtdm.c index b3310ef..f5432f7 100644 --- a/lib/cobalt/rtdm.c +++ b/lib/cobalt/rtdm.c @@ -92,16 +92,13 @@ COBALT_IMPL(int, close, (int fd)) pthread_setcanceltype(oldtype, NULL); - if (ret != -EBADF && ret != -ENOSYS) { - if (ret == 0) - __STD(close(fd)); + if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); - } return __STD(close(fd)); } -static int __xn_ioctl(int fd, unsigned long request, void *arg) +static int do_ioctl(int fd, unsigned long request, void *arg) { int ret, oldtype; @@ -124,7 +121,7 @@ COBALT_IMPL(int, ioctl, (int fd, unsigned long int request, ...)) arg = va_arg(ap, void *); va_end(ap); - ret = __xn_ioctl(fd, request, arg); + ret = do_ioctl(fd, request, arg); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -163,7 +160,7 @@ COBALT_IMPL(ssize_t, write, (int fd, const void *buf, size_t nbyte)) return __STD(write(fd, buf, nbyte)); } -static ssize_t __xn_recvmsg(int fd, struct msghdr *msg, int flags) +static ssize_t do_recvmsg(int fd, struct msghdr *msg, int flags) { int ret, oldtype; @@ -180,14 +177,14 @@ COBALT_IMPL(ssize_t, recvmsg, (int fd, struct msghdr *msg, int flags)) { int ret; - ret = __xn_recvmsg(fd, msg, flags); + ret = do_recvmsg(fd, msg, flags); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); return __STD(recvmsg(fd, msg, flags)); } -static ssize_t __xn_sendmsg(int fd, const struct msghdr *msg, int flags) +static ssize_t do_sendmsg(int fd, const struct msghdr *msg, int flags) { int ret, oldtype; @@ -204,7 +201,7 @@ COBALT_IMPL(ssize_t, sendmsg, (int fd, const struct msghdr *msg, int flags)) { int ret; - ret = __xn_sendmsg(fd, msg, flags); + ret = do_sendmsg(fd, msg, flags); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -219,7 +216,7 @@ COBALT_IMPL(ssize_t, recvfrom, (int fd, void *buf, size_t len, int flags, { from, (from != NULL) ? *fromlen : 0, &iov, 1, NULL, 0 }; int ret; - ret = __xn_recvmsg(fd, &msg, flags); + ret = do_recvmsg(fd, &msg, flags); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -234,7 +231,7 @@ COBALT_IMPL(ssize_t, sendto, (int fd, const void *buf, size_t len, int flags, { (struct sockaddr *)to, tolen, &iov, 1, NULL, 0 }; int ret; - ret = __xn_sendmsg(fd, &msg, flags); + ret = do_sendmsg(fd, &msg, flags); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -247,7 +244,7 @@ COBALT_IMPL(ssize_t, recv, (int fd, void *buf, size_t len, int flags)) struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0 }; int ret; - ret = __xn_recvmsg(fd, &msg, flags); + ret = do_recvmsg(fd, &msg, flags); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -260,7 +257,7 @@ COBALT_IMPL(ssize_t, send, (int fd, const void *buf, size_t len, int flags)) struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0 }; int ret; - ret = __xn_sendmsg(fd, &msg, flags); + ret = do_sendmsg(fd, &msg, flags); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -273,7 +270,7 @@ COBALT_IMPL(int, getsockopt, (int fd, int level, int optname, void *optval, struct _rtdm_getsockopt_args args = { level, optname, optval, optlen }; int ret; - ret = __xn_ioctl(fd, _RTIOC_GETSOCKOPT, &args); + ret = do_ioctl(fd, _RTIOC_GETSOCKOPT, &args); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -288,7 +285,7 @@ COBALT_IMPL(int, setsockopt, (int fd, int level, int optname, const void *optval }; int ret; - ret = __xn_ioctl(fd, _RTIOC_SETSOCKOPT, &args); + ret = do_ioctl(fd, _RTIOC_SETSOCKOPT, &args); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -300,7 +297,7 @@ COBALT_IMPL(int, bind, (int fd, const struct sockaddr *my_addr, socklen_t addrle struct _rtdm_setsockaddr_args args = { my_addr, addrlen }; int ret; - ret = __xn_ioctl(fd, _RTIOC_BIND, &args); + ret = do_ioctl(fd, _RTIOC_BIND, &args); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -312,7 +309,7 @@ COBALT_IMPL(int, connect, (int fd, const struct sockaddr *serv_addr, socklen_t a struct _rtdm_setsockaddr_args args = { serv_addr, addrlen }; int ret; - ret = __xn_ioctl(fd, _RTIOC_CONNECT, &args); + ret = do_ioctl(fd, _RTIOC_CONNECT, &args); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -323,7 +320,7 @@ COBALT_IMPL(int, listen, (int fd, int backlog)) { int ret; - ret = __xn_ioctl(fd, _RTIOC_LISTEN, (void *)(long)backlog); + ret = do_ioctl(fd, _RTIOC_LISTEN, (void *)(long)backlog); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -335,7 +332,7 @@ COBALT_IMPL(int, accept, (int fd, struct sockaddr *addr, socklen_t *addrlen)) struct _rtdm_getsockaddr_args args = { addr, addrlen }; int ret; - ret = __xn_ioctl(fd, _RTIOC_ACCEPT, &args); + ret = do_ioctl(fd, _RTIOC_ACCEPT, &args); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -347,7 +344,7 @@ COBALT_IMPL(int, getsockname, (int fd, struct sockaddr *name, socklen_t *namelen struct _rtdm_getsockaddr_args args = { name, namelen }; int ret; - ret = __xn_ioctl(fd, _RTIOC_GETSOCKNAME, &args); + ret = do_ioctl(fd, _RTIOC_GETSOCKNAME, &args); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -359,7 +356,7 @@ COBALT_IMPL(int, getpeername, (int fd, struct sockaddr *name, socklen_t *namelen struct _rtdm_getsockaddr_args args = { name, namelen }; int ret; - ret = __xn_ioctl(fd, _RTIOC_GETPEERNAME, &args); + ret = do_ioctl(fd, _RTIOC_GETPEERNAME, &args); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); @@ -370,7 +367,7 @@ COBALT_IMPL(int, shutdown, (int fd, int how)) { int ret; - ret = __xn_ioctl(fd, _RTIOC_SHUTDOWN, (void *)(long)how); + ret = do_ioctl(fd, _RTIOC_SHUTDOWN, (void *)(long)how); if (ret != -EBADF && ret != -ENOSYS) return set_errno(ret); _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git