ThreadX内核源码分析 - 线程同步之互斥锁及动态优先级

Posted arm7star

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ThreadX内核源码分析 - 线程同步之互斥锁及动态优先级相关的知识,希望对你有一定的参考价值。

1、ThreadX互斥锁介绍

互斥锁一般用来锁多线程都需要访问的临界资源,这些资源不能并发操作,例如对某个内存的互斥读写,这个读写很快,但是不能多线程同时进行,所以需要加互斥锁;

占用互斥锁的线程没能执行,可能是被高优先级线程抢占了或者临界资源里面调用了阻塞操作;高优先级线程想要访问临界资源就必须等待低优先级线程被调度然后释放互斥锁,如果低优先级线程不提高优先级不被执行的话,那么高优先级的线程就会阻塞,直到所有高优先级线程都阻塞了,才能轮到占用互斥锁的低优先级线程执行,这样高优先级线程就得不到及时处理,通常高优先级线程的任务都比较紧急;

ThreadX互斥锁实现了优先级继承,如果等待互斥锁的线程的优先级高于占用互斥锁的线程的优先级,那么将占用互斥锁线程的优先级调整到与等待互斥锁线程的优先级一样高,然占用互斥锁的线程尽快执行,尽快释放互斥锁,释放互斥锁时,线程优先级恢复原始优先级,让出cpu执行;

另外ThreadX互斥锁是可重复获取的,获取到了互斥锁的线程可以多次获取互斥锁,0表示互斥锁没有占用,非0表示互斥锁被占用,每获取一次互斥锁,互斥锁计数加1,获取互斥锁次数要与释放互斥锁次数相同,否则互斥锁不会被释放。

2、互斥锁获取_tx_mutex_get

2.1、互斥锁的获取_tx_mutex_get

互斥锁获取主要看互斥锁计数器:

  • 如果互斥锁计数器为0,那么互斥锁没有被占用,获取互斥锁,互斥锁继承当前线程的优先级,互斥锁计数器加1
  • 如果互斥锁已经被当前线程占用,互斥锁计数器加1即可;
  • 如果互斥锁被其他线程占用,当前线程不能阻塞或者没有设置等待参数就返回互斥锁不可用,否则挂起当前线程,当前线程加入等待互斥锁线程链表,更新tx_mutex_highest_priority_waiting(所有等待互斥锁的线程的最高优先级),如果当前等待互斥锁线程的优先级高于占用互斥锁线程的优先级,那么将占用互斥锁线程的优先级设置改变成当前线程的优先级,让占用互斥锁的线程尽快处理临界资源并释放互斥锁,等待互斥锁的高优先级线程才能尽快获取到互斥锁。

_tx_mutex_get代码实现如下:

077 UINT  _tx_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option)
078 
079 
080 TX_INTERRUPT_SAVE_AREA
081 
082 TX_THREAD       *thread_ptr;
083 TX_MUTEX        *next_mutex;
084 TX_MUTEX        *previous_mutex;
085 TX_THREAD       *mutex_owner;
086 TX_THREAD       *next_thread;
087 TX_THREAD       *previous_thread;
088 UINT            status;
089 
090 
091     /* Disable interrupts to get an instance from the mutex.  */
092     TX_DISABLE
093 
094 #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
095 
096     /* Increment the total mutex get counter.  */
097     _tx_mutex_performance_get_count++;
098 
099     /* Increment the number of attempts to get this mutex.  */
100     mutex_ptr -> tx_mutex_performance_get_count++;
101 #endif
102 
103     /* If trace is enabled, insert this event into the trace buffer.  */
104     TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_GET, mutex_ptr, wait_option, TX_POINTER_TO_ULONG_CONVERT(mutex_ptr -> tx_mutex_owner), mutex_ptr -> tx_mutex_ownership_count, TX_TRACE_MUTEX_EVENTS)
105 
106     /* Log this kernel call.  */
107     TX_EL_MUTEX_GET_INSERT
108 
109     /* Pickup thread pointer.  */
110     TX_THREAD_GET_CURRENT(thread_ptr)
111 
112     /* Determine if this mutex is available.  */
113     if (mutex_ptr -> tx_mutex_ownership_count == ((UINT) 0)) // 互斥锁没有被占用
114     
115 
116         /* Set the ownership count to 1.  */
117         mutex_ptr -> tx_mutex_ownership_count =  ((UINT) 1); // 互斥锁计数加1(互斥锁被占用)
118 
119         /* Remember that the calling thread owns the mutex.  */
120         mutex_ptr -> tx_mutex_owner =  thread_ptr; // 记录占用互斥锁的线程为当前线程
121 
122         /* Determine if the thread pointer is valid.  */
123         if (thread_ptr != TX_NULL) // 当前线程是否有效(非线程上下文调用不用执行if分支,正常情况下都是在线程上下文调用互斥锁)
124         
125 
126             /* Determine if priority inheritance is required.  */
127             if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
128             
129          
130                 /* Remember the current priority of thread.  */
131                 mutex_ptr -> tx_mutex_original_priority =   thread_ptr -> tx_thread_priority; // tx_mutex_original_priority记录线程获取互斥锁时的原始优先级(第一次获取互斥锁的时候才会执行到这里)
132 
133                 /* Setup the highest priority waiting thread.  */
134                 mutex_ptr -> tx_mutex_highest_priority_waiting =  ((UINT) TX_MAX_PRIORITIES); // 正在等待互斥锁的线程的最高优先级,没有时默认就是TX_MAX_PRIORITIES(最低优先级)
135             
136 
137             /* Pickup next mutex pointer, which is the head of the list.  */
138             next_mutex =  thread_ptr -> tx_thread_owned_mutex_list; // 线程占用互斥锁链表
139 
140             /* Determine if this thread owns any other mutexes that have priority inheritance.  */
141             if (next_mutex != TX_NULL) // 线程占用其他互斥锁,将当前获取的互斥锁加入链表表头
142             
143 
144                 /* Non-empty list. Link up the mutex.  */
145 
146                 /* Pickup the next and previous mutex pointer.  */
147                 previous_mutex =  next_mutex -> tx_mutex_owned_previous;
148 
149                 /* Place the owned mutex in the list.  */
150                 next_mutex -> tx_mutex_owned_previous =  mutex_ptr;
151                 previous_mutex -> tx_mutex_owned_next =  mutex_ptr;
152 
153                 /* Setup this mutex's next and previous created links.  */
154                 mutex_ptr -> tx_mutex_owned_previous =  previous_mutex;
155                 mutex_ptr -> tx_mutex_owned_next =      next_mutex;
156             
157             else // 线程没有占用其他互斥锁,新建一个互斥锁链表,只有一个当前获取到的互斥锁
158             
159 
160                 /* The owned mutex list is empty.  Add mutex to empty list.  */
161                 thread_ptr -> tx_thread_owned_mutex_list =     mutex_ptr;
162                 mutex_ptr -> tx_mutex_owned_next =             mutex_ptr;
163                 mutex_ptr -> tx_mutex_owned_previous =         mutex_ptr;
164             
165 
166             /* Increment the number of mutexes owned counter.  */
167             thread_ptr -> tx_thread_owned_mutex_count++; // 线程占用互斥锁个数加1
168         
169 
170         /* Restore interrupts.  */
171         TX_RESTORE
172 
173         /* Return success.  */
174         status =  TX_SUCCESS;
175     
176 
177     /* Otherwise, see if the owning thread is trying to obtain the same mutex.  */
178     else if (mutex_ptr -> tx_mutex_owner == thread_ptr) // 当前线程之前就已经占用了该互斥锁,再次获取该互斥锁,只需要增加互斥锁计数即可
179     
180 
181         /* The owning thread is requesting the mutex again, just 
182            increment the ownership count.  */
183         mutex_ptr -> tx_mutex_ownership_count++; // 互斥锁占用次数加1
184 
185         /* Restore interrupts.  */
186         TX_RESTORE
187 
188         /* Return success.  */
189         status =  TX_SUCCESS;
190     
191     else // 互斥锁被其他线程占用
192     
193 
194         /* Determine if the request specifies suspension.  */
195         if (wait_option != TX_NO_WAIT) // 有设置等待选项
196         
197 
198             /* Determine if the preempt disable flag is non-zero.  */
199             if (_tx_thread_preempt_disable != ((UINT) 0)) // 如果线程禁止抢占的话,那么不能阻塞当前线程,返回互斥锁不可用即可,否则其他线程被禁止抢占了就得不到执行
200             
201 
202                 /* Restore interrupts.  */
203                 TX_RESTORE
204 
205                 /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion.  */
206                 status =  TX_NOT_AVAILABLE;
207             
208             else // 线程没有禁止抢占,那么需要挂起当前线程
209             
210 
211                 /* Prepare for suspension of this thread.  */
212 
213                 /* Pickup the mutex owner.  */
214                 mutex_owner =  mutex_ptr -> tx_mutex_owner; // 获取占用互斥锁的线程
215 
216 #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
217 
218                 /* Increment the total mutex suspension counter.  */
219                 _tx_mutex_performance_suspension_count++;
220 
221                 /* Increment the number of suspensions on this mutex.  */
222                 mutex_ptr -> tx_mutex_performance_suspension_count++;
223 
224                 /* Determine if a priority inversion is present.  */
225                 if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_priority)
226                 
227 
228                     /* Yes, priority inversion is present!  */
229 
230                     /* Increment the total mutex priority inversions counter.  */
231                     _tx_mutex_performance_priority_inversion_count++;
232 
233                     /* Increment the number of priority inversions on this mutex.  */
234                     mutex_ptr -> tx_mutex_performance_priority_inversion_count++;
235 
236 #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
237 
238                     /* Increment the number of total thread priority inversions.  */
239                     _tx_thread_performance_priority_inversion_count++;
240 
241                     /* Increment the number of priority inversions for this thread.  */
242                     thread_ptr -> tx_thread_performance_priority_inversion_count++;
243 #endif
244                 
245 #endif
246 
247                 /* Setup cleanup routine pointer.  */
248                 thread_ptr -> tx_thread_suspend_cleanup =  &(_tx_mutex_cleanup); // 等待互斥锁超时或者被中断时的清理函数(等待超时需要通过定时调用_tx_mutex_cleanup唤醒阻塞的线程)
249 
250                 /* Setup cleanup information, i.e. this mutex control
251                    block.  */
252                 thread_ptr -> tx_thread_suspend_control_block =  (VOID *) mutex_ptr; // 清理函数的参数(等待的互斥锁),线程会挂到互斥锁等待链表里面,超时时需要从等待链表里面删除当前线程
253 
254 #ifndef TX_NOT_INTERRUPTABLE
255 
256                 /* Increment the suspension sequence number, which is used to identify
257                    this suspension event.  */
258                 thread_ptr -> tx_thread_suspension_sequence++;
259 #endif
260 
261                 /* Setup suspension list.  */
262                 if (mutex_ptr -> tx_mutex_suspended_count == TX_NO_SUSPENSIONS) // 当前线程加入等待mutex_ptr的挂起线程链表tx_mutex_suspension_list里面
263                 
264 
265                     /* No other threads are suspended.  Setup the head pointer and
266                        just setup this threads pointers to itself.  */
267                     mutex_ptr -> tx_mutex_suspension_list =         thread_ptr;
268                     thread_ptr -> tx_thread_suspended_next =        thread_ptr;
269                     thread_ptr -> tx_thread_suspended_previous =    thread_ptr;
270                 
271                 else
272                 
273 
274                     /* This list is not NULL, add current thread to the end. */
275                     next_thread =                                   mutex_ptr -> tx_mutex_suspension_list;
276                     thread_ptr -> tx_thread_suspended_next =        next_thread;
277                     previous_thread =                               next_thread -> tx_thread_suspended_previous;
278                     thread_ptr -> tx_thread_suspended_previous =    previous_thread;
279                     previous_thread -> tx_thread_suspended_next =   thread_ptr;
280                     next_thread -> tx_thread_suspended_previous =   thread_ptr;
281                 
282             
283                 /* Increment the suspension count.  */
284                 mutex_ptr -> tx_mutex_suspended_count++; // 等待互斥锁的线程计数加1
285 
286                 /* Set the state to suspended.  */
287                 thread_ptr -> tx_thread_state =    TX_MUTEX_SUSP; // 当前线程修改为挂起状态
288 
289 #ifdef TX_NOT_INTERRUPTABLE
290 
291                 /* Determine if we need to raise the priority of the thread 
292                    owning the mutex.  */
293                 if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
294                 
295 
296                     /* Determine if this is the highest priority to raise for this mutex.  */
297                     if (mutex_ptr -> tx_mutex_highest_priority_waiting > thread_ptr -> tx_thread_priority)
298                     
299 
300                         /* Remember this priority.  */
301                         mutex_ptr -> tx_mutex_highest_priority_waiting =  thread_ptr -> tx_thread_priority;
302                     
303 
304                     /* Determine if we have to update inherit priority level of the mutex owner.  */
305                     if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_inherit_priority)
306                     
307                     
308                         /* Remember the new priority inheritance priority.  */
309                         mutex_owner -> tx_thread_inherit_priority =  thread_ptr -> tx_thread_priority;
310                     
311 
312                     /* Priority inheritance is requested, check to see if the thread that owns the mutex is lower priority.  */
313                     if (mutex_owner -> tx_thread_priority > thread_ptr -> tx_thread_priority)
314                     
315 
316                         /* Yes, raise the suspended, owning thread's priority to that
317                            of the current thread.  */
318                         _tx_mutex_priority_change(mutex_owner, thread_ptr -> tx_thread_priority);
319 
320 #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
321 
322                         /* Increment the total mutex priority inheritance counter.  */
323                         _tx_mutex_performance__priority_inheritance_count++;
324 
325                         /* Increment the number of priority inheritance situations on this mutex.  */
326                         mutex_ptr -> tx_mutex_performance__priority_inheritance_count++;
327 #endif
328                     
329                 
330 
331                 /* Call actual non-interruptable thread suspension routine.  */
332                 _tx_thread_system_ni_suspend(thread_ptr, wait_option);
333 
334                 /* Restore interrupts.  */
335                 TX_RESTORE
336 #else
337 
338                 /* Set the suspending flag.  */
339                 thread_ptr -> tx_thread_suspending =  TX_TRUE; // 设置线程正在挂起(线程还没从就绪链表删除,还没真正挂起,其他挂起或者唤醒当前线程的操作需要检查tx_thread_suspending,不能唤醒挂起中的线程,延迟挂起挂起中线程,也就是互斥锁挂起之后,下次唤醒线程时再执行之前的挂起操作)
340 
341                 /* Setup the timeout period.  */
342                 thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  wait_option; // 线程超时时间(挂起线程时会启动一个定时器,定时器超时调用前面设置的回调函数,唤醒阻塞线程)
343 
344                 /* Temporarily disable preemption.  */
345                 _tx_thread_preempt_disable++; // 禁止抢占,后面会打开中断,避免当前线程被抢占切换出去,等线程真正挂起之后才调度其他线程,线程挂起之后,后面还有部分重要操作要执行
346 
347                 /* Restore interrupts.  */
348                 TX_RESTORE
349 
350                 /* Determine if we need to raise the priority of the thread 
351                    owning the mutex.  */
352                 if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) // 如果互斥锁继承为TX_TRUE,那么占用互斥锁的线程可以继承等待互斥锁线程的优先级
353                 
354 
355                     /* Determine if this is the highest priority to raise for this mutex.  */
356                     if (mutex_ptr -> tx_mutex_highest_priority_waiting > thread_ptr -> tx_thread_priority) // 当前线程是所有等待互斥锁的线程里面优先级最高的线程
357                     
358 
359                         /* Remember this priority.  */
360                         mutex_ptr -> tx_mutex_highest_priority_waiting =  thread_ptr -> tx_thread_priority; // 更新等待互斥锁线程的最高优先级
361                     
362 
363                     /* Determine if we have to update inherit priority level of the mutex owner.  */
364                     if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_inherit_priority) // 当前线程的优先级高于占用互斥锁线程的继承优先级(线程的继承优先级默认是TX_MAX_PRIORITIES)
365                     
366                     
367                         /* Remember the new priority inheritance priority.  */
368                         mutex_owner -> tx_thread_inherit_priority =  thread_ptr -> tx_thread_priority; // 更新占用互斥锁线程的继承优先级
369                     
370 
371                     /* Priority inheritance is requested, check to see if the thread that owns the mutex is lower priority.  */
372                     if (mutex_owner -> tx_thread_priority > thread_ptr -> tx_thread_priority) // 占用互斥的锁线程的优先级低于当前等待互斥锁线程的优先级
373                     
374 
375                         /* Yes, raise the suspended, owning thread's priority to that
376                            of the current thread.  */
377                         _tx_mutex_priority_change(mutex_owner, thread_ptr -> tx_thread_priority); // 调整占用互斥锁线程的优先级为当前线程的优先级(让占用互斥锁的线程尽快执行,然后释放互斥锁)
378 
379 #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
380 
381                         /* Increment the total mutex priority inheritance counter.  */
382                         _tx_mutex_performance__priority_inheritance_count++;
383 
384                         /* Increment the number of priority inheritance situations on this mutex.  */
385                         mutex_ptr -> tx_mutex_performance__priority_inheritance_count++;
386 #endif
387                     
388                 
389 
390                 /* Call actual thread suspension routine.  */
391                 _tx_thread_system_suspend(thread_ptr); // 挂起当前线程
392 #endif
393                 /* Return the completion status.  */
394                 status =  thread_ptr -> tx_thread_suspend_status;
395             
396         
397         else // 没有等待选项,不等待互斥锁,那么返回互斥锁不可用即可
398         
399 
400             /* Restore interrupts.  */
401             TX_RESTORE
402 
403             /* Immediate return, return error completion.  */
404             status =  TX_NOT_AVAILABLE;
405         
406     
407 
408     /* Return completion status.  */
409     return(status);
410 

2.2、线程优先级调整_tx_mutex_priority_change

调整优先级主要是将被改变优先级的线程从原来的就绪线程链表删除,加入到新的就绪线程链表,这个过程就导致被改变优先级的线程被加入到就绪线程链表末尾,而且还会导致内存重新选择下一个执行线程,例如:当前线程优先级为1,优先级1的线程只要当前线程就绪,优先级2有就绪线程,当前线程把自己的优先级将为2了,内核选择原来优先级2就绪链表的第一个就绪线程作为下一个执行的线程,很明显,应该让当前线程继续执行,那么就得再次把当前线程移动到表头,再例如:当前线程优先级为1,优先级1的线程只要当前线程就绪,就绪线程的次高优先级为5,优先级5的第一个就绪线程的抢占阈值为3,当前线程需要降低优先级为3,当前线程挂起时,内核选择优先级5的线程作为下一个执行线程,唤醒当前线程,虽然当前线程是最高优先级,但是优先级5的线程的抢占阈值为3,当前线程不能抢占阈值3的线程,理论上应该是抢占阈值3的线程不能抢占当前线程,当前线程就因为改变优先级而被不能抢占的线程抢占了,那么还得抢回来,将当前线程设置为下一个执行线程,并且移动到表头。(有些场景没看到内核怎么确保改变优先级的线程仍然在表头,而且有场景已经确认不能保证被标记抢占的线程不在就绪线程链表表头,不明白是bug能还是内核设计如此,向社区提交了issue,等待社区回复再具体分析!!!)

_tx_mutex_priority_change实现代码如下:

083 VOID  _tx_mutex_priority_change(TX_THREAD *thread_ptr, UINT new_priority)
084 
085 
086 #ifndef TX_NOT_INTERRUPTABLE
087 
088 TX_INTERRUPT_SAVE_AREA
089 #endif
090 
091 TX_THREAD       *execute_ptr;
092 TX_THREAD       *next_execute_ptr;
093 UINT            original_priority;
094 #ifndef TX_DISABLE_PREEMPTION_THRESHOLD
095 ULONG           priority_bit;
096 #if TX_MAX_PRIORITIES > 32
097 UINT            map_index;
098 #endif
099 #endif
100 
101 
102 
103 #ifndef TX_NOT_INTERRUPTABLE
104 
105     /* Lockout interrupts while the thread is being suspended.  */
106     TX_DISABLE
107 #endif
108 
109     /* Determine if this thread is currently ready.  */
110     if (thread_ptr -> tx_thread_state != TX_READY) // 如果线程非就绪状态,简单改变线程的优先级、抢占阈值,因为阻塞线程不在就绪链表里面,不需要移动(抢占阈值不低于线程创建时用户指定的抢占阈值;线程占用互斥锁时,线程会继承高优先级等待互斥锁线程的优先级,互斥锁释放时,会降低恢复旧的优先级)
111     
112 
113         /* Change thread priority to the new mutex priority-inheritance priority.  */
114         thread_ptr -> tx_thread_priority =  new_priority; // 设置线程的新的优先级
115             
116         /* Determine how to setup the thread's preemption-threshold.  */
117         if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority)
118         
119         
120             /* Change thread preemption-threshold to the user's preemption-threshold.  */
121             thread_ptr -> tx_thread_preempt_threshold =  thread_ptr -> tx_thread_user_preempt_threshold;
122         
123         else
124         
125         
126             /* Change the thread preemption-threshold to the new threshold.  */
127             thread_ptr -> tx_thread_preempt_threshold =  new_priority;
128         
129 
130 #ifndef TX_NOT_INTERRUPTABLE
131         /* Restore interrupts.  */
132         TX_RESTORE
133 #endif
134     
135     else // 就绪状态的线程,改变优先级后,线程需要移动到新的优先级的就绪线程链表里面(从原来链表删除,再添加到新的就绪线程链表)
136     
137 
138         /* Pickup the next thread to execute.  */
139         execute_ptr =  _tx_thread_execute_ptr; // 保存当前时间下一个需要执行的线程
140 
141         /* Save the original priority.  */
142         original_priority =  thread_ptr -> tx_thread_priority; // 记录线程的原始优先级(改变优先级前的优先级)
143 
144 #ifdef TX_NOT_INTERRUPTABLE
145 
146         /* Increment the preempt disable flag.  */
147         _tx_thread_preempt_disable++;
148 
149         /* Set the state to priority change.  */
150         thread_ptr -> tx_thread_state =    TX_PRIORITY_CHANGE;
151 
152         /* Call actual non-interruptable thread suspension routine.  */
153         _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0));
154 
155         /* At this point, the preempt disable flag is still set, so we still have 
156            protection against all preemption.  */
157 
158         /* Change thread priority to the new mutex priority-inheritance priority.  */
159         thread_ptr -> tx_thread_priority =  new_priority;
160             
161         /* Determine how to setup the thread's preemption-threshold.  */
162         if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority)
163         
164         
165             /* Change thread preemption-threshold to the user's preemption-threshold.  */
166             thread_ptr -> tx_thread_preempt_threshold =  thread_ptr -> tx_thread_user_preempt_threshold;
167         
168         else
169         
170         
171             /* Change the thread preemption-threshold to the new threshold.  */
172             thread_ptr -> tx_thread_preempt_threshold =  new_priority;
173         
174 
175         /* Resume the thread with the new priority.  */
176         _tx_thread_system_ni_resume(thread_ptr);
177 
178         /* Decrement the preempt disable flag.  */
179         _tx_thread_preempt_disable--;
180 #else
181 
182         /* Increment the preempt disable flag.  */
183         _tx_thread_preempt_disable =  _tx_thread_preempt_disable + ((UINT) 2); // 禁止抢占计数器加2(主要因为移动线程到其他就绪线程链表需要挂起再唤醒该线程,挂起/唤醒会对禁止抢占计数器减1,如果_tx_thread_preempt_disable减为0,就会进行调度,对抢占计数器加2就是为了在挂起/唤醒过程中,禁止抢占当前线程,不管是否有高优先级线程,当前线程需要继续处理后续代码;调用_tx_mutex_priority_change函数前的代码已经禁止抢占了,所以_tx_mutex_priority_change不会被其他线程抢占!!!)
184 
185         /* Set the state to priority change.  */
186         thread_ptr -> tx_thread_state =    TX_PRIORITY_CHANGE; // 将线程状态设置为TX_PRIORITY_CHANGE(主要是在挂起操作时,对TX_PRIORITY_CHANGE以及其他特殊状态的线程进行挂起,并不会立即挂起,而是会设置一个延迟挂起的标志,这些状态正在处理比较重要的事情,这个过程不能被挂起;延迟挂起被设置,那么下次唤醒线程时,就会执行延迟的挂起操作,挂起线程)
187 
188         /* Set the suspending flag. */
189         thread_ptr -> tx_thread_suspending =  TX_TRUE; // 设置挂起中(挂起中表示线程还没从就绪线程链表删除,如果有其他操作唤醒挂起中的线程,那么将状态改成就绪即可,因为线程还在就绪线程链表,不需要再次添加到就绪线程链表;_tx_thread_system_suspend只会对挂起中的线程进行挂起操作,线程的挂起中如果不为真,那么,可能线程挂起过程中,被其他线程唤醒了,就不要再继续挂起线程)
190 
191         /* Setup the timeout period.  */
192         thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  ((ULONG) 0); // 本次挂起不需要启动定时器(本次挂起的目的主要是将线程从就绪线程链表删除)
193 
194         /* Restore interrupts.  */
195         TX_RESTORE
196 
197         /* The thread is ready and must first be removed from the list.  Call the 
198            system suspend function to accomplish this.  */
199         _tx_thread_system_suspend(thread_ptr); // 挂起线程,从就绪线程链表删除线程,会对禁止抢占计数器减1(_tx_thread_system_suspend并不知道本次挂起的目的,挂起thread_ptr,可能会选一个新的下一个被执行的线程,所以前面先记录了下一个被执行的线程)
200 
201         /* Disable interrupts.  */
202         TX_DISABLE
203 
204         /* At this point, the preempt disable flag is still set, so we still have 
205            protection against all preemption.  */
206 
207         /* Change thread priority to the new mutex priority-inheritance priority.  */
208         thread_ptr -> tx_thread_priority =  new_priority; // 设置新的线程优先级
209             
210         /* Determine how to setup the thread's preemption-threshold.  */
211         if (thread_ptr -> tx_thread_user_preempt_threshold < new_priority) // 抢占阈值更新
212         
213         
214             /* Change thread preemption-threshold to the user's preemption-threshold.  */
215             thread_ptr -> tx_thread_preempt_threshold =  thread_ptr -> tx_thread_user_preempt_threshold;
216         
217         else
218         
219         
220             /* Change the thread preemption-threshold to the new threshold.  */
221             thread_ptr -> tx_thread_preempt_threshold =  new_priority;
222         
223 
224         /* Restore interrupts.  */
225         TX_RESTORE
226 
227         /* Resume the thread with the new priority.  */
228         _tx_thread_system_resume(thread_ptr); // 唤醒线程,将线程加入就绪线程链表,会对禁止抢占计数器减1,前面加的2被减没了,但是_tx_mutex_priority_change被调用前,禁止抢占计数器都会先加1,所以_tx_thread_system_resume还是不能调度其他线程,不会切换线程,后续代码要重新对下一个要执行的线程进行计算
229 #endif
230 
231         /* Optional processing extension.  */
232         TX_MUTEX_PRIORITY_CHANGE_EXTENSION
233 
234 #ifndef TX_NOT_INTERRUPTABLE
235 
236         /* Disable interrupts.  */
237         TX_DISABLE
238 #endif
239         
240         /* Pickup the next thread to execute.  */
241         next_execute_ptr =  _tx_thread_execute_ptr; // 挂起/唤醒线程,允许中断过程可能有更高优先级线程就绪,获取当前下一个要执行的线程
242 
243         /* Determine if this thread is not the next thread to execute.  */
244         if (thread_ptr != next_execute_ptr) // 被改变优先级的线程不是下一个需要执行的线程
245         
246         
247             /* Make sure the thread is still ready.  */
248             if (thread_ptr -> tx_thread_state == TX_READY) // _tx_thread_system_resume正常情况就会把线程设置为就绪状态,但是前面有解释延迟挂起,也就是在挂起线程中调用_tx_thread_system_resume之前,有其他操作挂起该线程并设置了延迟挂起,那么_tx_thread_system_resume就会挂起线程,而不会唤醒线程,因此这里还要再次判断线程状态
249             
250 
251                 /* Now check and see if this thread has an equal or higher priority.  */
252                 if (thread_ptr -> tx_thread_priority <= next_execute_ptr -> tx_thread_priority) // 改变优先级的线程的优先级等于或者高于下一个需要执行的线程
253                 
254 
255                     /* Now determine if this thread was the previously executing thread.  */
256                     if (thread_ptr == execute_ptr) // 如果thread_ptr在改变优先级之前就是下一个需要执行的线程,并且thread_ptr现在的优先级也不比next_execute_ptr低,那么应该继续选择thread_ptr作为下一个要执行的线程(释放互斥锁时,恢复低优先级,可能降低到次优先级就绪线程链表或者更低优先级线程启用了抢占,导致降低优先级的线程不能抢占线程next_execute_ptr)
257                     
258 
259                         /* Yes, this thread was previously executing before we temporarily suspended and resumed
260                            it in order to change the priority. A lower or same priority thread cannot be the next thread
261                            to execute in this case since this thread really didn't suspend.  Simply reset the execute
262                            pointer to this thread.  */
263                         _tx_thread_execute_ptr =  thread_ptr; // 让thread_ptr线程继续执行
264 
265                         /* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list.  */
266                         if (original_priority < new_priority) // 如果线程的优先级被降低了,thread_ptr可能添加到了就绪线程链表末尾,需要将thread_ptr移动到就绪线程链表表头(释放互斥锁优先级升高情况,暂时有些疑问,没看到怎么保证thread_ptr在链表表头,提交了一个issues到社区,等待社区回复!!!)
267                         
268                         
269                             /* Ensure that this thread is placed at the front of the priority list.  */
270                             _tx_thread_priority_list[thread_ptr -> tx_thread_priority] =  thread_ptr; // 就绪线程链表表头指向thread_ptr(等价将thread_ptr移动到表头)
271                         
272                     
273                 
274                 else // 1、提高优先级过程有更高优先级线程被中断服务程序唤醒,next_execute_ptr为被唤醒的高优先级线程 2、线程优先级降低,降低后已经不是最高优先级
275                 
276 
277                     /* Now determine if this thread's preemption-threshold needs to be enforced.  */
278                     if (thread_ptr -> tx_thread_preempt_threshold < thread_ptr -> tx_thread_priority) // thread_ptr启用了抢占,需要检查thread_ptr是否可以抢占next_execute_ptr(如果thread_ptr是当前释放互斥锁的线程,thread_ptr本来就是抢占了一些其他高优先级的线程,因为挂起恢复操作,内核选择了其他被抢占的高优先级线程执行,那么是不合理的,需要让thread_ptr继续抢占其他高优先级线程;如果有更高优先级线程被唤醒,且优先级高于thread_ptr的抢占阈值,那么thread_ptr需要标记被抢占)
279                     
280 
281                         /* Yes, preemption-threshold is in force for this thread. */
282 
283                         /* Compare the next thread to execute thread's priority against the thread's preemption-threshold.  */
284                         if (thread_ptr -> tx_thread_preempt_threshold <= next_execute_ptr -> tx_thread_priority) // thread_ptr的抢占阈值高于next_execute_ptr,thread_ptr抢占next_execute_ptr
285                         
286                 
287                             /* We must swap execute pointers to enforce the preemption-threshold of a thread coming out of
288                                priority inheritance.  */
289                             _tx_thread_execute_ptr =  thread_ptr;
290 
291                             /* Determine if we moved to a lower priority. If so, move the thread to the front of its priority list.  */
292                             if (original_priority < new_priority) // 这里升高优先级也需要考虑,还有疑问,等待社区回复!!!
293                             
294                         
295                                 /* Ensure that this thread is placed at the front of the priority list.  */
296                                 _tx_thread_priority_list[thread_ptr -> tx_thread_priority] =  thread_ptr;
297                             
298                         
299 
300 #ifndef TX_DISABLE_PREEMPTION_THRESHOLD
301 
302                         else // 下面的抢占标记似乎应该保证thread_ptr在链表表头,这个问题待社区回复(阅读threadx-6.1.2代码的时候,发现这个标记也有问题,然后查看官网最新代码已经修复了,写文章时顺道改了,旧的代码标记的是next_execute_ptr,实际是thread_ptr被抢占了,不是next_execute_ptr被抢占)
303                         
304 
305                             /* In this case, we need to mark the preempted map to indicate a thread executed above the
306                                preemption-threshold.  */
307 
308 #if TX_MAX_PRIORITIES > 32
309 
310                             /* Calculate the index into the bit map array.  */
311                             map_index =  (thread_ptr -> tx_thread_priority)/ ((UINT) 32);
312 
313                             /* Set the active bit to remember that the preempt map has something set.  */
314                             TX_DIV32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit)
315                             _tx_thread_preempted_map_active =  _tx_thread_preempted_map_active | priority_bit;
316 #endif
317 
318                             /* Remember that this thread was preempted by a thread above the thread's threshold.  */
319                             TX_MOD32_BIT_SET(thread_ptr -> tx_thread_priority, priority_bit)
320                             _tx_thread_preempted_maps[MAP_INDEX] =  _tx_thread_preempted_maps[MAP_INDEX] | priority_bit;
321                         
322 #endif
323                     
324                 
325             
326         
327 
328 #ifndef TX_NOT_INTERRUPTABLE
329         
330         /* Restore interrupts.  */
331         TX_RESTORE
332 #endif
333     
334 
335 

3、互斥锁释放_tx_mutex_put

互斥锁释放与互斥锁申请类似,因为互斥锁是可多次获取的,因此释放互斥锁也是要对互斥锁计数器减1,如果为0,才是真正释放互斥锁,因为存在继承优先级,释放互斥锁线程当前运行的优先级并不一定是创建时的优先级,如果没有占用其他互斥锁(不需要继承互斥锁优先级),那么就需要恢复创建时的优先级,如果还有占用其他线程,那么需要继承其他等待互斥锁线程的最高优先级,调整优先级跟获取互斥锁调整优先级一样的,前面小结已经介绍;

继承优先级,释放互斥锁时,是将互斥锁直接给等待互斥锁的最高优先级线程,也就是优先级高的线程先获取到互斥锁。

_tx_mutex_put实现代码如下:

047 UINT  _tx_mutex_put(TX_MUTEX *mutex_ptr)
048 
049 
050 TX_INTERRUPT_SAVE_AREA
051 
052 TX_THREAD       *thread_ptr;
053 TX_THREAD       *old_owner;
054 UINT            old_priority;
055 UINT            status;
056 TX_MUTEX        *next_mutex;
057 TX_MUTEX        *previous_mutex;
058 UINT            owned_count;
059 UINT            suspended_count;
060 TX_THREAD       *current_thread;
061 TX_THREAD       *next_thread;
062 TX_THREAD       *previous_thread;
063 TX_THREAD       *suspended_thread;
064 UINT            inheritance_priority;
065 
066 
067     /* Setup status to indicate the processing is not complete.  */
068     status =  TX_NOT_DONE;
069 
070     /* Disable interrupts to put an instance back to the mutex.  */
071     TX_DISABLE
072 
073 #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
074 
075     /* Increment the total mutex put counter.  */
076     _tx_mutex_performance_put_count++;
077 
078     /* Increment the number of attempts to put this mutex.  */
079     mutex_ptr -> tx_mutex_performance_put_count++;
080 #endif
081 
082     /* If trace is enabled, insert this event into the trace buffer.  */
083     TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_PUT, mutex_ptr, TX_POINTER_TO_ULONG_CONVERT(mutex_ptr -> tx_mutex_owner), mutex_ptr -> tx_mutex_ownership_count, TX_POINTER_TO_ULONG_CONVERT(&old_priority), TX_TRACE_MUTEX_EVENTS)
084 
085     /* Log this kernel call.  */
086     TX_EL_MUTEX_PUT_INSERT
087 
088     /* Determine if this mutex is owned.  */
089     if (mutex_ptr -> tx_mutex_ownership_count != ((UINT) 0)) // 互斥锁计数器不为0才被占用
090     
091 
092         /* Pickup the owning thread pointer.  */
093         thread_ptr =  mutex_ptr -> tx_mutex_owner; // 获取占用互斥锁的线程
094 
095         /* Pickup thread pointer.  */
096         TX_THREAD_GET_CURRENT(current_thread) // 获取当前线程
097 
098         /* Check to see if the mutex is owned by the calling thread.  */
099         if (mutex_ptr -> tx_mutex_owner != current_thread) // 如果占用互斥锁的线程不是当前线程,设置状态为TX_NOT_OWNED,不能释放别的线程占用的互斥锁,返回
100         
101         
102             /* Determine if the preempt disable flag is set, indicating that 
103                the caller is not the application but from ThreadX. In such
104                cases, the thread mutex owner does not need to match.  */
105             if (_tx_thread_preempt_disable == ((UINT) 0)) // _tx_thread_preempt_disable为0表示是应用程序调用,应用程序不能释放其他线程占用的互斥锁
106             
107 
108                 /* Invalid mutex release.  */
109 
110                 /* Restore interrupts.  */
111                 TX_RESTORE
112 
113                 /* Caller does not own the mutex.  */
114                 status =  TX_NOT_OWNED;
115             
116         
117         
118         /* Determine if we should continue.  */
119         if (status == TX_NOT_DONE)
120         
121     
122             /* Decrement the mutex ownership count.  */
123             mutex_ptr -> tx_mutex_ownership_count--; // 互斥锁计数器减1
124 
125             /* Determine if the mutex is still owned by the current thread.  */
126             if (mutex_ptr -> tx_mutex_ownership_count != ((UINT) 0)) // 互斥锁嵌套占用,没有真正释放,设置状态为TX_SUCCESS,返回即可
127             
128 
129                 /* Restore interrupts.  */
130                 TX_RESTORE
131 
132                 /* Mutex is still owned, just return successful status.  */
133                 status =  TX_SUCCESS;
134             
135             else // 互斥锁被释放
136             
137 
138                 /* Check for a NULL thread pointer, which can only happen during initialization.   */
139                 if (thread_ptr == TX_NULL) // 内核初始化过程释放互斥锁,不需要处理
140                 
141 
142                     /* Restore interrupts.  */
143                     TX_RESTORE
144 
145                     /* Mutex is now available, return successful status.  */
146                     status =  TX_SUCCESS;
147                 
148                 else // 线程释放互斥锁
149                 
150 
151                     /* The mutex is now available.   */
152             
153                     /* Remove this mutex from the owned mutex list.  */
154                     
155                     /* Decrement the ownership count.  */
156                     thread_ptr -> tx_thread_owned_mutex_count--; // 线程占用的互斥锁个数减1
157 
158                     /* Determine if this mutex was the only one on the list.  */
159                     if (thread_ptr -> tx_thread_owned_mutex_count == ((UINT) 0)) // 占用的互斥锁个数为0,占用互斥锁链表tx_thread_owned_mutex_list设置为0即可
160                     
161 
162                         /* Yes, the list is empty.  Simply set the head pointer to NULL.  */
163                         thread_ptr -> tx_thread_owned_mutex_list =  TX_NULL;
164                     
165                     else // 将释放的互斥锁从tx_thread_owned_mutex_list删除
166                     
167 
168                         /* No, there are more mutexes on the list.  */
169 
170                         /* Link-up the neighbors.  */
171                         next_mutex =                             mutex_ptr -> tx_mutex_owned_next;
172                         previous_mutex =                         mutex_ptr -> tx_mutex_owned_previous;
173                         next_mutex -> tx_mutex_owned_previous =  previous_mutex;
174                         previous_mutex -> tx_mutex_owned_next =  next_mutex;
175 
176                         /* See if we have to update the created list head pointer.  */
177                         if (thread_ptr -> tx_thread_owned_mutex_list == mutex_ptr)
178                         
179 
180                             /* Yes, move the head pointer to the next link. */
181                             thread_ptr -> tx_thread_owned_mutex_list =  next_mutex;
182                         
183                     
184 
185                     /* Determine if the simple, non-suspension, non-priority inheritance case is present.  */
186                     if (mutex_ptr -> tx_mutex_suspension_list == TX_NULL) // 没有等待互斥锁的线程
187                     
188                     
189                         /* Is this a priority inheritance mutex?  */
190                         if (mutex_ptr -> tx_mutex_inherit == TX_FALSE) // 如果没有继承优先级(占用互斥锁的线程不会动态调整优先级),返回即可
191                         
192 
193                             /* Yes, we are done - set the mutex owner to NULL.   */
194                             mutex_ptr -> tx_mutex_owner =  TX_NULL;
195                             
196                             /* Restore interrupts.  */
197                             TX_RESTORE
198 
199                             /* Mutex is now available, return successful status.  */
200                             status =  TX_SUCCESS;
201                         
202                     
203                      
204                     /* Determine if the processing is complete.  */
205                     if (status == TX_NOT_DONE) // 有等待互斥锁的线程或者有继承优先级(需要还原优先级)
206                     
207    
208                         /* Initialize original owner and thread priority.  */
209                         old_owner =      TX_NULL;
210                         old_priority =   thread_ptr -> tx_thread_user_priority;
211 
212                         /* Does this mutex support priority inheritance?  */
213                         if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) // 互斥锁支持继承优先级(if分支获取继承的优先级,如果继承的优先级比线程创建时的优先级还低,那么恢复到线程创建时的优先级(先记录,if后面恢复))
214                         
215 
216 #ifndef TX_NOT_INTERRUPTABLE
217 
218                             /* Temporarily disable preemption.  */
219                             _tx_thread_preempt_disable++; // 禁止抢占
220 
221                             /* Restore interrupts.  */
222                             TX_RESTORE // 允许中断(抢占被禁止了,中断服务程序不会操作互斥锁相关的数据,所以可以允许中断)
223 #endif
224 
225                             /* Default the inheritance priority to disabled.  */
226                             inheritance_priority =  ((UINT) TX_MAX_PRIORITIES); // 继承的优先级
227                             
228                             /* Search the owned mutexes for this thread to determine the highest priority for this 
229                                former mutex owner to return to.  */
230                             next_mutex =  thread_ptr -> tx_thread_owned_mutex_list; // 下一个互斥锁
231                             while (next_mutex != TX_NULL) // 遍历互斥锁链表(查找当前线程需要继承的最高优先级)
232                             
233 
234                                 /* Does this mutex support priority inheritance?  */
235                                 if (next_mutex -> tx_mutex_inherit == TX_TRUE) // next_mutex支持继承优先级
236                                 
237                             
238                                     /* Determine if highest priority field of the mutex is higher than the priority to 
239                                        restore.  */
240                                     if (next_mutex -> tx_mutex_highest_priority_waiting < inheritance_priority) // next_mutex等待互斥锁的线程的最高优先级高于inheritance_priority
241                                     
242 
243                                         /* Use this priority to return releasing thread to.  */
244                                         inheritance_priority =   next_mutex -> tx_mutex_highest_priority_waiting; // inheritance_priority更新为继承的最高优先级
245                                     
246                                 
247 
248                                 /* Move mutex pointer to the next mutex in the list.  */
249                                 next_mutex =  next_mutex -> tx_mutex_owned_next;
250 
251                                 /* Are we at the end of the list?  */
252                                 if (next_mutex == thread_ptr -> tx_thread_owned_mutex_list)
253                                 
254                             
255                                     /* Yes, set the next mutex to NULL.  */
256                                     next_mutex =  TX_NULL;
257                                 
258                             
259 
260 #ifndef TX_NOT_INTERRUPTABLE
261 
262                             /* Disable interrupts.  */
263                             TX_DISABLE // 关闭中断(可能中断会影响后面的代码或者性能,并且后面很快就会允许中断,所以禁止中断)
264 
265                             /* Undo the temporarily preemption disable.  */
266                             _tx_thread_preempt_disable--; // 取消临时的禁止抢占
267 #endif
268                        
269                             /* Set the inherit priority to that of the highest priority thread waiting on the mutex.  */
270                             thread_ptr -> tx_thread_inherit_priority =  inheritance_priority; // 设置线程继承优先级
271                                 
272                             /* Determine if the inheritance priority is less than the default old priority.  */
273                             if (inheritance_priority < old_priority) // 如果继承的优先级高于线程创建时指定的优先级,那么使用继承优先级做为线程的优先级(old_priority在后面会用于调整线程的优先级),否则释放互斥锁锁后恢复到线程创建时的优先级
274                             
275                             
276                                 /* Yes, update the old priority.  */
277                                 old_priority =  inheritance_priority;
278                             
279                         
280 
281                         /* Determine if priority inheritance is in effect and there are one or more
282                            threads suspended on the mutex.  */
283                         if (mutex_ptr -> tx_mutex_suspended_count > ((UINT) 1)) // 有多于1个线程等待互斥锁mutex_ptr,并且互斥锁有优先级继承,那么需要唤醒最高优先级的等待线程
284                         
285 
286                             /* Is priority inheritance in effect?  */
287                             if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
288                             
289 
290                                 /* Yes, this code is simply to ensure the highest priority thread is positioned
291                                    at the front of the suspension list.  */
292 
293 #ifndef TX_NOT_INTERRUPTABLE
294 
295                                 /* Temporarily disable preemption.  */
296                                 _tx_thread_preempt_disable++; // 禁止抢占(后面对等待互斥锁的线程链表进行处理,如果允许抢占的话,有等待互斥锁的线程超时的话,超时回调函数也会操作链表,就保证不了对链表的互斥操作)
297 
298                                 /* Restore interrupts.  */
299                                 TX_RESTORE // 允许中断(后面把等待互斥锁的最高优先级线程移动到链表前面需要一些时间,需要允许中断,否则定时器中断就不能及时响应)
300 #endif
301 
302                                 /* Call the mutex prioritize processing to ensure the 
303                                    highest priority thread is resumed.  */
304 #ifdef TX_MISRA_ENABLE
305                                 do
306                                 
307                                     status =  _tx_mutex_prioritize(mutex_ptr);
308                                  while (status != TX_SUCCESS);
309 #else
310                                 _tx_mutex_prioritize(mutex_ptr); // 将等待互斥锁线程的最高优先级线程移动到等待链表前面(优先级高的线程先获取到互斥锁)
311 #endif
312 
313                                 /* At this point, the highest priority thread is at the
314                                    front of the suspension list.  */
315 
316                                 /* Optional processing extension.  */
317                                 TX_MUTEX_PUT_EXTENSION_1
318 
319 #ifndef TX_NOT_INTERRUPTABLE
320 
321                                 /* Disable interrupts.  */
322                                 TX_DISABLE
323 
324                                 /* Back off the preemption disable.  */
325                                 _tx_thread_preempt_disable--;
326 #endif
327                             
328                         
329 
330                         /* Now determine if there are any threads still waiting on the mutex.  */
331                         if (mutex_ptr -> tx_mutex_suspension_list == TX_NULL) // 检查是否有线程仍然在等待互斥锁(前面检查过tx_mutex_suspension_list不为空,目前互斥锁等待超时是在超时线程里面处理,如果互斥锁超时在中断服务程序里面处理,那么tx_mutex_suspension_list倒可能被修改,暂时没看到其他场景,正常情况这里不会为空,先略过...)
332                         
333 
334                             /* No, there are no longer any threads waiting on the mutex.  */
335 
336 #ifndef TX_NOT_INTERRUPTABLE
337 
338                             /* Temporarily disable preemption.  */
339                             _tx_thread_preempt_disable++;
340 
341                             /* Restore interrupts.  */
342                             TX_RESTORE
343 #endif
344 
345                             /* Mutex is not owned, but it is possible that a thread that 
346                                caused a priority inheritance to occur is no longer waiting
347                                on the mutex.  */
348 
349                             /* Setup the highest priority waiting thread.  */
350                             mutex_ptr -> tx_mutex_highest_priority_waiting =  (UINT) TX_MAX_PRIORITIES; // 没有等待互斥锁的线程,等待互斥锁线程的最高优先级设置为默认优先级TX_MAX_PRIORITIES
351   
352                             /* Determine if we need to restore priority.  */
353                             if ((mutex_ptr -> tx_mutex_owner) -> tx_thread_priority != old_priority) // (mutex_ptr -> tx_mutex_owner) -> tx_thread_priority记录占用互斥锁线程运行时的优先级,old_priority为前面检查出来的等待互斥锁线程的最高优先级或者线程创建时的优先级,也就是释放互斥锁后,线程该恢复的优先级,如果当前的优先级与要恢复的优先级不同,那么就调用_tx_mutex_priority_change调整/恢复线程优先级,mutex_ptr -> tx_mutex_owner前面已经检查了,就是current_thread
354                             
355                       
356                                 /* Yes, restore the priority of thread.  */
357                                 _tx_mutex_priority_change(mutex_ptr -> tx_mutex_owner, old_priority); // 恢复线程创建时的优先级或者继承的最高优先级
358                             
359 
360 #ifndef TX_NOT_INTERRUPTABLE
361 
362                             /* Disable interrupts again.  */
363                             TX_DISABLE
364 
365                             /* Back off the preemption disable.  */
366                             _tx_thread_preempt_disable--;
367 #endif
368 
369                             /* Set the mutex owner to NULL.  */
370                             mutex_ptr -> tx_mutex_owner =  TX_NULL;
371 
372                             /* Restore interrupts.  */
373                             TX_RESTORE
374 
375                             /* Check for preemption.  */
376                             _tx_thread_system_preempt_check(); // 这里基本已经释放完了互斥锁,后续也没有其他操作要进行,因为前面禁止了抢占,释放互斥锁的上一级函数不会检查抢占,禁止抢占的过程中,可能有更高优先级线程就绪,所以在这里检查抢占,如果有被抢占的话,那么要重新调度
377 
378                             /* Set status to success.  */
379                             status =  TX_SUCCESS;
380                         
381                         else // 有线程等待互斥锁
382                         
383 
384                             /* Pickup the thread at the front of the suspension list.  */
385                             thread_ptr =  mutex_ptr -> tx_mutex_suspension_list; // 获取等待互斥锁的最高优先级线程(前面已经将最高优先级线程移动到表头了)
386 
387                             /* Save the previous ownership information, if inheritance is
388                                in effect.  */
389                             if (mutex_ptr -> tx_mutex_inherit == TX_TRUE) // 继承优先级
390                             
391 
392                                 /* Remember the old mutex owner.  */
393                                 old_owner =  mutex_ptr -> tx_mutex_owner; // 记录旧的占用互斥锁的线程
394         
395                                 /* Setup owner thread priority information.  */
396                                 mutex_ptr -> tx_mutex_original_priority =   thread_ptr -> tx_thread_priority; // 记录thread_ptr的原始优先级(thread_ptr即将获得互斥锁,因为继承优先级的关系,thread_ptr可能会改变优先级)
397 
398                                 /* Setup the highest priority waiting thread.  */
399                                 mutex_ptr -> tx_mutex_highest_priority_waiting =  (UINT) TX_MAX_PRIORITIES;
400                             
401 
402                             /* Determine how many mutexes are owned by this thread.  */
403                             owned_count =  thread_ptr -> tx_thread_owned_mutex_count; // thread_ptr之前占用多少互斥锁(互斥锁嵌套,线程可能占用多个互斥锁)
404 
405                             /* Determine if this thread owns any other mutexes that have priority inheritance.  */
406                             if (owned_count == ((UINT) 0)) // thread_ptr没有占用其他线程,那么当前互斥锁就是该线程唯一获得的互斥锁,一个互斥锁组成一个链表(线程占用互斥锁的链表tx_thread_owned_mutex_list)
407                             
408 
409                                 /* The owned mutex list is empty.  Add mutex to empty list.  */
410                                 thread_ptr -> tx_thread_owned_mutex_list =     mutex_ptr;
411                                 mutex_ptr -> tx_mutex_owned_next =             mutex_ptr;
412                                 mutex_ptr -> tx_mutex_owned_previous =         mutex_ptr;
413                             
414                             else // 将互斥锁加入旧的占用互斥锁链表tx_thread_owned_mutex_list
415                             
416 
417                                 /* Non-empty list. Link up the mutex.  */
418 
419                                 /* Pickup tail pointer.  */
420                                 next_mutex =                            thread_ptr -> tx_thread_owned_mutex_list;
421                                 previous_mutex =                        next_mutex -> tx_mutex_owned_previous; // previous_mutex第一个节点的前一个节点,也就是尾节点
422 
423                                 /* Place the owned mutex in the list.  */
424                                 next_mutex -> tx_mutex_owned_previous =  mutex_ptr;
425                                 previous_mutex -> tx_mutex_owned_next =  mutex_ptr;
426 
427                                 /* Setup this mutex's next and previous created links.  */
428                                 mutex_ptr -> tx_mutex_owned_previous =   previous_mutex;
429                                 mutex_ptr -> tx_mutex_owned_next =       next_mutex;
430                             
431 
432                             /* Increment the number of mutexes owned counter.  */
433                             thread_ptr -> tx_thread_owned_mutex_count =  owned_count + ((UINT) 1); // thread_ptr占用互斥锁个数加1(释放互斥锁的时候,直接将互斥锁给thread_ptr,不需要唤醒所有等待互斥锁的线程,让这些线程去抢占互斥锁)
434 
435                             /* Mark the Mutex as owned and fill in the corresponding information.  */
436                             mutex_ptr -> tx_mutex_ownership_count =  (UINT) 1; // mutex_ptr第一次获取到互斥锁mutex_ptr
437                             mutex_ptr -> tx_mutex_owner =            thread_ptr; // 互斥锁mutex_ptr被线程thread_ptr占用
438 
439                             /* Remove the suspended thread from the list.  */
440 
441                             /* Decrement the suspension count.  */
442                             mutex_ptr -> tx_mutex_suspended_count--

以上是关于ThreadX内核源码分析 - 线程同步之互斥锁及动态优先级的主要内容,如果未能解决你的问题,请参考以下文章

ThreadX内核源码分析(SMP) - 核间互斥(arm)

ThreadX内核源码分析 - 计数信号量

ThreadX内核源码分析 - 定时器及线程时间片调度(arm)

ThreadX内核源码分析 - 定时器及线程时间片调度(arm)

ThreadX内核源码分析 - ports线程上下文相关代码分析(arm)

ThreadX内核源码分析 - 事件