(NucleusPlus非开源操作系统,仅提供有限代码供参考理解)
1、NucleusPlus protection机制
NucleusPlus内核对小段代码保护使用TC_PROTECT进行保护,只有在TC_PROTECT操作时才会关中断,因此NucleusPlus内核中断响应及调度相对与μC/OS-III、ThreadX更及时;互斥锁仅用于应用程序(线程间的互斥)。
TC_PROTECT包含两个成员,一个记录获取到TC_PROTECT的线程指针tc_tcb_pointer,另外一个标记是否有线程正在等待TC_PROTECT的变量tc_thread_waiting。
2、TC_PROTECT获取(TCT_Protect)
关中断
1624 MRS r1,CPSR // Pickup current CPSR
1625 ORR r1,r1,#LOCKOUT // Place lockout value in
1626 MSR CPSR_cxsf,r1 // Lockout interrupts
检查TC_PROTECT是否被占用(检查tc_tcb_pointer是否为空;如果没有被占用则跳转到TCT_Protect_Available,设置tc_tcb_pointer为当前线程指针,再次开启中断即可;如果被占用,则不断检查是否被占用,类似linux内核的自旋锁,不过NucleusPlus是单核的,因此当前线程要切换出cpu)
1632 TCT_Protect_Loop:
1633 LDR r1,[r0, #0] // Pickup protection owner field
1634 CMP r1,#0 // Is there any protection?
1635 BEQ TCT_Protect_Available // If NU_NULL, no current protection
设置tc_thread_waiting为1(表示有线程在等待TC_PROTECT)
1642 MOV r2,#1 // Build thread waiting flag
1643 STR r2,[r0, #4] // Set waiting field
如果TC_PROTECT被占用,保存当前线程的上下文,调用TCT_Schedule_Protected调度占用TC_PROTECT的线程(当前线程为最高优先级的线程,占有TC_PROTECT的线程的优先级更低,不主动调度低优先级线程的话,低优先级线程永远没办法执行,TC_PROTECT永远不会被释放)
1648 STR r0,[sp, #-4]! // Save r0 on the stack
1649 STR lr,[sp, #-4]! // Save lr on the stack
1650 MOV r0,r3 // Place current thread into r0
1651 BL TCT_Schedule_Protected // Call routine to schedule the
1652 // owner of the thread
3、TC_PROTECT释放(TCT_Unprotect)
检查tc_thread_waiting是否为0,如果为0,则没有线程在等待TC_PROTECT,否则有更高优先级线程在等待TC_PROTECT(TC_PROTECT获取后到释放过程是没有关中断的,在没有释放TC_PROTECT前,有可能有更高优先级就绪,高优先级线程申请同一个TC_PROTECT);如果没有线程等待TCT_Unprotect,则简单设置tc_tcb_pointer为空,开启中断即可;否则调用TCT_Control_To_System进行重新调度(等待TCT_Unprotect的线程此时不一定是优先级最高的线程,由调度程序获取最高优先级就绪线程执行);
TCT_Control_To_System检查当前线程时间片是否用完;如果没有用完,则继续执行当前线程(避免频繁切换线程,因此在调用TCT_Control_To_System前并没有设置tc_tcb_pointer为空);如果时间片用完了,则设置tc_tcb_pointer为空、tc_thread_waiting为0(之前等待TC_PROTECT释放的线程,此时已经不是等待TC_PROTECT了,线程被调度后,回到TCT_Protect_Loop时,相当于重新调用了TCT_Protect,重新获取锁(由于某些原因等待TC_PROTECT释放的线程被挂起了,tc_thread_waiting标志不能一直被设置为1,否则别的线程释放TC_PROTECT时会误以为有线程在等待TC_PROTECT释放)),调用TCT_Schedule选择最高优先级就绪线程执行。(线程调度参考NucleusPlus中断处理(基于ARM处理器)_tct中断控制-CSDN博客 “NucleusPlus中断处理(基于ARM处理器)”)
1783 LDR r2,[r0, #4] // Pickup thread waiting flag
1784 CMP r2,#0 // Are there any threads waiting?
1785 BEQ TCT_Not_Waiting_Unpr // If not, just release protection
4、总结
NucleusPlus的Protect机制一定程度上可以看作是优先级反转,即高优先级线程让出cpu给低优先级线程执行。NucleusPlus没有实现动态优先级,Protect避免了死锁的情况发生。