drvlib.c

来自「xenomai 很好的linux实时补丁」· C语言 代码 · 共 1,740 行 · 第 1/3 页

C
1,740
字号
 * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: possible. */void rtdm_event_signal(rtdm_event_t *event){    spl_t s;    xnlock_get_irqsave(&nklock, s);    __set_bit(0, &event->pending);    if (xnsynch_flush(&event->synch_base, 0))        xnpod_schedule();    xnlock_put_irqrestore(&nklock, s);}EXPORT_SYMBOL(rtdm_event_signal);/** * @brief Wait on event occurrence * * This is the light-weight version of rtdm_event_timedwait(), implying an * infinite timeout. * * @param[in,out] event Event handle as returned by rtdm_event_init() * * @return 0 on success, otherwise: * * - -EINTR is returned if calling task has been unblock by a signal or * explicitely via rtdm_task_unblock(). * * - -EIDRM is returned if @a event has been destroyed. * * Environments: * * This service can be called from: * * - Kernel-based task * - User-space task (RT) * * Rescheduling: possible. */int rtdm_event_wait(rtdm_event_t *event){    spl_t   s;    int     err = 0;    xnlock_get_irqsave(&nklock, s);    if (testbits(event->synch_base.status, SYNCH_DELETED))        err = -EIDRM;    else if (!__test_and_clear_bit(0, &event->pending)) {        xnthread_t  *thread = xnpod_current_thread();        xnsynch_sleep_on(&event->synch_base, XN_INFINITE);        if (!xnthread_test_flags(thread, XNRMID|XNBREAK))            __clear_bit(0, &event->pending);        else if (xnthread_test_flags(thread, XNRMID))            err = -EIDRM;        else /* XNBREAK */            err = -EINTR;    }    xnlock_put_irqrestore(&nklock, s);    return err;}EXPORT_SYMBOL(rtdm_event_wait);/** * @brief Wait on event occurrence with timeout * * This function waits or tests for the occurence of the given event, taking * the provided timeout into account. On successful return, the event is * reset. * * @param[in,out] event Event handle as returned by rtdm_event_init() * @param[in] timeout Relative timeout in nanoseconds, 0 for infinite, or any * negative value for non-blocking (test for event occurrence) * @param[in,out] timeout_seq Handle of a timeout sequence as returned by * rtdm_toseq_init() or rtdm_toseq_absinit(), or NULL * * @return 0 on success, otherwise: * * - -ETIMEDOUT is returned if the if the request has not been satisfied * within the specified amount of time. * * - -EINTR is returned if calling task has been unblock by a signal or * explicitely via rtdm_task_unblock(). * * - -EIDRM is returned if @a event has been destroyed. * * Environments: * * This service can be called from: * * - Kernel-based task * - User-space task (RT) * * Rescheduling: possible. */int rtdm_event_timedwait(rtdm_event_t *event, int64_t timeout,                         rtdm_toseq_t *timeout_seq){    xnthread_t  *thread;    spl_t       s;    int         err = 0;    xnlock_get_irqsave(&nklock, s);    if (unlikely(testbits(event->synch_base.status, SYNCH_DELETED)))        err = -EIDRM;    else if (!__test_and_clear_bit(0, &event->pending)) {        /* non-blocking mode */        if (unlikely(timeout < 0)) {            err = -EWOULDBLOCK;            goto unlock_out;        }        /* timeout sequence */        if (timeout_seq && (timeout > 0)) {            timeout = *timeout_seq - xnpod_get_time();            if (unlikely(timeout <= 0)) {                err = -ETIMEDOUT;                goto unlock_out;            }            xnsynch_sleep_on(&event->synch_base, timeout);        }        /* infinite or relative timeout */        else            xnsynch_sleep_on(&event->synch_base, xnpod_ns2ticks(timeout));        thread = xnpod_current_thread();        if (!xnthread_test_flags(thread, XNTIMEO|XNRMID|XNBREAK))            __clear_bit(0, &event->pending);        else if (xnthread_test_flags(thread, XNTIMEO))            err = -ETIMEDOUT;        else if (xnthread_test_flags(thread, XNRMID))            err = -EIDRM;        else /* XNBREAK */            err = -EINTR;    } unlock_out:    xnlock_put_irqrestore(&nklock, s);    return err;}EXPORT_SYMBOL(rtdm_event_timedwait);/** @} *//*! * @name Semaphore Services * @{ */#ifdef DOXYGEN_CPP /* Only used for doxygen doc generation *//** * @brief Initialise a semaphore * * @param[in,out] sem Semaphore handle * @param[in] value Initial value of the semaphore * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */void rtdm_sem_init(rtdm_sem_t *sem, unsigned long value);/** * @brief Destroy a semaphore * * @param[in,out] sem Semaphore handle as returned by rtdm_sem_init() * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: possible. */void rtdm_sem_destroy(rtdm_sem_t *sem);#endif /* DOXYGEN_CPP *//** * @brief Decrement a semaphore * * This is the light-weight version of rtdm_sem_timeddown(), implying an * infinite timeout. * * @param[in,out] sem Semaphore handle as returned by rtdm_sem_init() * * @return 0 on success, otherwise: * * - -EINTR is returned if calling task has been unblock by a signal or * explicitely via rtdm_task_unblock(). * * - -EIDRM is returned if @a sem has been destroyed. * * Environments: * * This service can be called from: * * - Kernel-based task * - User-space task (RT) * * Rescheduling: possible. */int rtdm_sem_down(rtdm_sem_t *sem){    spl_t   s;    int     err = 0;    xnlock_get_irqsave(&nklock, s);    if (testbits(sem->synch_base.status, SYNCH_DELETED))        err = -EIDRM;    else if (sem->value > 0)        sem->value--;    else {        xnthread_t  *thread = xnpod_current_thread();        xnsynch_sleep_on(&sem->synch_base, XN_INFINITE);        if (xnthread_test_flags(thread, XNRMID|XNBREAK)) {            if (xnthread_test_flags(thread, XNRMID))                err = -EIDRM;            else /*  XNBREAK */                err = -EINTR;        }    }    xnlock_put_irqrestore(&nklock, s);    return err;}EXPORT_SYMBOL(rtdm_sem_down);/** * @brief Decrement a semaphore with timeout * * This function tries to decrement the given semphore's value if it is * positive on entry. If not, the caller is blocked unless non-blocking * operation was selected. * * @param[in,out] sem Semaphore handle as returned by rtdm_sem_init() * @param[in] timeout Relative timeout in nanoseconds, 0 for infinite, or any * negative value for non-blocking operation * @param[in,out] timeout_seq Handle of a timeout sequence as returned by * rtdm_toseq_init() or rtdm_toseq_absinit(), or NULL * * @return 0 on success, otherwise: * * - -ETIMEDOUT is returned if the if the request has not been satisfied * within the specified amount of time. * * - -EWOULDBLOCK is returned if @a timeout is negative and the semaphore * value is currently not positive. * * - -EINTR is returned if calling task has been unblock by a signal or * explicitely via rtdm_task_unblock(). * * - -EIDRM is returned if @a sem has been destroyed. * * Environments: * * This service can be called from: * * - Kernel-based task * - User-space task (RT) * * Rescheduling: possible. */int rtdm_sem_timeddown(rtdm_sem_t *sem, int64_t timeout,                       rtdm_toseq_t *timeout_seq){    xnthread_t  *thread;    spl_t       s;    int         err = 0;    xnlock_get_irqsave(&nklock, s);    if (testbits(sem->synch_base.status, SYNCH_DELETED))        err = -EIDRM;    else if (sem->value > 0)        sem->value--;    else if (timeout < 0)   /* non-blocking mode */        err = -EWOULDBLOCK;    else {        /* timeout sequence */        if (timeout_seq && (timeout > 0)) {            timeout = *timeout_seq - xnpod_get_time();            if (unlikely(timeout <= 0)) {                err = -ETIMEDOUT;                goto unlock_out;            }            xnsynch_sleep_on(&sem->synch_base, timeout);        }        /* infinite or relative timeout */        else            xnsynch_sleep_on(&sem->synch_base, xnpod_ns2ticks(timeout));        thread = xnpod_current_thread();        if (xnthread_test_flags(thread, XNTIMEO|XNRMID|XNBREAK)) {            if (xnthread_test_flags(thread, XNTIMEO))                err = -ETIMEDOUT;            else if (xnthread_test_flags(thread, XNRMID))                err = -EIDRM;            else /*  XNBREAK */                err = -EINTR;        }    } unlock_out:    xnlock_put_irqrestore(&nklock, s);    return err;}EXPORT_SYMBOL(rtdm_sem_timeddown);/** * @brief Increment a semaphore * * This function increments the given semphore's value, waking up a potential * waiter which was blocked upon rtdm_sem_down(). * * @param[in,out] sem Semaphore handle as returned by rtdm_sem_init() * * 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: possible. */void rtdm_sem_up(rtdm_sem_t *sem){    spl_t s;    xnlock_get_irqsave(&nklock, s);    if (xnsynch_wakeup_one_sleeper(&sem->synch_base))        xnpod_schedule();    else        sem->value++;    xnlock_put_irqrestore(&nklock, s);}EXPORT_SYMBOL(rtdm_sem_up);/** @} *//*! * @name Mutex Services * @{ */#ifdef DOXYGEN_CPP /* Only used for doxygen doc generation *//** * @brief Initialise a mutex * * This function initalises a basic mutex with priority inversion protection. * "Basic", as it does not allow a mutex owner to recursively lock the same * mutex again. * * @param[in,out] mutex Mutex handle * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: never. */void rtdm_mutex_init(rtdm_mutex_t *mutex);/** * @brief Destroy a mutex * * @param[in,out] mutex Mutex handle as returned by rtdm_mutex_init() * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task (RT, non-RT) * * Rescheduling: possible. */void rtdm_mutex_destroy(rtdm_mutex_t *mutex);#endif /* DOXYGEN_CPP *//** * @brief Request a mutex * * This is the light-weight version of rtdm_mutex_timedlock(), implying an * infinite timeout. * * @param[in,out] mutex Mutex handle as returned by rtdm_mutex_init() * * @return 0 on success, otherwise: * * - -EIDRM is returned if @a mutex has been destroyed. * * Environments: * * This service can be called from: * * - Kernel-based task * - User-space task (RT) * * Rescheduling: possible. */int rtdm_mutex_lock(rtdm_mutex_t *mutex){    spl_t   s;    int     err = 0;    xnlock_get_irqsave(&nklock, s);    if (testbits(mutex->synch_base.status, SYNCH_DELETED))        err = -EIDRM;    else        while (__test_and_set_bit(0, &mutex->locked)) {            xnsynch_sleep_on(&mutex->synch_base, XN_INFINITE);            if (xnthread_test_flags(xnpod_current_thread(), XNRMID)) {                err = -EIDRM;                break;            }        }    xnlock_put_irqrestore(&nklock, s);    return err;}EXPORT_SYMBOL(rtdm_mutex_lock);/** * @brief Request a mutex with timeout * * This function tries to acquire the given mutex. If it is not available, the * caller is blocked unless non-blocking operation was selected. * * @param[in,out] mutex Mutex handle as returned by rtdm_mutex_init() * @param[in] timeout Relative timeout in nanoseconds, 0 for infinite, or any * negative value for non-blocking operation * @param[in,out] timeout_seq Handle of a timeout sequence as returned by * rtdm_toseq_init() or rtdm_toseq_absinit(), or NULL * * @return 0 on success, otherwise: * * - -ETIMEDOUT is returned if the if the request has not been satisfied * within the specified amount of time. * * - -EWOULDBLOCK is returned if @a timeout is negative and the semaphore * value is currently not positive. * * - -EINTR is returned if calling task has been unblock by a signal or * explicitely via rtdm_task_unblock(). * * - -EIDRM is returned if @a mutex has been destroyed. * * Environments: * * This service can be called from: * * - Kernel-based task * - User-space task (RT) * * Rescheduling: possible. */int rtdm_mutex_timedlock(rtdm_mutex_t *mutex, int64_t timeout,                         rtdm_toseq_t *timeout_seq){    xnthread_t  *thread;    spl_t       s;    int         err = 0;    xnlock_get_irqsave(&nklock, s);    if (testbits(mutex->synch_base.status, SYNCH_DELETED))        err = -EIDRM;    else        while (__test_and_set_bit(0, &mutex->locked)) {            /* non-blocking mode */            if (timeout < 0) {                err = -EWOULDBLOCK;                break;            }            /* timeout sequence */            if (timeout_seq && (timeout > 0)) {                timeout = *timeout_seq - xnpod_get_time();                if (unlikely(timeout <= 0)) {                    err = -ETIMEDOUT;                    break;                }                xnsynch_sleep_on(&mutex->synch_base, timeout);            }            /* infinite or relative timeout */            else                xnsynch_sleep_on(&mutex->synch_base, xnpod_ns2ticks(timeout));            thread = xnpod_current_thread();            if (xnthread_test_flags(thread, XNTIMEO|XNRMID)) {                if (xnthread_test_flags(thread, XNTIMEO))                    err = -ETIMEDOUT;                else /*  XNRMID */                    err = -EIDRM;                break;            }        }    xnlock_put_irqrestore(&nklock, s);    return err;}EXPORT_SYMBOL(rtdm_mutex_timedlock);/** * @brief Release a mutex * * This function releases the given mutex, waking up a potential waiter which * was blocked upon rtdm_mutex_lock() or rtdm_mutex_timedlock(). * * @param[in,out] mutex Mutex handle as returned by rtdm_mutex_init()

⌨️ 快捷键说明

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