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