📄 sem.c
字号:
if (spl->owndby == (rt_current = RT_CURRENT)) { spl->count++; } else { if (atomic_cmpxchg(&spl->owndby, 0, rt_current)) { hard_restore_flags(flags); return -1; } spl->flags = flags; } return 0;}/** * @anchor rt_spl_lock_timed * @brief Acquire a spinlock with timeout. * * rt_spl_lock_timed acquires a spinlock @spl, but waiting spinning only * for an allowed time. * * @param spl must point to an allocated @e SPL structure. * * rt_spl_lock spins on lock till it can be acquired, as for rt_spl_lock, * but only for an allowed time. If the spinlock cannot be acquired in time * the functions returns in error. * This function can be usefull either in itself or as a diagnosis toll * during code development. * * @returns 0 if the spinlock was acquired, -1 if a timeout occured. * */int rt_spl_lock_timed(SPL *spl, unsigned long ns){ unsigned long flags; RT_TASK *rt_current; hard_save_flags_and_cli(flags); if (spl->owndby == (rt_current = RT_CURRENT)) { spl->count++; } else { RTIME end_time; void *locked; end_time = rdtsc() + imuldiv(ns, tuned.cpu_freq, 1000000000); while ((locked = atomic_cmpxchg(&spl->owndby, 0, rt_current)) && rdtsc() < end_time); if (locked) { hard_restore_flags(flags); return -1; } spl->flags = flags; } return 0;}/** * @anchor rt_spl_unlock * @brief Release an owned spinlock. * * rt_spl_lock releases an owned spinlock @spl. * * @param spl must point to an allocated @e SPL structure. * * rt_spl_unlock releases an owned lock. The spinlock can remain locked and * its ownership can remain with the task is the spinlock acquisition was * recursed. * * @returns 0 if the function was used legally, -1 if a tasks tries to unlock * a spinlock it does not own. * */int rt_spl_unlock(SPL *spl){ unsigned long flags; RT_TASK *rt_current; hard_save_flags_and_cli(flags); if (spl->owndby == (rt_current = RT_CURRENT)) { if (spl->count) { --spl->count; } else { spl->owndby = 0; spl->count = 0; hard_restore_flags(spl->flags); } return 0; } hard_restore_flags(flags); return -1;}/* ++++++ NAMED SEMAPHORES, BARRIER, COND VARIABLES, RWLOCKS, SPINLOCKS +++++ */#include <rtai_registry.h>/** * @anchor _rt_typed_named_sem_init * @brief Initialize a specifically typed (counting, binary, resource) * semaphore identified by a name. * * _rt_typed_named_sem_init allocate and initializes a semaphore identified * by @e name of type @e type. Once the semaphore structure is allocated the * initialization is as for rt_typed_sem_init. The function returns the * handle pointing to the allocated semaphore structure, to be used as the * usual semaphore address in all semaphore based services. Named objects * are useful for use among different processes, kernel/user space and * in distributed applications, see netrpc. * * @param sem must point to an allocated SEM structure. * * @param value is the initial value of the semaphore, always set to 1 * for a resource semaphore. * * @param type is the semaphore type and queuing policy. It can be an OR * a semaphore kind: CNT_SEM for counting semaphores, BIN_SEM for binary * semaphores, RES_SEM for resource semaphores; and queuing policy: * FIFO_Q, PRIO_Q for a fifo and priority queueing respectively. * Resource semaphores will enforce a PRIO_Q policy anyhow. * * Since @a name can be a clumsy identifier, services are provided to * convert 6 characters identifiers to unsigned long, and vice versa. * * @see nam2num() and num2nam(). * * See rt_typed_sem_init for further clues. * * As for all the named initialization functions it must be remarked that * only the very first call to initilize/create a named RTAI object does a * real allocation of the object, any following call with the same name * will just increase its usage count. In any case the function returns * a pointer to the named object, or zero if in error. * * @returns either a valid pointer or 0 if in error. * */SEM *_rt_typed_named_sem_init(unsigned long sem_name, int value, int type){ SEM *sem; if ((sem = rt_get_adr_cnt(sem_name))) { return sem; } if ((sem = rt_malloc(sizeof(SEM)))) { rt_typed_sem_init(sem, value, type); if (rt_register(sem_name, sem, IS_SEM, 0)) { return sem; } rt_sem_delete(sem); } rt_free(sem); return (SEM *)0;}/** * @anchor rt_named_sem_delete * @brief Delete a semaphore initialized in named mode. * * rt_named_sem_delete deletes a semaphore previously created with * @ref _rt_typed_named_sem_init(). * * @param sem points to the structure pointer returned by a corresponding * call to _rt_typed_named_sem_init. * * Any tasks blocked on this semaphore is returned in error and * allowed to run when semaphore is destroyed. * As it is done by all the named allocation functions delete calls have just * the effect of decrementing a usage count till the last is done, as that is * the one the really frees the object. * * @return an int >=0 is returned upon success, SEM_ERR if it failed to * delete the semafore, -EFAULT if the semaphore does not exist anymore. * */int rt_named_sem_delete(SEM *sem){ int ret; if (!(ret = rt_drg_on_adr_cnt(sem))) { if (!rt_sem_delete(sem)) { rt_free(sem); return 0; } else { return SEM_ERR; } } return ret;}/** * @anchor _rt_named_rwl_init * @brief Initialize a multi readers single writer lock identified by a name. * * _rt_named_rwl_init allocate and initializes a multi readers single writer * lock (RWL) identified by @e name. Once the lock structure is allocated the * initialization is as for rt_rwl_init. The function returns the * handle pointing to the allocated multi readers single writer lock o * structure, to be used as the usual lock address in all rwl based services. * Named objects are useful for use among different processes, kernel/user * space and in distributed applications, see netrpc. * * @param rwl must point to an allocated @e RWL structure. * * Since @a name can be a clumsy identifier, services are provided to * convert 6 characters identifiers to unsigned long, and vice versa. * * @see nam2num() and num2nam(). * * As for all the named initialization functions it must be remarked that * only the very first call to initilize/create a named RTAI object does a * real allocation of the object, any following call with the same name * will just increase its usage count. In any case the function returns * a pointer to the named object, or zero if in error. * * @returns either a valid pointer or 0 if in error. * */RWL *_rt_named_rwl_init(unsigned long rwl_name){ RWL *rwl; if ((rwl = rt_get_adr_cnt(rwl_name))) { return rwl; } if ((rwl = rt_malloc(sizeof(RWL)))) { rt_rwl_init(rwl); if (rt_register(rwl_name, rwl, IS_RWL, 0)) { return rwl; } rt_rwl_delete(rwl); } rt_free(rwl); return (RWL *)0;}/** * @anchor rt_named_rwl_delete * @brief Delete a multi readers single writer lock in named mode. * * rt_named_rwl_delete deletes a multi readers single writer lock * previously created with @ref rt_named_rwl_init(). * * @param rwl points to the structure pointer returned by a corresponding * call to rt_named_rwl_init. * * As it is done by all the named allocation functions delete calls have just * the effect of decrementing a usage count till the last is done, as that is * the one the really frees the object. * * @return an int >=0 is returned upon success, SEM_ERR if it failed to * delete the multi readers single writer lock, -EFAULT if the lock does * not exist anymore. * */int rt_named_rwl_delete(RWL *rwl){ int ret; if (!(ret = rt_drg_on_adr_cnt(rwl))) { if (!rt_rwl_delete(rwl)) { rt_free(rwl); return 0; } else { return SEM_ERR; } } return ret;}/** * @anchor _rt_named_spl_init * @brief Initialize a spinlock identified by a name. * * _rt_named_spl_init allocate and initializes a spinlock (SPL) identified * by @e name. Once the spinlock structure is allocated the initialization * is as for rt_spl_init. The function returns the handle pointing to the * allocated spinlock structure, to be used as the usual spinlock address * in all spinlock based services. Named objects are useful for use among * different processes and kernel/user space. * * @param spl must point to an allocated @e RWL structure. * * Since @a name can be a clumsy identifier, services are provided to * convert 6 characters identifiers to unsigned long, and vice versa. * * @see nam2num() and num2nam(). * * As for all the named initialization functions it must be remarked that * only the very first call to initilize/create a named RTAI object does a * real allocation of the object, any following call with the same name * will just increase its usage count. In any case the function returns * a pointer to the named object, or zero if in error. * * @returns either a valid pointer or 0 if in error. * */SPL *_rt_named_spl_init(unsigned long spl_name){ SPL *spl; if ((spl = rt_get_adr_cnt(spl_name))) { return spl; } if ((spl = rt_malloc(sizeof(SPL)))) { rt_spl_init(spl); if (rt_register(spl_name, spl, IS_SPL, 0)) { return spl; } rt_spl_delete(spl); } rt_free(spl); return (SPL *)0;}/** * @anchor rt_named_spl_delete * @brief Delete a spinlock in named mode. * * rt_named_spl_delete deletes a spinlock previously created with * @ref rt_named_spl_init(). * * @param spl points to the structure pointer returned by a corresponding * call to rt_named_spl_init. * * As it is done by all the named allocation functions delete calls have just * the effect of decrementing a usage count till the last is done, as that is * the one the really frees the object. * * @return an int >=0 is returned upon success, -EFAULT if the spinlock * does not exist anymore. * */int rt_named_spl_delete(SPL *spl){ int ret; if (!(ret = rt_drg_on_adr_cnt(spl))) { rt_spl_delete(spl); rt_free(spl); return 0; } return ret;}/* +++++ SEMAPHORES, BARRIER, COND VARIABLES, RWLOCKS, SPINLOCKS ENTRIES ++++ */struct rt_native_fun_entry rt_sem_entries[] = { { { 0, rt_typed_sem_init }, TYPED_SEM_INIT }, { { 0, rt_sem_delete }, SEM_DELETE }, { { 0, _rt_typed_named_sem_init }, NAMED_SEM_INIT }, { { 0, rt_named_sem_delete }, NAMED_SEM_DELETE }, { { 1, rt_sem_signal }, SEM_SIGNAL }, { { 1, rt_sem_wait }, SEM_WAIT }, { { 1, rt_sem_wait_if }, SEM_WAIT_IF }, { { 1, rt_sem_wait_until }, SEM_WAIT_UNTIL }, { { 1, rt_sem_wait_timed }, SEM_WAIT_TIMED }, { { 1, rt_sem_broadcast }, SEM_BROADCAST }, { { 1, rt_sem_wait_barrier }, SEM_WAIT_BARRIER }, { { 1, rt_sem_count }, SEM_COUNT }, { { 1, rt_cond_wait }, COND_WAIT }, { { 1, rt_cond_wait_until }, COND_WAIT_UNTIL }, { { 1, rt_cond_wait_timed }, COND_WAIT_TIMED }, { { 0, rt_rwl_init }, RWL_INIT }, { { 0, rt_rwl_delete }, RWL_DELETE }, { { 0, _rt_named_rwl_init }, NAMED_RWL_INIT }, { { 0, rt_named_rwl_delete }, NAMED_RWL_DELETE }, { { 1, rt_rwl_rdlock }, RWL_RDLOCK }, { { 1, rt_rwl_rdlock_if }, RWL_RDLOCK_IF }, { { 1, rt_rwl_rdlock_until }, RWL_RDLOCK_UNTIL }, { { 1, rt_rwl_rdlock_timed }, RWL_RDLOCK_TIMED }, { { 1, rt_rwl_wrlock }, RWL_WRLOCK }, { { 1, rt_rwl_wrlock_if }, RWL_WRLOCK_IF }, { { 1, rt_rwl_wrlock_until }, RWL_WRLOCK_UNTIL }, { { 1, rt_rwl_wrlock_timed }, RWL_WRLOCK_TIMED }, { { 1, rt_rwl_unlock }, RWL_UNLOCK }, { { 0, rt_spl_init }, SPL_INIT }, { { 0, rt_spl_delete }, SPL_DELETE }, { { 0, _rt_named_spl_init }, NAMED_SPL_INIT }, { { 0, rt_named_spl_delete }, NAMED_SPL_DELETE }, { { 1, rt_spl_lock }, SPL_LOCK }, { { 1, rt_spl_lock_if }, SPL_LOCK_IF }, { { 1, rt_spl_lock_timed }, SPL_LOCK_TIMED }, { { 1, rt_spl_unlock }, SPL_UNLOCK }, { { 1, rt_cond_signal}, COND_SIGNAL }, { { 0, 0 }, 000 }};extern int set_rt_fun_entries(struct rt_native_fun_entry *entry);extern void reset_rt_fun_entries(struct rt_native_fun_entry *entry);int __rtai_sem_init (void){ return set_rt_fun_entries(rt_sem_entries);}void __rtai_sem_exit (void){ reset_rt_fun_entries(rt_sem_entries);}/* +++++++ END SEMAPHORES, BARRIER, COND VARIABLES, RWLOCKS, SPINLOCKS ++++++ *//*@}*/#ifndef CONFIG_RTAI_SEM_BUILTINmodule_init(__rtai_sem_init);module_exit(__rtai_sem_exit);#endif /* !CONFIG_RTAI_SEM_BUILTIN */#ifdef CONFIG_KBUILDEXPORT_SYMBOL(rt_typed_sem_init);EXPORT_SYMBOL(rt_sem_init);EXPORT_SYMBOL(rt_sem_delete);EXPORT_SYMBOL(rt_sem_count);EXPORT_SYMBOL(rt_sem_signal);EXPORT_SYMBOL(rt_sem_broadcast);EXPORT_SYMBOL(rt_sem_wait);EXPORT_SYMBOL(rt_sem_wait_if);EXPORT_SYMBOL(rt_sem_wait_until);EXPORT_SYMBOL(rt_sem_wait_timed);EXPORT_SYMBOL(rt_sem_wait_barrier);EXPORT_SYMBOL(_rt_typed_named_sem_init);EXPORT_SYMBOL(rt_named_sem_delete);EXPORT_SYMBOL(rt_cond_signal);EXPORT_SYMBOL(rt_cond_wait);EXPORT_SYMBOL(rt_cond_wait_until);EXPORT_SYMBOL(rt_cond_wait_timed);EXPORT_SYMBOL(rt_rwl_init);EXPORT_SYMBOL(rt_rwl_delete);EXPORT_SYMBOL(rt_rwl_rdlock);EXPORT_SYMBOL(rt_rwl_rdlock_if);EXPORT_SYMBOL(rt_rwl_rdlock_until);EXPORT_SYMBOL(rt_rwl_rdlock_timed);EXPORT_SYMBOL(rt_rwl_wrlock);EXPORT_SYMBOL(rt_rwl_wrlock_if);EXPORT_SYMBOL(rt_rwl_wrlock_until);EXPORT_SYMBOL(rt_rwl_wrlock_timed);EXPORT_SYMBOL(rt_rwl_unlock);EXPORT_SYMBOL(_rt_named_rwl_init);EXPORT_SYMBOL(rt_named_rwl_delete);EXPORT_SYMBOL(rt_spl_init);EXPORT_SYMBOL(rt_spl_delete);EXPORT_SYMBOL(rt_spl_lock);EXPORT_SYMBOL(rt_spl_lock_if);EXPORT_SYMBOL(rt_spl_lock_timed);EXPORT_SYMBOL(rt_spl_unlock);EXPORT_SYMBOL(_rt_named_spl_init);EXPORT_SYMBOL(rt_named_spl_delete);#endif /* CONFIG_KBUILD */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -