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