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 + -
显示快捷键?