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