互斥量用来保证对共享资源或临界区的访问唯一性,保证在指定范围内,只能有一个线程访问该共享资源。
Threadx中同一个线程可以多次申请同一互斥量,并且释放互斥量必须释放相同次数。
互斥量控制块
Threadx中互斥量控制块(MCB)是用来保持运行时互斥量状态的数据结构。
/* Define the mutex structure utilized by the application. */
typedef struct TX_MUTEX_STRUCT
{
/* Define the mutex ID used for error checking. */
ULONG tx_mutex_id;
/* Define the mutex's name. */
CHAR_PTR tx_mutex_name;
/* Define the mutex ownership count. */
ULONG tx_mutex_ownership_count;
/* Define the mutex ownership pointer. This pointer points to the
the thread that owns the mutex. */
TX_THREAD *tx_mutex_owner;
/* Define the priority inheritance flag. If this flag is set, priority
inheritance will be in effect. */
UINT tx_mutex_inherit;
/* Define the save area for the owning thread's original priority and
threshold. */
UINT tx_mutex_original_priority;
UINT tx_mutex_original_threshold;
/* Define the mutex suspension list head along with a count of
how many threads are suspended. */
struct TX_THREAD_STRUCT *tx_mutex_suspension_list;
ULONG tx_mutex_suspended_count;
/* Define the created list next and previous pointers. */
struct TX_MUTEX_STRUCT
*tx_mutex_created_next,
*tx_mutex_created_previous;
} TX_MUTEX;
域 | 意义 |
---|---|
tx_mutex_id | 互斥量控制块ID |
tx_mutex_name | 互斥量名字指针 |
tx_mutex_ownership_count | 互斥量所有权计数器,表示某线程获取互斥量次数,范围0到2^32-1 |
tx_mutex_owner | 拥有互斥量的线程指针 |
tx_mutex_inherit | 优先级继承标志 |
tx_mutex_original_priority | 拥有互斥量的线程的原始优先级 |
tx_mutex_original_threshold | 拥有互斥量的线程的原始抢占门限 |
tx_mutex_suspension_list | 互斥量挂起list指针 |
tx_mutex_suspended_count | 互斥量挂起list上线程个数 |
tx_mutex_created_next | 指向下一个互斥量指针 |
tx_mutex_created_previous | 指向前一个互斥量指针 |
互斥量队列
系统中所有互斥量挂载同一个链表中,_tx_mutex_created_ptr执行链表头部。tx_mutex_created_next 指向下一个互斥量,tx_mutex_created_previous 指向前一个互斥量。
TX_MUTEX *_tx_mutex_created_ptr;
互斥量API
函数 | 描述 |
---|---|
UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit) | 创建互斥量 |
UINT _tx_mutex_delete(TX_MUTEX *mutex_ptr) | 删除互斥量 |
UINT _tx_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option) | 申请互斥量 |
UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner,TX_THREAD **first_suspended, ULONG *suspended_count,TX_MUTEX **next_mutex | 获取互斥量信息 |
UINT _tx_mutex_prioritize(TX_MUTEX *mutex_ptr) | 调整最高优先级线程到互斥量挂起队列的最前面 |
UINT _tx_mutex_put(TX_MUTEX *mutex_ptr) | 释放拥有的互斥量 |
VOID _tx_mutex_priority_change(TX_THREAD *thread_ptr, UINT new_priority, UINT new_threshold) | 改变线程优先级和抢占门限 |
VOID _tx_mutex_cleanup(TX_THREAD *thread_ptr) | clean线程在互斥量数据结构 |
互斥量创建_tx_mutex_create
_tx_mutex_create创建互斥量,函数很简单。 同一资源的互斥量只创建一次,互斥量创建时并没有拥有者。
线程使用时需要申请。
UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit)
{
TX_INTERRUPT_SAVE_AREA
TX_MUTEX *tail_ptr; /* Working mutex pointer */
/* Setup the basic mutex fields. */
mutex_ptr -> tx_mutex_name = name_ptr;
mutex_ptr -> tx_mutex_ownership_count = 0;
#def 优先级继承标志
mutex_ptr -> tx_mutex_inherit = inherit;
mutex_ptr -> tx_mutex_suspension_list = TX_NULL;
mutex_ptr -> tx_mutex_suspended_count = 0;
/* Disable interrupts to place the mutex on the created list. */
TX_DISABLE
/* Setup the mutex ID to make it valid. */
mutex_ptr -> tx_mutex_id = TX_MUTEX_ID;
/* Place the mutex on the list of created mutexes. First,
check for an empty list. */
#def 把互斥量插入_tx_mutex_created_ptr 队列
if (_tx_mutex_created_ptr)
{
/* Pickup tail pointer. */
tail_ptr = _tx_mutex_created_ptr -> tx_mutex_created_previous;
/* Place the new mutex in the list. */
_tx_mutex_created_ptr -> tx_mutex_created_previous = mutex_ptr;
tail_ptr -> tx_mutex_created_next = mutex_ptr;
/* Setup this mutex's next and previous created links. */
mutex_ptr -> tx_mutex_created_previous = tail_ptr;
mutex_ptr -> tx_mutex_created_next = _tx_mutex_created_ptr;
}
else
{
/* The created mutex list is empty. Add mutex to empty list. */
_tx_mutex_created_ptr = mutex_ptr;
mutex_ptr -> tx_mutex_created_next = mutex_ptr;
mutex_ptr -> tx_mutex_created_previous = mutex_ptr;
}
/* Increment the number of mutexes created counter. */
_tx_mutex_created_count++;
/* Restore interrupts. */
TX_RESTORE
/* Return TX_SUCCESS. */
return (TX_SUCCESS);
}
删除互斥量 _tx_semaphore_delete
删除互斥量:
1,把互斥量从_tx_mutex_created_ptr 队列删除。
2,把tx_mutex_suspension_list队列中线程移除,清除互斥量数据结构,并恢复线程
UINT _tx_mutex_delete(TX_MUTEX *mutex_ptr)
{
TX_INTERRUPT_SAVE_AREA
TX_THREAD *thread_ptr; /* Working thread pointer */
/* Disable interrupts to remove the mutex from the created list. */
TX_DISABLE
/* Decrement the number of mutexes created. */
_tx_mutex_created_count--;
/* Clear the mutex ID to make it invalid. */
mutex_ptr -> tx_mutex_id = 0;
/* See if the mutex is the only one on the list. */
#def 从_tx_mutex_created_ptr 删除mutex
if (mutex_ptr == mutex_ptr -> tx_mutex_created_next)
{
/* Only created mutex, just set the created list to NULL. */
_tx_mutex_created_ptr = TX_NULL;
}
else
{
/* Link-up the neighbors. */
(mutex_ptr -> tx_mutex_created_next) -> tx_mutex_created_previous =
mutex_ptr -> tx_mutex_created_previous;
(mutex_ptr -> tx_mutex_created_previous) -> tx_mutex_created_next =
mutex_ptr -> tx_mutex_created_next;
/* See if we have to update the created list head pointer. */
if (_tx_mutex_created_ptr == mutex_ptr)
/* Yes, move the head pointer to the next link. */
_tx_mutex_created_ptr = mutex_ptr -> tx_mutex_created_next;
}
/* Temporarily disable preemption. */
_tx_thread_preempt_disable++;
/* Restore interrupts. */
TX_RESTORE
/* Walk through the mutex list to resume any and all threads suspended
on this mutex. */
thread_ptr = mutex_ptr -> tx_mutex_suspension_list;
#def 从tx_mutex_suspension_list移除线程,清除数据,并恢复线程
while (mutex_ptr -> tx_mutex_suspended_count)
{
/* Lockout interrupts. */
TX_DISABLE
/* Clear the cleanup pointer, this prevents the timeout from doing
anything. */
thread_ptr -> tx_suspend_cleanup = TX_NULL;
/* Temporarily disable preemption again. */
_tx_thread_preempt_disable++;
/* Restore interrupts. */
TX_RESTORE
/* Yes, deactivate the thread's timer just in case. */
_tx_timer_deactivate(&(thread_ptr -> tx_thread_timer));
/* Set the return status in the thread to TX_DELETED. */
thread_ptr -> tx_suspend_status = TX_DELETED;
/* Move the thread pointer ahead. */
thread_ptr = thread_ptr -> tx_suspended_next;
/* Resume the thread. */
_tx_thread_resume(thread_ptr -> tx_suspended_previous);
/* Decrease the suspended count. */
mutex_ptr -> tx_mutex_suspended_count--;
}
/* Disable interrupts. */
TX_DISABLE
/* Release previous preempt disable. */
_tx_thread_preempt_disable--;
/* Restore interrupts. */
TX_RESTORE
/* Check for preemption. */
if (_tx_thread_current_ptr != _tx_thread_execute_ptr)
/* Transfer control to system. */
_tx_thread_system_return();
/* Return TX_SUCCESS. */
return (TX_SUCCESS);
}