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