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