申请信号量_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);
}