]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Event/timer.c
Add comments and DoxyGen format for these files.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Event / timer.c
CommitLineData
504214c4 1/** @file \r
28a00297 2\r
504214c4
LG
3 Core Timer Services\r
4\r
5Copyright (c) 2006 - 2008, Intel Corporation\r
28a00297 6All rights reserved. This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
504214c4 14**/\r
28a00297 15\r
16\r
17#include <DxeMain.h>\r
18\r
19//\r
20// Internal prototypes\r
21//\r
22STATIC\r
23UINT64\r
24CoreCurrentSystemTime (\r
25 VOID\r
26 );\r
27\r
28STATIC\r
29VOID\r
30EFIAPI\r
31CoreCheckTimers (\r
32 IN EFI_EVENT Event,\r
33 IN VOID *Context\r
34 );\r
35\r
36STATIC\r
37VOID\r
38CoreInsertEventTimer (\r
39 IN IEVENT *Event\r
40 );\r
41\r
42//\r
43// Internal data\r
44//\r
45\r
46static LIST_ENTRY mEfiTimerList = INITIALIZE_LIST_HEAD_VARIABLE (mEfiTimerList);\r
47static EFI_LOCK mEfiTimerLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL - 1);\r
48static EFI_EVENT mEfiCheckTimerEvent;\r
49\r
50static EFI_LOCK mEfiSystemTimeLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL);\r
51static UINT64 mEfiSystemTime = 0;\r
52\r
53//\r
54// Timer functions\r
55//\r
56\r
57VOID\r
58CoreInitializeTimer (\r
59 VOID\r
60 )\r
61/*++\r
62\r
63Routine Description:\r
64\r
65 Initializes timer support\r
66\r
67Arguments:\r
68\r
69 None\r
70\r
71Returns:\r
72\r
73 None\r
74\r
75--*/\r
76{\r
77 EFI_STATUS Status;\r
78\r
79 Status = CoreCreateEvent (\r
80 EVT_NOTIFY_SIGNAL,\r
81 TPL_HIGH_LEVEL - 1,\r
82 CoreCheckTimers,\r
83 NULL,\r
84 &mEfiCheckTimerEvent\r
85 );\r
86 ASSERT_EFI_ERROR (Status);\r
87}\r
88\r
89STATIC\r
90UINT64\r
91CoreCurrentSystemTime (\r
92 VOID\r
93 )\r
94/*++\r
95\r
96Routine Description:\r
97\r
98 Returns the current system time\r
99\r
100Arguments:\r
101\r
102 None\r
103\r
104Returns:\r
105\r
106 Returns the current system time\r
107\r
108--*/\r
109{\r
110 UINT64 SystemTime;\r
111\r
112 CoreAcquireLock (&mEfiSystemTimeLock);\r
113 SystemTime = mEfiSystemTime;\r
114 CoreReleaseLock (&mEfiSystemTimeLock);\r
115 return SystemTime;\r
116}\r
117\r
118VOID\r
119EFIAPI\r
120CoreTimerTick (\r
121 IN UINT64 Duration\r
122 )\r
123/*++\r
124\r
125Routine Description:\r
126\r
127 Called by the platform code to process a tick.\r
128\r
129Arguments:\r
130\r
131 Duration - The number of 100ns elasped since the last call to TimerTick\r
132\r
133Returns:\r
134\r
135 None\r
136\r
137--*/\r
138{\r
139 IEVENT *Event;\r
140\r
141 //\r
142 // Check runtiem flag in case there are ticks while exiting boot services\r
143 //\r
144\r
145 CoreAcquireLock (&mEfiSystemTimeLock);\r
146\r
147 //\r
148 // Update the system time\r
149 //\r
150\r
151 mEfiSystemTime += Duration;\r
152\r
153 //\r
154 // If the head of the list is expired, fire the timer event\r
155 // to process it\r
156 //\r
157\r
158 if (!IsListEmpty (&mEfiTimerList)) {\r
159 Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE);\r
160\r
161 if (Event->u.Timer.TriggerTime <= mEfiSystemTime) {\r
162 CoreSignalEvent (mEfiCheckTimerEvent);\r
163 }\r
164 }\r
165\r
166 CoreReleaseLock (&mEfiSystemTimeLock);\r
167}\r
168\r
169STATIC\r
170VOID\r
171EFIAPI\r
172CoreCheckTimers (\r
173 IN EFI_EVENT CheckEvent,\r
174 IN VOID *Context\r
175 )\r
176/*++\r
177\r
178Routine Description:\r
179\r
180 Checks the sorted timer list against the current system time.\r
181 Signals any expired event timer.\r
182\r
183Arguments:\r
184\r
185 CheckEvent - Not used\r
186\r
187 Context - Not used\r
188\r
189Returns:\r
190\r
191 None\r
192\r
193--*/\r
194{\r
195 UINT64 SystemTime;\r
196 IEVENT *Event;\r
197\r
198 //\r
199 // Check the timer database for expired timers\r
200 //\r
201\r
202 CoreAcquireLock (&mEfiTimerLock);\r
203 SystemTime = CoreCurrentSystemTime ();\r
204\r
205 while (!IsListEmpty (&mEfiTimerList)) {\r
206 Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE);\r
207\r
208 //\r
209 // If this timer is not expired, then we're done\r
210 //\r
211\r
212 if (Event->u.Timer.TriggerTime > SystemTime) {\r
213 break;\r
214 }\r
215\r
216 //\r
217 // Remove this timer from the timer queue\r
218 //\r
219\r
220 RemoveEntryList (&Event->u.Timer.Link);\r
221 Event->u.Timer.Link.ForwardLink = NULL;\r
222\r
223 //\r
224 // Signal it\r
225 //\r
226 CoreSignalEvent (Event);\r
227\r
228 //\r
229 // If this is a periodic timer, set it\r
230 //\r
231 if (Event->u.Timer.Period) {\r
232\r
233 //\r
234 // Compute the timers new trigger time\r
235 //\r
236\r
237 Event->u.Timer.TriggerTime = Event->u.Timer.TriggerTime + Event->u.Timer.Period;\r
238\r
239 //\r
240 // If that's before now, then reset the timer to start from now\r
241 //\r
242 if (Event->u.Timer.TriggerTime <= SystemTime) {\r
243 Event->u.Timer.TriggerTime = SystemTime;\r
244 CoreSignalEvent (mEfiCheckTimerEvent);\r
245 }\r
246\r
247 //\r
248 // Add the timer\r
249 //\r
250\r
251 CoreInsertEventTimer (Event);\r
252 }\r
253 }\r
254\r
255 CoreReleaseLock (&mEfiTimerLock);\r
256}\r
257\r
258STATIC\r
259VOID\r
260CoreInsertEventTimer (\r
261 IN IEVENT *Event\r
262 )\r
263/*++\r
264\r
265Routine Description:\r
266\r
267 Inserts the timer event\r
268\r
269Arguments:\r
270\r
271 Event - Points to the internal structure of timer event to be installed\r
272\r
273Returns:\r
274\r
275 None\r
276\r
277--*/\r
278{\r
279 UINT64 TriggerTime;\r
280 LIST_ENTRY *Link;\r
281 IEVENT *Event2;\r
282\r
283 ASSERT_LOCKED (&mEfiTimerLock);\r
284\r
285 //\r
286 // Get the timer's trigger time\r
287 //\r
288\r
289 TriggerTime = Event->u.Timer.TriggerTime;\r
290\r
291 //\r
292 // Insert the timer into the timer database in assending sorted order\r
293 //\r
294\r
295 for (Link = mEfiTimerList.ForwardLink; Link != &mEfiTimerList; Link = Link->ForwardLink) {\r
296 Event2 = CR (Link, IEVENT, u.Timer.Link, EVENT_SIGNATURE);\r
297\r
298 if (Event2->u.Timer.TriggerTime > TriggerTime) {\r
299 break;\r
300 }\r
301 }\r
302\r
303 InsertTailList (Link, &Event->u.Timer.Link);\r
304}\r
305\r
306\r
307\r
308EFI_STATUS\r
309EFIAPI\r
310CoreSetTimer (\r
311 IN EFI_EVENT UserEvent,\r
312 IN EFI_TIMER_DELAY Type,\r
313 IN UINT64 TriggerTime\r
314 )\r
315/*++\r
316\r
317Routine Description:\r
318\r
319 Sets the type of timer and the trigger time for a timer event.\r
320\r
321Arguments:\r
322\r
323 UserEvent - The timer event that is to be signaled at the specified time\r
324 Type - The type of time that is specified in TriggerTime\r
325 TriggerTime - The number of 100ns units until the timer expires\r
326\r
327Returns:\r
328\r
329 EFI_SUCCESS - The event has been set to be signaled at the requested time\r
330 EFI_INVALID_PARAMETER - Event or Type is not valid\r
331\r
332--*/\r
333{\r
334 IEVENT *Event;\r
335\r
336 Event = UserEvent;\r
337\r
338 if (Event == NULL) {\r
339 return EFI_INVALID_PARAMETER;\r
340 }\r
341\r
342 if (Event->Signature != EVENT_SIGNATURE) {\r
343 return EFI_INVALID_PARAMETER;\r
344 }\r
345\r
346 if (Type < 0 || Type > TimerRelative || !(Event->Type & EVT_TIMER)) {\r
347 return EFI_INVALID_PARAMETER;\r
348 }\r
349\r
350 CoreAcquireLock (&mEfiTimerLock);\r
351\r
352 //\r
353 // If the timer is queued to the timer database, remove it\r
354 //\r
355\r
356 if (Event->u.Timer.Link.ForwardLink != NULL) {\r
357 RemoveEntryList (&Event->u.Timer.Link);\r
358 Event->u.Timer.Link.ForwardLink = NULL;\r
359 }\r
360\r
361 Event->u.Timer.TriggerTime = 0;\r
362 Event->u.Timer.Period = 0;\r
363\r
364 if (Type != TimerCancel) {\r
365\r
366 if (Type == TimerPeriodic) {\r
367 Event->u.Timer.Period = TriggerTime;\r
368 }\r
369\r
370 Event->u.Timer.TriggerTime = CoreCurrentSystemTime () + TriggerTime;\r
371 CoreInsertEventTimer (Event);\r
372\r
373 if (TriggerTime == 0) {\r
374 CoreSignalEvent (mEfiCheckTimerEvent);\r
375 }\r
376 }\r
377\r
378 CoreReleaseLock (&mEfiTimerLock);\r
379 return EFI_SUCCESS;\r
380}\r