]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Event/Timer.c
Update to fix minor coding style issues.
[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 STATIC LIST_ENTRY mEfiTimerList = INITIALIZE_LIST_HEAD_VARIABLE (mEfiTimerList);
64 STATIC EFI_LOCK mEfiTimerLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL - 1);
65 STATIC EFI_EVENT mEfiCheckTimerEvent;
66
67 STATIC EFI_LOCK mEfiSystemTimeLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL);
68 STATIC UINT64 mEfiSystemTime = 0;
69
70 //
71 // Timer functions
72 //
73
74
75 /**
76 Initializes timer support.
77
78 **/
79 VOID
80 CoreInitializeTimer (
81 VOID
82 )
83 {
84 EFI_STATUS Status;
85
86 Status = CoreCreateEvent (
87 EVT_NOTIFY_SIGNAL,
88 TPL_HIGH_LEVEL - 1,
89 CoreCheckTimers,
90 NULL,
91 &mEfiCheckTimerEvent
92 );
93 ASSERT_EFI_ERROR (Status);
94 }
95
96
97 /**
98 Returns the current system time.
99
100 @return The current system time
101
102 **/
103 UINT64
104 CoreCurrentSystemTime (
105 VOID
106 )
107 {
108 UINT64 SystemTime;
109
110 CoreAcquireLock (&mEfiSystemTimeLock);
111 SystemTime = mEfiSystemTime;
112 CoreReleaseLock (&mEfiSystemTimeLock);
113 return SystemTime;
114 }
115
116
117 /**
118 Called by the platform code to process a tick.
119
120 @param Duration The number of 100ns elasped since the last call
121 to TimerTick
122
123 **/
124 VOID
125 EFIAPI
126 CoreTimerTick (
127 IN UINT64 Duration
128 )
129 {
130 IEVENT *Event;
131
132 //
133 // Check runtiem flag in case there are ticks while exiting boot services
134 //
135
136 CoreAcquireLock (&mEfiSystemTimeLock);
137
138 //
139 // Update the system time
140 //
141
142 mEfiSystemTime += Duration;
143
144 //
145 // If the head of the list is expired, fire the timer event
146 // to process it
147 //
148
149 if (!IsListEmpty (&mEfiTimerList)) {
150 Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
151
152 if (Event->u.Timer.TriggerTime <= mEfiSystemTime) {
153 CoreSignalEvent (mEfiCheckTimerEvent);
154 }
155 }
156
157 CoreReleaseLock (&mEfiSystemTimeLock);
158 }
159
160
161 /**
162 Checks the sorted timer list against the current system time.
163 Signals any expired event timer.
164
165 @param CheckEvent Not used
166 @param Context Not used
167
168 **/
169 VOID
170 EFIAPI
171 CoreCheckTimers (
172 IN EFI_EVENT CheckEvent,
173 IN VOID *Context
174 )
175 {
176 UINT64 SystemTime;
177 IEVENT *Event;
178
179 //
180 // Check the timer database for expired timers
181 //
182
183 CoreAcquireLock (&mEfiTimerLock);
184 SystemTime = CoreCurrentSystemTime ();
185
186 while (!IsListEmpty (&mEfiTimerList)) {
187 Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
188
189 //
190 // If this timer is not expired, then we're done
191 //
192
193 if (Event->u.Timer.TriggerTime > SystemTime) {
194 break;
195 }
196
197 //
198 // Remove this timer from the timer queue
199 //
200
201 RemoveEntryList (&Event->u.Timer.Link);
202 Event->u.Timer.Link.ForwardLink = NULL;
203
204 //
205 // Signal it
206 //
207 CoreSignalEvent (Event);
208
209 //
210 // If this is a periodic timer, set it
211 //
212 if (Event->u.Timer.Period) {
213
214 //
215 // Compute the timers new trigger time
216 //
217
218 Event->u.Timer.TriggerTime = Event->u.Timer.TriggerTime + Event->u.Timer.Period;
219
220 //
221 // If that's before now, then reset the timer to start from now
222 //
223 if (Event->u.Timer.TriggerTime <= SystemTime) {
224 Event->u.Timer.TriggerTime = SystemTime;
225 CoreSignalEvent (mEfiCheckTimerEvent);
226 }
227
228 //
229 // Add the timer
230 //
231
232 CoreInsertEventTimer (Event);
233 }
234 }
235
236 CoreReleaseLock (&mEfiTimerLock);
237 }
238
239
240 /**
241 Inserts the timer event.
242
243 @param Event Points to the internal structure of timer event
244 to be installed
245
246 **/
247 VOID
248 CoreInsertEventTimer (
249 IN IEVENT *Event
250 )
251 {
252 UINT64 TriggerTime;
253 LIST_ENTRY *Link;
254 IEVENT *Event2;
255
256 ASSERT_LOCKED (&mEfiTimerLock);
257
258 //
259 // Get the timer's trigger time
260 //
261
262 TriggerTime = Event->u.Timer.TriggerTime;
263
264 //
265 // Insert the timer into the timer database in assending sorted order
266 //
267
268 for (Link = mEfiTimerList.ForwardLink; Link != &mEfiTimerList; Link = Link->ForwardLink) {
269 Event2 = CR (Link, IEVENT, u.Timer.Link, EVENT_SIGNATURE);
270
271 if (Event2->u.Timer.TriggerTime > TriggerTime) {
272 break;
273 }
274 }
275
276 InsertTailList (Link, &Event->u.Timer.Link);
277 }
278
279
280
281
282 /**
283 Sets the type of timer and the trigger time for a timer event.
284
285 @param UserEvent The timer event that is to be signaled at the
286 specified time
287 @param Type The type of time that is specified in
288 TriggerTime
289 @param TriggerTime The number of 100ns units until the timer
290 expires
291
292 @retval EFI_SUCCESS The event has been set to be signaled at the
293 requested time
294 @retval EFI_INVALID_PARAMETER Event or Type is not valid
295
296 **/
297 EFI_STATUS
298 EFIAPI
299 CoreSetTimer (
300 IN EFI_EVENT UserEvent,
301 IN EFI_TIMER_DELAY Type,
302 IN UINT64 TriggerTime
303 )
304 {
305 IEVENT *Event;
306
307 Event = UserEvent;
308
309 if (Event == NULL) {
310 return EFI_INVALID_PARAMETER;
311 }
312
313 if (Event->Signature != EVENT_SIGNATURE) {
314 return EFI_INVALID_PARAMETER;
315 }
316
317 if (Type < 0 || Type > TimerRelative || !(Event->Type & EVT_TIMER)) {
318 return EFI_INVALID_PARAMETER;
319 }
320
321 CoreAcquireLock (&mEfiTimerLock);
322
323 //
324 // If the timer is queued to the timer database, remove it
325 //
326
327 if (Event->u.Timer.Link.ForwardLink != NULL) {
328 RemoveEntryList (&Event->u.Timer.Link);
329 Event->u.Timer.Link.ForwardLink = NULL;
330 }
331
332 Event->u.Timer.TriggerTime = 0;
333 Event->u.Timer.Period = 0;
334
335 if (Type != TimerCancel) {
336
337 if (Type == TimerPeriodic) {
338 Event->u.Timer.Period = TriggerTime;
339 }
340
341 Event->u.Timer.TriggerTime = CoreCurrentSystemTime () + TriggerTime;
342 CoreInsertEventTimer (Event);
343
344 if (TriggerTime == 0) {
345 CoreSignalEvent (mEfiCheckTimerEvent);
346 }
347 }
348
349 CoreReleaseLock (&mEfiTimerLock);
350 return EFI_SUCCESS;
351 }