UEFI.源码分析.DXE的异步事件服务.第三部分.定时器与时钟中断
Posted 木艮氵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UEFI.源码分析.DXE的异步事件服务.第三部分.定时器与时钟中断相关的知识,希望对你有一定的参考价值。
- 源代码:EDK2
- 版本:UDK2017
- UEFI源码分析第二篇,异步事件服务
- 第三部分,定时器
- 第一部分,事件驱动
- 第二部分,任务优先级
设置定时器EVT_TIMER
244 EFI_STATUS
245 EFIAPI
246 CoreSetTimer (
247 IN EFI_EVENT UserEvent,
248 IN EFI_TIMER_DELAY Type,
249 IN UINT64 TriggerTime
250 )
函数CoreSetTimer
将定时器类型的事件设置好超时时间,也就是更新Event->Timer
域
273 if (Event->Timer.Link.ForwardLink != NULL)
274 RemoveEntryList (&Event->Timer.Link);
275 Event->Timer.Link.ForwardLink = NULL;
276
进一步调用CoreInsertEventTimer
将定时器设置好。
281 if (Type != TimerCancel)
282
283 if (Type == TimerPeriodic)
284 if (TriggerTime == 0)
285 gTimer->GetTimerPeriod (gTimer, &TriggerTime);
286
287 Event->Timer.Period = TriggerTime;
288
289
290 Event->Timer.TriggerTime = CoreCurrentSystemTime () + TriggerTime;
291 CoreInsertEventTimer (Event);
292
293 if (TriggerTime == 0)
294 CoreSignalEvent (mEfiCheckTimerEvent);
295
296
函数CoreInsertEventTimer
如下
40 VOID
41 CoreInsertEventTimer (
42 IN IEVENT *Event
43 )
44
54 TriggerTime = Event->Timer.TriggerTime;
59 for (Link = mEfiTimerList.ForwardLink; Link != &mEfiTimerList; Link = Link->ForwardLink)
60 Event2 = CR (Link, IEVENT, Timer.Link, EVENT_SIGNATURE);
61
62 if (Event2->Timer.TriggerTime > TriggerTime)
63 break;
64
65
66
67 InsertTailList (Link, &Event->Timer.Link);
68
将定时器按序插入到全局变量mEfiTimerList
中。
时钟中断
在DXE阶段初始化事件服务时,会调用CoreInitializeEventServices
/** /Dxe/Event/Event.c **/
130 EFI_STATUS
131 CoreInitializeEventServices (
132 VOID
133 )
134
135 UINTN Index;
136
137 for (Index=0; Index <= TPL_HIGH_LEVEL; Index++)
138 InitializeListHead (&gEventQueue[Index]);
139
140
141 CoreInitializeTimer ();
142
143 CoreCreateEventEx (
144 EVT_NOTIFY_SIGNAL,
145 TPL_NOTIFY,
146 EfiEventEmptyFunction,
147 NULL,
148 &gIdleLoopEventGuid,
149 &gIdleLoopEvent
150 );
151
152 return EFI_SUCCESS;
153
函数CoreInitializeTimer
会初始化一个EVT_NORIFY_SIGNAL
类型的事件,其回调函数为CoreCheckTimers
/** /Dxe/Event/Timer.c **/
168 VOID
169 CoreInitializeTimer (
170 VOID
171 )
172
173 EFI_STATUS Status;
174
175 Status = CoreCreateEventInternal (
176 EVT_NOTIFY_SIGNAL,
177 TPL_HIGH_LEVEL - 1,
178 CoreCheckTimers,
179 NULL,
180 NULL,
181 &mEfiCheckTimerEvent
182 );
183 ASSERT_EFI_ERROR (Status);
184
该回调函数CoreCheckTimers
就是检查所有的定时器,即mEfiTimerList
,若到期则执行其回调函数。若是永久定时器,则增加一段时间后,再次将该定时器唤醒。
98 VOID
99 EFIAPI
100 CoreCheckTimers (
101 IN EFI_EVENT CheckEvent,
102 IN VOID *Context
103 )
104
111 CoreAcquireLock (&mEfiTimerLock);
112 SystemTime = CoreCurrentSystemTime ();
113
114 while (!IsListEmpty (&mEfiTimerList))
115 Event = CR (mEfiTimerList.ForwardLink, IEVENT, Timer.Link, EVENT_SIGNATURE);
116
120 if (Event->Timer.TriggerTime > SystemTime)
121 break;
122
127
128 RemoveEntryList (&Event->Timer.Link);
129 Event->Timer.Link.ForwardLink = NULL;
130
134 CoreSignalEvent (Event);
135
139 if (Event->Timer.Period != 0)
143 Event->Timer.TriggerTime = Event->Timer.TriggerTime + Event->Timer.Period;
144
148 if (Event->Timer.TriggerTime <= SystemTime)
149 Event->Timer.TriggerTime = SystemTime;
150 CoreSignalEvent (mEfiCheckTimerEvent);
151
152
156 CoreInsertEventTimer (Event);
157
158
159
160 CoreReleaseLock (&mEfiTimerLock);
161
真正的时钟中断函数CoreTimerTick
正是利用了事件mEfiCheckTimerEvent
来执行定时器
- 更新全局时间
mEfiSystemTime
- 若
mEfiTimerList
非空,且最近的定时器已过期,则SignalEvent
事件mEfiCheckTimerEvent
,也就是执行其回调函数CoreCheckTimers
来处理定时器。
194 VOID
195 EFIAPI
196 CoreTimerTick (
197 IN UINT64 Duration
198 )
199
205 CoreAcquireLock (&mEfiSystemTimeLock);
206
210 mEfiSystemTime += Duration;
211
216 if (!IsListEmpty (&mEfiTimerList))
217 Event = CR (mEfiTimerList.ForwardLink, IEVENT, Timer.Link, EVENT_SIGNATURE);
218
219 if (Event->Timer.TriggerTime <= mEfiSystemTime)
220 CoreSignalEvent (mEfiCheckTimerEvent);
221
222
223
224 CoreReleaseLock (&mEfiSystemTimeLock);
225
时钟中断的初始化
1、 在DXE入口中调用函数CoreNotifyOnProtocolInstallation
/** /Dxe/DxeMain/DxeProtocolNotify.c **/
252 VOID
253 CoreNotifyOnProtocolInstallation (
254 VOID
255 )
256
257 CoreNotifyOnProtocolEntryTable (mArchProtocols);
258 CoreNotifyOnProtocolEntryTable (mOptionalProtocols);
259
2、函数CoreNotifyOnProtocolEntryTable
为某些特定的协议设置对应的回调函数,当该协议的实例被安装时,回调函数就会被调用
215 VOID
216 CoreNotifyOnProtocolEntryTable (
217 EFI_CORE_PROTOCOL_NOTIFY_ENTRY *Entry
218 )
219
220 EFI_STATUS Status;
221
222 for (; Entry->ProtocolGuid != NULL; Entry++)
226 Status = CoreCreateEvent (
227 EVT_NOTIFY_SIGNAL,
228 TPL_CALLBACK,
229 GenericProtocolNotify,
230 Entry,
231 &Entry->Event
232 );
233 ASSERT_EFI_ERROR(Status);
234
238 Status = CoreRegisterProtocolNotify (
239 Entry->ProtocolGuid,
240 Entry->Event,
241 &Entry->Registration
242 );
243 ASSERT_EFI_ERROR(Status);
244
245
指定的协议,如mArchProocol
包括如下协议
27 EFI_CORE_PROTOCOL_NOTIFY_ENTRY mArchProtocols[] =
28 &gEfiSecurityArchProtocolGuid, (VOID **)&gSecurity, NULL, NULL, FALSE ,
29 &gEfiCpuArchProtocolGuid, (VOID **)&gCpu, NULL, NULL, FALSE ,
30 &gEfiMetronomeArchProtocolGuid, (VOID **)&gMetronome, NULL, NULL, FALSE ,
31 &gEfiTimerArchProtocolGuid, (VOID **)&gTimer, NULL, NULL, FALSE ,
32 &gEfiBdsArchProtocolGuid, (VOID **)&gBds, NULL, NULL, FALSE ,
33 &gEfiWatchdogTimerArchProtocolGuid, (VOID **)&gWatchdogTimer, NULL, NULL, FALSE ,
34 &gEfiRuntimeArchProtocolGuid, (VOID **)&gRuntime, NULL, NULL, FALSE ,
35 &gEfiVariableArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE ,
36 &gEfiVariableWriteArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE ,
37 &gEfiCapsuleArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE ,
38 &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE ,
39 &gEfiResetArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE ,
40 &gEfiRealTimeClockArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE ,
41 NULL, (VOID **)NULL, NULL, NULL, FALSE
42 ;
回调函数GenericProtocolNotify
的工作注释解释的很清楚
这个回调函数被注册到每个ArchProcotol
上,这个函数会使用协议实例来更新mArchProtocol
。
101 /**
102 Notification event handler registered by CoreNotifyOnArchProtocolInstallation ().
103 This notify function is registered for every architectural protocol. This handler
104 updates mArchProtocol[] array entry with protocol instance data and sets it's
105 present flag to TRUE. If any constructor is required it is executed. The EFI
106 System Table headers are updated.
107
108 @param Event The Event that is being processed, not used.
109 @param Context Event Context, not used.
110
111 **/
112 VOID
113 EFIAPI
114 GenericProtocolNotify (
115 IN EFI_EVENT Event,
116 IN VOID *Context
117 )
118
这里只注意这一段处理,和定时器相关的
157 if (CompareGuid (Entry->ProtocolGuid, &gEfiTimerArchProtocolGuid))
158 //
159 // Register the Core timer tick handler with the Timer AP
160 //
161 gTimer->RegisterHandler (gTimer, CoreTimerTick);
162
即当EFI_TIMER_ARCH_PROTOCOL
的协议实例被注册的时候,则调用该协议的RegisterHandler
接口,注册时钟中断处理程序,即CoreTimerTick
。
全局变量gTimer
定义于DxeMain.c
29 EFI_TIMER_ARCH_PROTOCOL *gTimer = NULL;
注意到在全局变量mArchProtocols
中有gTimer
的地址,故回调函数GenericProtocolNotify
会将协议的实例写入gTimer
。
以上是关于UEFI.源码分析.DXE的异步事件服务.第三部分.定时器与时钟中断的主要内容,如果未能解决你的问题,请参考以下文章
UEFI.源码分析.DXE的异步事件服务.第一部分.事件驱动
UEFI.源码分析.DXE的异步事件服务.第一部分.事件驱动
UEFI.源码分析.DXE的异步事件服务.第二部分.任务优先级
UEFI.源码分析.DXE的异步事件服务.第二部分.任务优先级