互斥量用來保證對共享資源或臨界區的訪問唯一性,保證在指定範圍內,只能有一個線程訪問該共享資源。
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);
}