📄 mutex.c
字号:
* and the mutex is not immediately available. * * - -EINTR is returned if rt_task_unblock() has been called for the * waiting task before the mutex has become available. * * - -ETIMEDOUT is returned if the mutex cannot be made available to * the calling task within the specified amount of time. * * - -EPERM is returned if this service was called from a context * which cannot be given the ownership of the mutex (e.g. interrupt, * non-realtime or scheduler locked). * * Environments: * * This service can be called from: * * - Kernel-based task * - User-space task (switches to primary mode) * * Rescheduling: always unless the request is immediately satisfied or * @a timeout specifies a non-blocking operation. If the caller is * blocked, the current owner's priority might be temporarily raised * as a consequence of the priority inheritance protocol. * * @note This service is sensitive to the current operation mode of * the system timer, as defined by the rt_timer_start() service. In * periodic mode, clock ticks are interpreted as periodic jiffies. In * oneshot mode, clock ticks are interpreted as nanoseconds. */int rt_mutex_lock (RT_MUTEX *mutex, RTIME timeout){ RT_TASK *task; int err = 0; spl_t s; if (xnpod_unblockable_p()) return -EPERM; xnlock_get_irqsave(&nklock,s); mutex = xeno_h2obj_validate(mutex,XENO_MUTEX_MAGIC,RT_MUTEX); if (!mutex) { err = xeno_handle_error(mutex,XENO_MUTEX_MAGIC,RT_MUTEX); goto unlock_and_exit; } task = xeno_current_task(); if (mutex->owner == NULL) { xnsynch_set_owner(&mutex->synch_base,&task->thread_base); mutex->owner = task; mutex->lockcnt = 1; goto unlock_and_exit; } if (mutex->owner == task) { mutex->lockcnt++; goto unlock_and_exit; } if (timeout == TM_NONBLOCK) { err = -EWOULDBLOCK; goto unlock_and_exit; } xnsynch_sleep_on(&mutex->synch_base,timeout); if (xnthread_test_flags(&task->thread_base,XNRMID)) err = -EIDRM; /* Mutex deleted while pending. */ else if (xnthread_test_flags(&task->thread_base,XNTIMEO)) err = -ETIMEDOUT; /* Timeout.*/ else if (xnthread_test_flags(&task->thread_base,XNBREAK)) err = -EINTR; /* Unblocked.*/ unlock_and_exit: xnlock_put_irqrestore(&nklock,s); return err;}/** * @fn int rt_mutex_unlock(RT_MUTEX *mutex) * * @brief Unlock mutex. * * Release a mutex. If the mutex is pended, the first waiting task (by * priority order) is immediately unblocked and transfered the * ownership of the mutex; otherwise, the mutex is left in an unlocked * state. * * @param mutex The descriptor address of the released mutex. * * @return 0 is returned upon success. Otherwise: * * - -EINVAL is returned if @a mutex is not a mutex descriptor. * * - -EIDRM is returned if @a mutex is a deleted mutex descriptor. * * - -EPERM is returned if @a mutex is not owned by the current task, * or more generally if this service was called from a context which * cannot own any mutex (e.g. interrupt, or non-realtime context). * * Environments: * * This service can be called from: * * - Kernel-based task * - User-space task (switches to primary mode) * * Rescheduling: possible. */int rt_mutex_unlock (RT_MUTEX *mutex){ int err = 0; spl_t s; if (xnpod_asynch_p() || testbits(xnpod_current_thread()->status,XNROOT)) return -EPERM; xnlock_get_irqsave(&nklock,s); mutex = xeno_h2obj_validate(mutex,XENO_MUTEX_MAGIC,RT_MUTEX); if (!mutex) { err = xeno_handle_error(mutex,XENO_MUTEX_MAGIC,RT_MUTEX); goto unlock_and_exit; } if (xeno_current_task() != mutex->owner) { err = -EPERM; goto unlock_and_exit; } if (--mutex->lockcnt > 0) goto unlock_and_exit; mutex->owner = thread2rtask(xnsynch_wakeup_one_sleeper(&mutex->synch_base)); if (mutex->owner != NULL) { mutex->lockcnt = 1; xnpod_schedule(); } unlock_and_exit: xnlock_put_irqrestore(&nklock,s); return err;}/** * @fn int rt_mutex_inquire(RT_MUTEX *mutex, RT_MUTEX_INFO *info) * * @brief Inquire about a mutex. * * Return various information about the status of a given mutex. * * @param mutex The descriptor address of the inquired mutex. * * @param info The address of a structure the mutex information will * be written to. * @return 0 is returned and status information is written to the * structure pointed at by @a info upon success. Otherwise: * * - -EINVAL is returned if @a mutex is not a mutex descriptor. * * - -EIDRM is returned if @a mutex is a deleted mutex descriptor. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * - Kernel-based task * - User-space task * * Rescheduling: never. */int rt_mutex_inquire (RT_MUTEX *mutex, RT_MUTEX_INFO *info){ int err = 0; spl_t s; xnlock_get_irqsave(&nklock,s); mutex = xeno_h2obj_validate(mutex,XENO_MUTEX_MAGIC,RT_MUTEX); if (!mutex) { err = xeno_handle_error(mutex,XENO_MUTEX_MAGIC,RT_MUTEX); goto unlock_and_exit; } strcpy(info->name,mutex->name); info->lockcnt = mutex->lockcnt; info->nwaiters = xnsynch_nsleepers(&mutex->synch_base); unlock_and_exit: xnlock_put_irqrestore(&nklock,s); return err;}/** * @fn int rt_mutex_bind(RT_MUTEX *mutex,const char *name,RTIME timeout) * * @brief Bind to a mutex. * * This user-space only service retrieves the uniform descriptor of a * given Xenomai mutex identified by its symbolic name. If the mutex does * not exist on entry, this service blocks the caller until a mutex of * the given name is created. * * @param name A valid NULL-terminated name which identifies the * mutex to bind to. * * @param mutex The address of a mutex descriptor retrieved by the * operation. Contents of this memory is undefined upon failure. * * @param timeout The number of clock ticks to wait for the * registration to occur (see note). Passing TM_INFINITE causes the * caller to block indefinitely until the object is * registered. Passing TM_NONBLOCK causes the service to return * immediately without waiting if the object is not registered on * entry. * * @return 0 is returned upon success. Otherwise: * * - -EFAULT is returned if @a mutex or @a name is referencing invalid * memory. * * - -EINTR is returned if rt_task_unblock() has been called for the * waiting task before the retrieval has completed. * * - -EWOULDBLOCK is returned if @a timeout is equal to TM_NONBLOCK * and the searched object is not registered on entry. * * - -ETIMEDOUT is returned if the object cannot be retrieved within * the specified amount of time. * * - -EPERM is returned if this service should block, but was called * from a context which cannot sleep (e.g. interrupt, non-realtime or * scheduler locked). * * Environments: * * This service can be called from: * * - User-space task (switches to primary mode) * * Rescheduling: always unless the request is immediately satisfied or * @a timeout specifies a non-blocking operation. * * @note This service is sensitive to the current operation mode of * the system timer, as defined by the rt_timer_start() service. In * periodic mode, clock ticks are interpreted as periodic jiffies. In * oneshot mode, clock ticks are interpreted as nanoseconds. *//** * @fn int rt_mutex_unbind(RT_MUTEX *mutex) * * @brief Unbind from a mutex. * * This user-space only service unbinds the calling task from the * mutex object previously retrieved by a call to rt_mutex_bind(). * * @param mutex The address of a mutex descriptor to unbind from. * * @return 0 is always returned. * * This service can be called from: * * - User-space task. * * Rescheduling: never. */int __native_mutex_pkg_init (void){ return 0;}void __native_mutex_pkg_cleanup (void){}/*@}*/EXPORT_SYMBOL(rt_mutex_create);EXPORT_SYMBOL(rt_mutex_delete);EXPORT_SYMBOL(rt_mutex_lock);EXPORT_SYMBOL(rt_mutex_unlock);EXPORT_SYMBOL(rt_mutex_inquire);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -