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