⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 core.c

📁 xenomai 很好的linux实时补丁
💻 C
📖 第 1 页 / 共 3 页
字号:
/** * @file * Real-Time Driver Model for Xenomai, device operation multiplexing * * @note Copyright (C) 2005 Jan Kiszka <jan.kiszka@web.de> * @note Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@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. *//*! * @ingroup driverapi * @defgroup interdrv Inter-Driver API * @{ */#include <linux/module.h>#include <nucleus/pod.h>#include <nucleus/heap.h>#include <rtdm/syscall.h>#include <rtdm/rtdm_driver.h>#include "rtdm/core.h"#include "rtdm/device.h"unsigned int                fd_count = DEF_FILDES_COUNT;module_param(fd_count, uint, 0400);MODULE_PARM_DESC(fd_count, "Maximum number of file descriptors");struct rtdm_fildes          *fildes_table;  /* allocated on init */static struct rtdm_fildes   *free_fildes;   /* chain of free descriptors */int                         open_fildes;    /* number of used descriptors */#ifdef CONFIG_SMPxnlock_t                    rt_fildes_lock = XNARCH_LOCK_UNLOCKED;#endif /* !CONFIG_SMP */static inline int get_fd(struct rtdm_fildes *fildes){    return (fildes - fildes_table);}/** * @brief Resolve file descriptor to device context * * @param[in] fd File descriptor * * @return Pointer to associated device context, or NULL on error * * @note The device context has to be unlocked using rtdm_context_unlock() * when it is no longer referenced. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */struct rtdm_dev_context *rtdm_context_get(int fd){    struct rtdm_fildes      *fildes;    struct rtdm_dev_context *context;    spl_t                   s;    if ((unsigned int)fd >= fd_count)        return NULL;    fildes = &fildes_table[fd];    xnlock_get_irqsave(&rt_fildes_lock, s);    context = (struct rtdm_dev_context *)fildes->context;    if (unlikely(!context ||                 test_bit(RTDM_CLOSING, &context->context_flags))) {        xnlock_put_irqrestore(&rt_fildes_lock, s);        return NULL;    }    rtdm_context_lock(context);    xnlock_put_irqrestore(&rt_fildes_lock, s);    return context;}static int create_instance(struct rtdm_device *device,                           struct rtdm_dev_context **context_ptr,                           struct rtdm_fildes **fildes_ptr,                           int nrt_mem){    struct rtdm_fildes      *fildes;    struct rtdm_dev_context *context;    spl_t                   s;    *context_ptr = NULL;    xnlock_get_irqsave(&rt_fildes_lock, s);    *fildes_ptr = fildes = free_fildes;    if (unlikely(!fildes)) {        xnlock_put_irqrestore(&rt_fildes_lock, s);        return -ENFILE;    }    free_fildes = fildes->next;    open_fildes++;    xnlock_put_irqrestore(&rt_fildes_lock, s);    context = device->reserved.exclusive_context;    if (context) {        xnlock_get_irqsave(&rt_dev_lock, s);        if (unlikely(context->device != NULL)) {            xnlock_put_irqrestore(&rt_dev_lock, s);            return -EBUSY;        }        context->device = device;        xnlock_put_irqrestore(&rt_dev_lock, s);    } else {        if (nrt_mem)            context = kmalloc(sizeof(struct rtdm_dev_context) +                              device->context_size, GFP_KERNEL);        else            context = xnmalloc(sizeof(struct rtdm_dev_context) +                               device->context_size);        if (unlikely(!context))            return -ENOMEM;        context->device = device;    }    *context_ptr = context;    context->fd  = get_fd(fildes);    context->ops = &device->ops;    atomic_set(&context->close_lock_count, 0);    return 0;}/* call with rt_fildes_lock acquired - will release it */static void cleanup_instance(struct rtdm_device *device,                             struct rtdm_dev_context *context,                             struct rtdm_fildes *fildes,                             int nrt_mem,                             spl_t *s){    if (fildes) {        fildes->next = free_fildes;        free_fildes = fildes;        open_fildes--;        fildes->context = NULL;    }    xnlock_put_irqrestore(&rt_fildes_lock, *s);    if (context) {        if (device->reserved.exclusive_context)            context->device = NULL;        else {            if (nrt_mem)                kfree(context);            else                xnfree(context);        }    }    rtdm_dereference_device(device);}int _rtdm_open(rtdm_user_info_t *user_info, const char *path, int oflag){    struct rtdm_device      *device;    struct rtdm_fildes      *fildes;    struct rtdm_dev_context *context;    spl_t                   s;    int                     ret;    int                     nrt_mode = !rtdm_in_rt_context();    device = get_named_device(path);    ret = -ENODEV;    if (!device)        goto err_out;    ret = create_instance(device, &context, &fildes, nrt_mode);    if (ret != 0)        goto cleanup_out;    if (nrt_mode) {        context->context_flags = (1 << RTDM_CREATED_IN_NRT);        ret = device->open_nrt(context, user_info, oflag);    } else {        context->context_flags = 0;        ret = device->open_rt(context, user_info, oflag);    }    if (unlikely(ret < 0))        goto cleanup_out;    fildes->context = context;    return context->fd; cleanup_out:    xnlock_get_irqsave(&rt_fildes_lock, s);    cleanup_instance(device, context, fildes, nrt_mode, &s); err_out:    return ret;}int _rtdm_socket(rtdm_user_info_t *user_info, int protocol_family,                 int socket_type, int protocol){    struct rtdm_device      *device;    struct rtdm_fildes      *fildes;    struct rtdm_dev_context *context;    spl_t                   s;    int                     ret;    int                     nrt_mode = !rtdm_in_rt_context();    device = get_protocol_device(protocol_family, socket_type);    ret = -EAFNOSUPPORT;    if (!device)        goto err_out;    ret = create_instance(device, &context, &fildes, nrt_mode);    if (ret != 0)        goto cleanup_out;    if (nrt_mode) {        context->context_flags = (1 << RTDM_CREATED_IN_NRT);        ret = device->socket_nrt(context, user_info, protocol);    } else {        context->context_flags = 0;        ret = device->socket_rt(context, user_info, protocol);    }    if (unlikely(ret < 0))        goto cleanup_out;    fildes->context = context;    return context->fd; cleanup_out:    xnlock_get_irqsave(&rt_fildes_lock, s);    cleanup_instance(device, context, fildes, nrt_mode, &s); err_out:    return ret;}int _rtdm_close(rtdm_user_info_t *user_info, int fd, int forced){    struct rtdm_fildes      *fildes;    struct rtdm_dev_context *context;    spl_t                   s;    int                     ret;    ret = -EBADF;    if (unlikely((unsigned int)fd >= fd_count))        goto err_out;    fildes = &fildes_table[fd];    xnlock_get_irqsave(&rt_fildes_lock, s);    context = (struct rtdm_dev_context *)fildes->context;    if (unlikely(!context)) {        xnlock_put_irqrestore(&rt_fildes_lock, s);        goto err_out;   /* -EBADF */    }    set_bit(RTDM_CLOSING, &context->context_flags);    if (forced)        set_bit(RTDM_FORCED_CLOSING, &context->context_flags);    rtdm_context_lock(context);    xnlock_put_irqrestore(&rt_fildes_lock, s);    if (rtdm_in_rt_context()) {        ret = -ENOTSUPP;        /* Warn about asymmetric open/close, but only if there is really a           close_rt handler. Otherwise, we will be switched to nrt           automatically. */        if (unlikely(test_bit(RTDM_CREATED_IN_NRT, &context->context_flags) &&                     (context->ops->close_rt !=                         (rtdm_close_handler_t)rtdm_no_support))) {            xnprintf("RTDM: closing device in real-time mode while creation "                     "ran in non-real-time - this is not supported!\n");            goto unlock_out;        }        ret = context->ops->close_rt(context, user_info);    } else        ret = context->ops->close_nrt(context, user_info);    if (unlikely(ret < 0))        goto unlock_out;    xnlock_get_irqsave(&rt_fildes_lock, s);    if (unlikely((atomic_read(&context->close_lock_count) > 1) && !forced)) {        xnlock_put_irqrestore(&rt_fildes_lock, s);        ret = -EAGAIN;        goto unlock_out;    }    fildes->context = NULL;    cleanup_instance((struct rtdm_device *)context->device, context,        fildes, test_bit(RTDM_CREATED_IN_NRT, &context->context_flags), &s);    return ret;  unlock_out:    rtdm_context_unlock(context);  err_out:    return ret;}#define MAJOR_FUNCTION_WRAPPER(operation, args...)                          \{                                                                           \    struct rtdm_dev_context *context;                                       \    struct rtdm_operations  *ops;                                           \    int                     ret;                                            \                                                                            \                                                                            \    context = rtdm_context_get(fd);                                         \    ret = -EBADF;                                                           \    if (unlikely(!context))                                                 \        goto err_out;                                                       \                                                                            \    ops = context->ops;                                                     \                                                                            \    if (rtdm_in_rt_context())                                               \        ret = ops->operation##_rt(context, user_info, args);                \    else                                                                    \        ret = ops->operation##_nrt(context, user_info, args);               \                                                                            \    rtdm_context_unlock(context);                                           \                                                                            \ err_out:                                                                   \    return ret;                                                             \}int _rtdm_ioctl(rtdm_user_info_t *user_info, int fd, int request, ...){    va_list args;    void    *arg;    va_start(args, request);    arg = va_arg(args, void *);    va_end(args);    MAJOR_FUNCTION_WRAPPER(ioctl, request, arg);}ssize_t _rtdm_read(rtdm_user_info_t *user_info, int fd, void *buf, size_t nbyte){    MAJOR_FUNCTION_WRAPPER(read, buf, nbyte);}ssize_t _rtdm_write(rtdm_user_info_t *user_info, int fd, const void *buf,                size_t nbyte){    MAJOR_FUNCTION_WRAPPER(write, buf, nbyte);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -