申請信號量_tx_semaphore_get
1,如果信號量計數器tx_semaphore_count不爲0,就減一,返回申請成功。
2,如果信號量計數器tx_semaphore_count爲0,說明資源都被佔用,掛起當前線程到tx_semaphore_suspension_list隊列,掛入隊列的尾部,FIFO, 後續恢復時按住FIFO,而不是按照線程優先級
UINT _tx_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option)
{
TX_INTERRUPT_SAVE_AREA
REG_1 UINT status; /* Return status */
REG_2 TX_THREAD *thread_ptr; /* Working thread pointer */
/* Disable interrupts to get an instance from the semaphore. */
#def 禁止中斷,防止打斷對全局變量操作。如果更高優先級線程不需要信號量呢,是否有必要禁止中斷
TX_DISABLE
/* Determine if there is an instance of the semaphore. */
#def 還有信號量資源
if (semaphore_ptr -> tx_semaphore_count)
{
/* Decrement the semaphore count. */
#def 計數器減1,少一個可用信號量資源
semaphore_ptr -> tx_semaphore_count--;
#def 記錄最後一個申請到資源的線程
semaphore_ptr->sema_last_owner = _tx_thread_current_ptr;
/* Set status to success. */
status = TX_SUCCESS;
}
else
{
#def 沒有信號量資源,並且wait_option不爲0,掛起線程
/* Determine if the request specifies suspension. */
if (wait_option)
{
/* Prepare for suspension of this thread. */
/* Pickup thread pointer. */
thread_ptr = _tx_thread_current_ptr;
/* Setup cleanup routine pointer. */
#def 由於獲取不到信號量而掛起,所以設置清除函數爲信號量相關的函數_tx_semaphore_cleanup,當定時器超時或線程中止時,回調這個函數,釋放清除和信號量相關數據,比如從tx_semaphore_suspension_list隊列移除線程
thread_ptr -> tx_suspend_cleanup = _tx_semaphore_cleanup;
/* Setup cleanup information, i.e. this semaphore control
block. */
thread_ptr -> tx_suspend_control_block = (VOID_PTR) semaphore_ptr;
/* Setup suspension list. */
#def 插入隊列的尾部,fifo,所以後續恢復時也是按照fifo,並不是按照優先級高低 恢復線程
if (semaphore_ptr -> tx_semaphore_suspension_list)
{
/* This list is not NULL, add current thread to the end. */
thread_ptr -> tx_suspended_next =
semaphore_ptr -> tx_semaphore_suspension_list;
thread_ptr -> tx_suspended_previous =
(semaphore_ptr -> tx_semaphore_suspension_list) -> tx_suspended_previous;
((semaphore_ptr -> tx_semaphore_suspension_list) -> tx_suspended_previous) -> tx_suspended_next =
thread_ptr;
(semaphore_ptr -> tx_semaphore_suspension_list) -> tx_suspended_previous = thread_ptr;
}
else
{
/* No other threads are suspended. Setup the head pointer and
just setup this threads pointers to itself. */
semaphore_ptr -> tx_semaphore_suspension_list = thread_ptr;
thread_ptr -> tx_suspended_next = thread_ptr;
thread_ptr -> tx_suspended_previous = thread_ptr;
}
/* Increment the suspended thread count. */
semaphore_ptr -> tx_semaphore_suspended_count++;
/* Set the state to suspended. */
#def 線程狀態改爲掛起
thread_ptr -> tx_state = TX_SEMAPHORE_SUSP;
/* Set the suspending flag. */
#def 開始進行掛起過程標誌
thread_ptr -> tx_suspending = TX_TRUE;
/* Temporarily disable preemption. */
_tx_thread_preempt_disable++;
/* Save the timeout value. */
thread_ptr -> tx_thread_timer.tx_remaining_ticks = wait_option;
/* Restore interrupts. */
#def 恢復中斷,後續可能被搶佔了,線程可能被恢復
TX_RESTORE
/* See if we need to start a timer. */
#def 不是TX_WAIT_FOREVER永久掛起是,開啓定時器
if (wait_option != TX_WAIT_FOREVER)
{
/* A timeout is required. */
_tx_timer_activate(&(thread_ptr -> tx_thread_timer));
}
/* Call actual thread suspension routine. */
#def 掛起,執行到這個函數時,這個 線程可能又被標記爲恢復了,會檢查tx_suspending 標誌
_tx_thread_suspend(thread_ptr);
/* Return the completion status. */
return (thread_ptr -> tx_suspend_status);
}
else
/* Immediate return, return error completion. */
status = TX_NO_INSTANCE;
}
/* Restore interrupts. */
TX_RESTORE
/* Return completion status. */
return (status);
}