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