UEFI下的优先级
UEFI SPEC中定义了如下几种优先级:
对应到EDK代码中是一个整型,如下所示:
//
// Task priority level
//
#define TPL_APPLICATION 4
#define TPL_CALLBACK 8
#define TPL_NOTIFY 16
#define TPL_HIGH_LEVEL 31
关于优先级有以下需要注意的点:
1. 优先级是与Boot Service同时存在的,因此在PEI阶段,以及ExitBootServices事件之后都没有意义了;
2. 目前提供给外部接口使用的只有三种优先级:TPL_APPLICATION、TPL_CALLBACK和TPL_NOTIFY,它们的优先级依次增加;至于TPL_HIGH_LEVEL以及其它没有具体名称的优先级是供内部使用的,一般代码不应该去使用;
3. 高优先级的任务可以打断低优先级的任务;
4. 高优先级的任务执行的时间要求越短,否则就可能导致异常;
5. TPL_APPLICATION是通常代码下的优先级,TPL_HIGH_LEVEL是最高优先级无法被中断;
6. 通常是事件来触发更好的优先级代码的执行;
关于目前各个模块(Protocol)的优先级可以在UEFI SPEC中找到,这里不再列举。
优先级的操作函数
Boot Services中提供了两个接口用来操作优先级:
typedef
EFI_BOOTSERVICE
EFI_TPL
(EFIAPI *EFI_RAISE_TPL) (
IN EFI_TPL NewTpl
);
typedef
EFI_BOOTSERVICE
VOID
(EFIAPI *EFI_RESTORE_TPL) (
IN EFI_TPL OldTpl
);
前者用来设置当前的优先级并返回原始的优先级;
后者恢复到原来的优先级。
两个函数配合使用,可以自行提供当前的优先级以防止代码被打断。
下面是一个例子,代码来自Ping.c:
/**
Get the timer period of the system.
This function tries to get the system timer period by creating
an 1ms period timer.
@return System timer period in MS, or 0 if operation failed.
**/
UINT32
GetTimerPeriod(
VOID
)
{
EFI_STATUS Status;
UINT32 RttTimerTick;
EFI_EVENT TimerEvent;
UINT32 StallCounter;
EFI_TPL OldTpl;
RttTimerTick = 0;
StallCounter = 0;
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
RttTimerTickRoutine,
&RttTimerTick,
&TimerEvent
);
if (EFI_ERROR (Status)) {
return 0;
}
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
Status = gBS->SetTimer (
TimerEvent,
TimerPeriodic,
TICKS_PER_MS
);
if (EFI_ERROR (Status)) {
gBS->CloseEvent (TimerEvent);
return 0;
}
while (RttTimerTick < 10) {
gBS->Stall (STALL_1_MILLI_SECOND);
++StallCounter;
}
gBS->RestoreTPL (OldTpl);
gBS->SetTimer (TimerEvent, TimerCancel, 0);
gBS->CloseEvent (TimerEvent);
return StallCounter / RttTimerTick;
}
除了上述的两个基本函数,还有其它的函数也会用到,比如说创建事件的函数:
/**
Creates an event.
@param[in] Type The type of event to create and its mode and attributes.
@param[in] NotifyTpl The task priority level of event notifications, if needed.
@param[in] NotifyFunction The pointer to the event's notification function, if any.
@param[in] NotifyContext The pointer to the notification function's context; corresponds to parameter
Context in the notification function.
@param[out] Event The pointer to the newly created event if the call succeeds; undefined
otherwise.
@retval EFI_SUCCESS The event structure was created.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The event could not be allocated.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_CREATE_EVENT)(
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction,
IN VOID *NotifyContext,
OUT EFI_EVENT *Event
);
这里的优先级表示了回调函数的优先级。