1,如果tx_semaphore_suspension_list挂起队列为空,那么直接把tx_semaphore_count计数器加一
2,如果tx_semaphore_suspension_list挂起队列不为空,那么tx_semaphore_suspension_list最前面线程获取释放的信号量,
并恢复线程。这里采用的FIFO,并没有按照优先级高低选择恢复线程。
_tx_semaphore_put函数在释放信号量是并没有检查当前释放信号量的线程是不是线程的拥有者,信号量并没有所有权属性。
这种特性可以用来进行事件通知,比如一个线程不断等待信号量,成功后处理任务;另一个线程,进行信号量释放。
这种特性,任何线程都可以释放信号量。
UINT _tx_semaphore_put(TX_SEMAPHORE *semaphore_ptr)
{
TX_INTERRUPT_SAVE_AREA
REG_1 TX_THREAD *thread_ptr; /* Working thread pointer */
/* Disable interrupts to put an instance back to the semaphore. */
TX_DISABLE
/* Determine if there are any threads suspended on the semaphore. */
thread_ptr = semaphore_ptr -> tx_semaphore_suspension_list;
#def tx_semaphore_suspension_list不为空,队列头部线程获得信号量,恢复线程
if (thread_ptr)
{
/* Remove the suspended thread from the list. */
/* See if this is the only suspended thread on the list. */
if (thread_ptr == thread_ptr -> tx_suspended_next)
{
/* Yes, the only suspended thread. */
/* Update the head pointer. */
semaphore_ptr -> tx_semaphore_suspension_list = TX_NULL;
}
else
{
/* At least one more thread is on the same expiration list. */
/* Update the list head pointer. */
semaphore_ptr -> tx_semaphore_suspension_list = thread_ptr -> tx_suspended_next;
/* Update the links of the adjacent threads. */
(thread_ptr -> tx_suspended_next) -> tx_suspended_previous =
thread_ptr -> tx_suspended_previous;
(thread_ptr -> tx_suspended_previous) -> tx_suspended_next =
thread_ptr -> tx_suspended_next;
}
/* Decrement the suspension count. */
semaphore_ptr -> tx_semaphore_suspended_count--;
/* Prepare for resumption of the first thread. */
/* Clear cleanup routine to avoid timeout. */
thread_ptr -> tx_suspend_cleanup = TX_NULL;
/* Temporarily disable preemption. */
_tx_thread_preempt_disable++;
/* Restore interrupts. */
TX_RESTORE
/* Deactivate the timeout timer if necessary. */
#def 关闭定时器
if (thread_ptr -> tx_thread_timer.tx_list_head)
{
/* Deactivate the thread's timeout timer. */
_tx_timer_deactivate(&(thread_ptr -> tx_thread_timer));
}
else
{
/* Clear the remaining time to ensure timer doesn't get activated. */
thread_ptr -> tx_thread_timer.tx_remaining_ticks = 0;
}
/* Put return status into the thread control block. */
thread_ptr -> tx_suspend_status = TX_SUCCESS;
semaphore_ptr->sema_last_owner = thread_ptr;
/* Resume thread. */
#def 恢复线程
if (_tx_thread_resume(thread_ptr))
/* Preemption is required, transfer control back to
system. */
_tx_thread_system_return();
/* Return success. */
return (TX_SUCCESS);
}
else
{
#def 没有线程挂起等待信号量,信号量计数器加1
/* Increment the semaphore count. */
semaphore_ptr -> tx_semaphore_count++;
semaphore_ptr->sema_last_owner = 0;
}
/* Restore interrupts. */
TX_RESTORE
/* Return successful completion status. */
return (TX_SUCCESS);
}