mutex_get_2">申请互斥量 _tx_mutex_get
_tx_mutex_get用于申请互斥量:
1,如果是系统中第一个申请互斥量线程,tx_mutex_ownership_count 设置为1,申请成功。
2,如果是拥有互斥量的线程再次申请,那么只需tx_mutex_ownership_count 计数器加一,申请成功。
3,如果申请互斥量的当前线程不是拥有互斥量的线程,需要把当前线程挂入tx_mutex_suspension_list队列:
(1)如果设置了优先级继承,并且当前线程优先级高于拥有互斥量线程的优先级,那么设置拥有互斥量线程的优先级
为当前线程优先级;
4,挂起队列中线程优先级一定大于拥有者线程优先级,因为只有高优先级才能够打断拥有者线程,尝试申请互斥量
UINT _tx_mutex_get(TX_MUTEX *mutex_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 mutex. */
TX_DISABLE
/* Determine if there is an instance of the mutex. */
if (!mutex_ptr -> tx_mutex_ownership_count)
{
#def 第一次线程申请互斥量
/* Set the ownership count to 1. */
mutex_ptr -> tx_mutex_ownership_count = 1;
/* Remember that the calling thread owns the mutex. */
mutex_ptr -> tx_mutex_owner = _tx_thread_current_ptr;
/* Determine if priority inheritance is required. */
if ((mutex_ptr -> tx_mutex_inherit) && (_tx_thread_current_ptr))
{
#def 设置了优先级继承,保存原始的优先级和抢占门限
/* Remember the current priority and threshold of thread. */
mutex_ptr -> tx_mutex_original_priority = _tx_thread_current_ptr -> tx_priority;
mutex_ptr -> tx_mutex_original_threshold = _tx_thread_current_ptr -> tx_preempt_threshold;
}
/* Set status to success. */
status = TX_SUCCESS;
}
else if (mutex_ptr -> tx_mutex_owner == _tx_thread_current_ptr)
{
#def 本线程已经拥有了这个互斥量,已经申请过。再次申请,只需tx_mutex_ownership_count计数器加一
/* The owning thread is requesting the mutex again, just
increment the ownership count. */
mutex_ptr -> tx_mutex_ownership_count++;
/* Set status to success. */
status = TX_SUCCESS;
}
else
{
#def 互斥量已经被其他线程申请成功; 本线程进行申请
#def 1,wait_option =0 本线程不等待互斥量释放,直接返回
#def 2,wait_option 不为0,本线程挂入tx_mutex_suspension_list队列,自我挂起
/* 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_mutex_cleanup,如果后续这个线程不再等待信号量,会回调tx_suspend_cleanup ,清除互斥量相关的data struct
thread_ptr -> tx_suspend_cleanup = _tx_mutex_cleanup;
/* Setup cleanup information, i.e. this mutex control
block. */
thread_ptr -> tx_suspend_control_block = (VOID_PTR) mutex_ptr;
#def 插入到互斥量挂起队列tx_mutex_suspension_list,这里挂入了尾部,也就是FIFO。这里并没有按照线程优先级,把最高优先级插入到最前面
/* Setup suspension list. */
if (mutex_ptr -> tx_mutex_suspension_list)
{
/* This list is not NULL, add current thread to the end. */
thread_ptr -> tx_suspended_next =
mutex_ptr -> tx_mutex_suspension_list;
thread_ptr -> tx_suspended_previous =
(mutex_ptr -> tx_mutex_suspension_list) -> tx_suspended_previous;
((mutex_ptr -> tx_mutex_suspension_list) -> tx_suspended_previous) -> tx_suspended_next =
thread_ptr;
(mutex_ptr -> tx_mutex_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. */
mutex_ptr -> tx_mutex_suspension_list = thread_ptr;
thread_ptr -> tx_suspended_next = thread_ptr;
thread_ptr -> tx_suspended_previous = thread_ptr;
}
/* Increment the suspended thread count. */
mutex_ptr -> tx_mutex_suspended_count++;
/* Set the state to suspended. */
#def 设置为挂起状态
thread_ptr -> tx_state = TX_MUTEX_SUSP;
/* Set the suspending flag. */
#def 设置为true,表示正在挂起过程;_tx_thread_suspend或resume中用到这个标志
thread_ptr -> tx_suspending = TX_TRUE;
/* Temporarily disable preemption. */
_tx_thread_preempt_disable++;
/* Save the timeout value. */
#def wait_option为线程等待互斥量时间,需要开启定时器;定时器超时就调用前面设置的tx_suspend_cleanup
thread_ptr -> tx_thread_timer.tx_remaining_ticks = wait_option;
/* Restore interrupts. */
TX_RESTORE
/* Determine if we need to raise the priority of the thread
owning the mutex. */
#def 如果设置了优先级继承标志,
if ((mutex_ptr -> tx_mutex_inherit) && (mutex_ptr -> tx_mutex_owner)
&& (_tx_thread_current_ptr))
{
/* Priority inheritance is requested, check to see if the
thread that owns the mutex is lower priority. */
#def 如果当前申请互斥量线程优先级高于 互斥量拥有者的线程,那么把互斥量拥有者的线程设置为当前线程优先级,抢占门限也设置为当前线程优先级。 这样保证了拥有互斥量线程优先级最高,防止了中等优先级线程抢占, 这样高优先级等待互斥量时间 由 拥有互斥量线程 占用互斥量的时间。把不确定变为了确定。
if ((mutex_ptr -> tx_mutex_owner) -> tx_priority >
_tx_thread_current_ptr -> tx_priority)
{
/* Yes, raise the suspended, owning thread's priority to that
of the current thread. */
_tx_mutex_priority_change(mutex_ptr -> tx_mutex_owner, _tx_thread_current_ptr -> tx_priority, _tx_thread_current_ptr -> tx_priority);
}
}
/* See if we need to start a timer. */
#def wait_option 不是永久等待时,启动等待定时器
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_thread_suspend(thread_ptr);
/* Return the completion status. */
return (thread_ptr -> tx_suspend_status);
}
else
/* Immediate return, return error completion. */
status = TX_NOT_AVAILABLE;
}
/* Restore interrupts. */
TX_RESTORE
/* Return completion status. */
return (status);
}
mutex_prioritize_176">_tx_mutex_prioritize
_tx_mutex_prioritize把最高优先级线程挂到tx_mutex_suspension_list最前面
UINT _tx_mutex_prioritize(TX_MUTEX *mutex_ptr)
{
TX_INTERRUPT_SAVE_AREA
REG_1 TX_THREAD *thread_ptr; /* Working thread pointer */
REG_2 TX_THREAD *priority_thread_ptr; /* Highest priority thread */
/* Disable interrupts. */
TX_DISABLE
/* Determine if there how many threads are suspended on this mutex. */
if (mutex_ptr -> tx_mutex_suspended_count == 2)
{
#def list中只有两个线程,只需要把tx_mutex_suspension_list指向优先级最高线程
/* Determine if the next suspended thread has a higher priority. */
if (((mutex_ptr -> tx_mutex_suspension_list) -> tx_suspended_next) -> tx_priority <
((mutex_ptr -> tx_mutex_suspension_list) -> tx_priority))
{
/* Yes, move the list head to the next thread. */
mutex_ptr -> tx_mutex_suspension_list =
(mutex_ptr -> tx_mutex_suspension_list) -> tx_suspended_next;
}
}
else if (mutex_ptr -> tx_mutex_suspended_count > 2)
{
/* Default the highest priority thread to the thread at the front of the list. */
priority_thread_ptr = mutex_ptr -> tx_mutex_suspension_list;
/* Setup search pointer. */
thread_ptr = priority_thread_ptr -> tx_suspended_next;
#def 从tx_mutex_suspension_list队列中找出优先级最高的线程
/* Search through the list to find the highest priority thread. */
do
{
/* Is the current thread higher priority? */
if (thread_ptr -> tx_priority < priority_thread_ptr -> tx_priority)
{
/* Yes, remember that this thread is the highest priority. */
priority_thread_ptr = thread_ptr;
}
/* Move the thread pointer to the next thread. */
thread_ptr = thread_ptr -> tx_suspended_next;
}
while (thread_ptr != mutex_ptr -> tx_mutex_suspension_list);
/* Now determine if the highest priority thread is at the front
of the list. */
#def 如果优先级最高线程不是在队列最前面,那么先从队列中remove 最高优先级线程,再插入到队列最前面
if (priority_thread_ptr != mutex_ptr -> tx_mutex_suspension_list)
{
/* No, we need to move the highest priority suspended thread to the
front of the list. */
/* First, remove the highest priority thread by updating the
adjacent suspended threads. */
(priority_thread_ptr -> tx_suspended_next) -> tx_suspended_previous =
priority_thread_ptr -> tx_suspended_previous;
(priority_thread_ptr -> tx_suspended_previous) -> tx_suspended_next =
priority_thread_ptr -> tx_suspended_next;
/* Now, link the highest priority thread at the front of the list. */
priority_thread_ptr -> tx_suspended_next =
mutex_ptr -> tx_mutex_suspension_list;
priority_thread_ptr -> tx_suspended_previous =
(mutex_ptr -> tx_mutex_suspension_list) -> tx_suspended_previous;
((mutex_ptr -> tx_mutex_suspension_list) -> tx_suspended_previous) -> tx_suspended_next =
priority_thread_ptr;
(mutex_ptr -> tx_mutex_suspension_list) -> tx_suspended_previous = priority_thread_ptr;
/* Move the list head pointer to the highest priority suspended thread. */
mutex_ptr -> tx_mutex_suspension_list = priority_thread_ptr;
}
}
/* Restore interrupts. */
TX_RESTORE
/* Return completion status. */
return (TX_SUCCESS);
}