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