UEFI.源码分析.DXE的异步事件服务.第二部分.任务优先级
Posted 木艮氵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UEFI.源码分析.DXE的异步事件服务.第二部分.任务优先级相关的知识,希望对你有一定的参考价值。
任务优先级简述
典型的优先级有四种
/** MdePkg/Include/Uefi/UefiSpec.h **/
585 //
586 // Task priority level
587 //
588 #define TPL_APPLICATION 4
589 #define TPL_CALLBACK 8
590 #define TPL_NOTIFY 16
591 #define TPL_HIGH_LEVEL 31
在Event.h
中还提供了一个宏来判断合法
20 #define VALID_TPL(a) ((a) <= TPL_HIGH_LEVEL)
第一部分中的gEventPending
则是一个UINTN
类型的变量
21 extern UINTN gEventPending;
对于UINTN
的定义,依赖于体系结构
MdePkg/Include/X64/ProcessorBind.h:237:typedef UINT64 UINTN;
MdePkg/Include/Ia32/ProcessorBind.h:224:typedef UINT32 UINTN;
在Event.c
中则使用全局变量保存了当前优先级
23 EFI_TPL gEfiCurrentTpl = TPL_APPLICATION;
接口
提高优先级RaiseTpl
/** /Dxe/Event/Tpl.c **/
59 EFI_TPL
60 EFIAPI
61 CoreRaiseTpl (
62 IN EFI_TPL NewTpl
63 )
64
保证优先级是不降低的,并检查合法性
67 OldTpl = gEfiCurrentTpl;
68 if (OldTpl > NewTpl)
69 DEBUG ((EFI_D_ERROR, "FATAL ERROR
70 ASSERT (FALSE);
71
72 ASSERT (VALID_TPL (NewTpl));
若新优先级超过或等于TPL_HIGH_LEVEL
,且原优先级低于TPL_HIGH_LEVEL
,则关闭中断
77 if (NewTpl >= TPL_HIGH_LEVEL && OldTpl < TPL_HIGH_LEVEL)
78 CoreSetInterruptState (FALSE);
79
更新全局变量gEfiCurrentTpl
84 gEfiCurrentTpl = NewTpl;
85
86 return OldTpl;
87
恢复优先级RestoreTpl
/** /Dxe/Event/Tpl.c **/
99 VOID
100 EFIAPI
101 CoreRestoreTpl (
102 IN EFI_TPL NewTpl
103 )
104
保证是不提升的,并检查合法性
107 OldTpl = gEfiCurrentTpl;
108 if (NewTpl > OldTpl)
109 DEBUG ((EFI_D_ERROR, "FATAL
110 ASSERT (FALSE);
111
112 ASSERT (VALID_TPL (NewTpl));
根据gEventPending
来执行回调函数
126 while (((-2 << NewTpl) & gEventPending) != 0)
127 gEfiCurrentTpl = (UINTN) HighBitSet64 (gEventPending);
128 if (gEfiCurrentTpl < TPL_HIGH_LEVEL)
129 CoreSetInterruptState (TRUE);
130
131 CoreDispatchEventNotifies (gEfiCurrentTpl);
132
注意到gEventPending
在置为1
的时候是这样的
gEventPending |= (UINTN)(1 << Event->NotifyTpl);
函数HighBitSet64
是通过调用HighBitSet32
来实现的,即返回最高位为1
的索引
34 INTN
35 EFIAPI
36 HighBitSet32 (
37 IN UINT32 Operand
38 )
39
40 INTN BitIndex;
41
42 if (Operand == 0)
43 return - 1;
44
45 for (BitIndex = 31; (INT32)Operand > 0; BitIndex--, Operand <<= 1);
46 return BitIndex;
47
操作(-2 << NewTpl) & gEventPending
会将低于NewTpl
的位屏蔽。
故实际上只会调度执行低于NewTpl
的事件的回调函数。
最后恢复gEfiCurrentTpl
并恢复中断状态
138 gEfiCurrentTpl = NewTpl;
139
140 //
141 // If lowering below HIGH_LEVEL, make sur
142 // interrupts are enabled
143 //
144 if (gEfiCurrentTpl < TPL_HIGH_LEVEL)
145 CoreSetInterruptState (TRUE);
146
总结
RaiseTpl
在提升到TPL_HIGH_LEVEL
以上时会关中断RestoreTpl
在降低时会调度执行事件的回调函数,且只会调度执行高于或等于原优先级的事件的回调函数- 默认的优先级是
TPL_APPLICATION
即最低优先级,所以此时的RestoreTpl
实际上会调度执行所有的回调函数 - 在时钟中断的开始会
RaiseTpl(TPL_HIGH_LEVEL)
实际上也就关了中断
以上是关于UEFI.源码分析.DXE的异步事件服务.第二部分.任务优先级的主要内容,如果未能解决你的问题,请参考以下文章
UEFI.源码分析.DXE的异步事件服务.第一部分.事件驱动
UEFI.源码分析.DXE的异步事件服务.第一部分.事件驱动
UEFI.源码分析.DXE的异步事件服务.第三部分.定时器与时钟中断