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