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