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