]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Event/Event.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Event / Event.c
CommitLineData
23c98c94 1/** @file\r
504214c4
LG
2 UEFI Event support functions implemented in this file.\r
3\r
ac72474d 4Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
82f3edf2 5(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
9d510e61 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
28a00297 7\r
504214c4 8**/\r
28a00297 9\r
9c4ac31c 10#include "DxeMain.h"\r
ec90508b 11#include "Event.h"\r
28a00297 12\r
1947c70c 13///\r
14/// gEfiCurrentTpl - Current Task priority level\r
15///\r
16EFI_TPL gEfiCurrentTpl = TPL_APPLICATION;\r
17\r
18///\r
d613c2a8 19/// gEventQueueLock - Protects the event queues\r
1947c70c 20///\r
1436aea4 21EFI_LOCK gEventQueueLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_HIGH_LEVEL);\r
1947c70c 22\r
23///\r
24/// gEventQueue - A list of event's to notify for each priority level\r
25///\r
1436aea4 26LIST_ENTRY gEventQueue[TPL_HIGH_LEVEL + 1];\r
1947c70c 27\r
28///\r
29/// gEventPending - A bitmask of the EventQueues that are pending\r
30///\r
1436aea4 31UINTN gEventPending = 0;\r
1947c70c 32\r
33///\r
34/// gEventSignalQueue - A list of events to signal based on EventGroup type\r
35///\r
1436aea4 36LIST_ENTRY gEventSignalQueue = INITIALIZE_LIST_HEAD_VARIABLE (gEventSignalQueue);\r
1947c70c 37\r
38///\r
39/// Enumerate the valid types\r
40///\r
1436aea4 41UINT32 mEventTable[] = {\r
1947c70c 42 ///\r
43 /// 0x80000200 Timer event with a notification function that is\r
44 /// queue when the event is signaled with SignalEvent()\r
45 ///\r
28a00297 46 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
1947c70c 47 ///\r
48 /// 0x80000000 Timer event without a notification function. It can be\r
49 /// signaled with SignalEvent() and checked with CheckEvent() or WaitForEvent().\r
50 ///\r
28a00297 51 EVT_TIMER,\r
1947c70c 52 ///\r
53 /// 0x00000100 Generic event with a notification function that\r
54 /// can be waited on with CheckEvent() or WaitForEvent()\r
55 ///\r
28a00297 56 EVT_NOTIFY_WAIT,\r
1947c70c 57 ///\r
58 /// 0x00000200 Generic event with a notification function that\r
59 /// is queue when the event is signaled with SignalEvent()\r
60 ///\r
28a00297 61 EVT_NOTIFY_SIGNAL,\r
1947c70c 62 ///\r
63 /// 0x00000201 ExitBootServicesEvent.\r
64 ///\r
28a00297 65 EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
1947c70c 66 ///\r
67 /// 0x60000202 SetVirtualAddressMapEvent.\r
68 ///\r
28a00297 69 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,\r
70\r
1947c70c 71 ///\r
72 /// 0x00000000 Generic event without a notification function.\r
73 /// It can be signaled with SignalEvent() and checked with CheckEvent()\r
74 /// or WaitForEvent().\r
75 ///\r
28a00297 76 0x00000000,\r
1947c70c 77 ///\r
78 /// 0x80000100 Timer event with a notification function that can be\r
79 /// waited on with CheckEvent() or WaitForEvent()\r
80 ///\r
28a00297 81 EVT_TIMER | EVT_NOTIFY_WAIT,\r
82};\r
83\r
54cd17e9 84///\r
85/// gIdleLoopEvent - Event which is signalled when the core is idle\r
86///\r
1436aea4 87EFI_EVENT gIdleLoopEvent = NULL;\r
162ed594 88\r
89/**\r
90 Enter critical section by acquiring the lock on gEventQueueLock.\r
91\r
92**/\r
28a00297 93VOID\r
94CoreAcquireEventLock (\r
95 VOID\r
96 )\r
28a00297 97{\r
98 CoreAcquireLock (&gEventQueueLock);\r
99}\r
100\r
162ed594 101/**\r
102 Exit critical section by releasing the lock on gEventQueueLock.\r
103\r
104**/\r
28a00297 105VOID\r
106CoreReleaseEventLock (\r
107 VOID\r
108 )\r
28a00297 109{\r
110 CoreReleaseLock (&gEventQueueLock);\r
111}\r
112\r
162ed594 113/**\r
c18f12d3 114 Initializes "event" support.\r
28a00297 115\r
162ed594 116 @retval EFI_SUCCESS Always return success\r
28a00297 117\r
162ed594 118**/\r
119EFI_STATUS\r
120CoreInitializeEventServices (\r
121 VOID\r
122 )\r
28a00297 123{\r
1436aea4 124 UINTN Index;\r
28a00297 125\r
1436aea4 126 for (Index = 0; Index <= TPL_HIGH_LEVEL; Index++) {\r
28a00297 127 InitializeListHead (&gEventQueue[Index]);\r
128 }\r
129\r
130 CoreInitializeTimer ();\r
131\r
54cd17e9 132 CoreCreateEventEx (\r
133 EVT_NOTIFY_SIGNAL,\r
134 TPL_NOTIFY,\r
ac72474d 135 EfiEventEmptyFunction,\r
54cd17e9 136 NULL,\r
137 &gIdleLoopEventGuid,\r
138 &gIdleLoopEvent\r
139 );\r
140\r
28a00297 141 return EFI_SUCCESS;\r
142}\r
143\r
162ed594 144/**\r
28a00297 145 Dispatches all pending events.\r
146\r
022c6d45 147 @param Priority The task priority level of event notifications\r
162ed594 148 to dispatch\r
28a00297 149\r
162ed594 150**/\r
151VOID\r
152CoreDispatchEventNotifies (\r
1436aea4 153 IN EFI_TPL Priority\r
162ed594 154 )\r
28a00297 155{\r
1436aea4
MK
156 IEVENT *Event;\r
157 LIST_ENTRY *Head;\r
28a00297 158\r
159 CoreAcquireEventLock ();\r
160 ASSERT (gEventQueueLock.OwnerTpl == Priority);\r
161 Head = &gEventQueue[Priority];\r
162\r
163 //\r
164 // Dispatch all the pending notifications\r
165 //\r
166 while (!IsListEmpty (Head)) {\r
28a00297 167 Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE);\r
168 RemoveEntryList (&Event->NotifyLink);\r
169\r
170 Event->NotifyLink.ForwardLink = NULL;\r
171\r
172 //\r
173 // Only clear the SIGNAL status if it is a SIGNAL type event.\r
174 // WAIT type events are only cleared in CheckEvent()\r
175 //\r
6e536468 176 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
28a00297 177 Event->SignalCount = 0;\r
178 }\r
179\r
180 CoreReleaseEventLock ();\r
181\r
182 //\r
183 // Notify this event\r
184 //\r
185 ASSERT (Event->NotifyFunction != NULL);\r
186 Event->NotifyFunction (Event, Event->NotifyContext);\r
187\r
188 //\r
189 // Check for next pending event\r
190 //\r
191 CoreAcquireEventLock ();\r
192 }\r
193\r
6e1e5405 194 gEventPending &= ~(UINTN)(1 << Priority);\r
28a00297 195 CoreReleaseEventLock ();\r
196}\r
197\r
162ed594 198/**\r
199 Queues the event's notification function to fire.\r
200\r
201 @param Event The Event to notify\r
202\r
203**/\r
28a00297 204VOID\r
205CoreNotifyEvent (\r
1436aea4 206 IN IEVENT *Event\r
28a00297 207 )\r
28a00297 208{\r
28a00297 209 //\r
210 // Event database must be locked\r
211 //\r
212 ASSERT_LOCKED (&gEventQueueLock);\r
213\r
214 //\r
215 // If the event is queued somewhere, remove it\r
216 //\r
217\r
218 if (Event->NotifyLink.ForwardLink != NULL) {\r
219 RemoveEntryList (&Event->NotifyLink);\r
220 Event->NotifyLink.ForwardLink = NULL;\r
221 }\r
222\r
223 //\r
224 // Queue the event to the pending notification list\r
225 //\r
226\r
227 InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink);\r
228 gEventPending |= (UINTN)(1 << Event->NotifyTpl);\r
229}\r
230\r
162ed594 231/**\r
232 Signals all events in the EventGroup.\r
233\r
234 @param EventGroup The list to signal\r
235\r
236**/\r
28a00297 237VOID\r
238CoreNotifySignalList (\r
1436aea4 239 IN EFI_GUID *EventGroup\r
28a00297 240 )\r
28a00297 241{\r
1436aea4
MK
242 LIST_ENTRY *Link;\r
243 LIST_ENTRY *Head;\r
244 IEVENT *Event;\r
28a00297 245\r
246 CoreAcquireEventLock ();\r
247\r
248 Head = &gEventSignalQueue;\r
249 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
250 Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE);\r
251 if (CompareGuid (&Event->EventGroup, EventGroup)) {\r
252 CoreNotifyEvent (Event);\r
253 }\r
254 }\r
255\r
256 CoreReleaseEventLock ();\r
257}\r
258\r
162ed594 259/**\r
670d4d88 260 Creates an event.\r
162ed594 261\r
022c6d45 262 @param Type The type of event to create and its mode and\r
263 attributes\r
264 @param NotifyTpl The task priority level of event notifications\r
265 @param NotifyFunction Pointer to the events notification function\r
266 @param NotifyContext Pointer to the notification functions context;\r
267 corresponds to parameter "Context" in the\r
268 notification function\r
269 @param Event Pointer to the newly created event if the call\r
270 succeeds; undefined otherwise\r
271\r
272 @retval EFI_SUCCESS The event structure was created\r
273 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value\r
162ed594 274 @retval EFI_OUT_OF_RESOURCES The event could not be allocated\r
275\r
276**/\r
28a00297 277EFI_STATUS\r
278EFIAPI\r
279CoreCreateEvent (\r
1436aea4
MK
280 IN UINT32 Type,\r
281 IN EFI_TPL NotifyTpl,\r
282 IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,\r
283 IN VOID *NotifyContext OPTIONAL,\r
284 OUT EFI_EVENT *Event\r
28a00297 285 )\r
28a00297 286{\r
bb8ffffd 287 return CoreCreateEventEx (Type, NotifyTpl, NotifyFunction, NotifyContext, NULL, Event);\r
28a00297 288}\r
289\r
162ed594 290/**\r
670d4d88 291 Creates an event in a group.\r
162ed594 292\r
022c6d45 293 @param Type The type of event to create and its mode and\r
294 attributes\r
295 @param NotifyTpl The task priority level of event notifications\r
296 @param NotifyFunction Pointer to the events notification function\r
297 @param NotifyContext Pointer to the notification functions context;\r
298 corresponds to parameter "Context" in the\r
299 notification function\r
300 @param EventGroup GUID for EventGroup if NULL act the same as\r
301 gBS->CreateEvent().\r
302 @param Event Pointer to the newly created event if the call\r
303 succeeds; undefined otherwise\r
304\r
305 @retval EFI_SUCCESS The event structure was created\r
306 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value\r
162ed594 307 @retval EFI_OUT_OF_RESOURCES The event could not be allocated\r
308\r
309**/\r
28a00297 310EFI_STATUS\r
311EFIAPI\r
312CoreCreateEventEx (\r
1436aea4
MK
313 IN UINT32 Type,\r
314 IN EFI_TPL NotifyTpl,\r
315 IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,\r
316 IN CONST VOID *NotifyContext OPTIONAL,\r
317 IN CONST EFI_GUID *EventGroup OPTIONAL,\r
318 OUT EFI_EVENT *Event\r
28a00297 319 )\r
670d4d88
SZ
320{\r
321 //\r
322 // If it's a notify type of event, check for invalid NotifyTpl\r
323 //\r
324 if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {\r
1436aea4
MK
325 if ((NotifyTpl != TPL_APPLICATION) &&\r
326 (NotifyTpl != TPL_CALLBACK) &&\r
327 (NotifyTpl != TPL_NOTIFY))\r
328 {\r
670d4d88
SZ
329 return EFI_INVALID_PARAMETER;\r
330 }\r
331 }\r
332\r
333 return CoreCreateEventInternal (Type, NotifyTpl, NotifyFunction, NotifyContext, EventGroup, Event);\r
334}\r
335\r
336/**\r
337 Creates a general-purpose event structure\r
338\r
339 @param Type The type of event to create and its mode and\r
340 attributes\r
341 @param NotifyTpl The task priority level of event notifications\r
342 @param NotifyFunction Pointer to the events notification function\r
343 @param NotifyContext Pointer to the notification functions context;\r
344 corresponds to parameter "Context" in the\r
345 notification function\r
346 @param EventGroup GUID for EventGroup if NULL act the same as\r
347 gBS->CreateEvent().\r
348 @param Event Pointer to the newly created event if the call\r
349 succeeds; undefined otherwise\r
350\r
351 @retval EFI_SUCCESS The event structure was created\r
352 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value\r
353 @retval EFI_OUT_OF_RESOURCES The event could not be allocated\r
354\r
355**/\r
356EFI_STATUS\r
357EFIAPI\r
358CoreCreateEventInternal (\r
1436aea4
MK
359 IN UINT32 Type,\r
360 IN EFI_TPL NotifyTpl,\r
361 IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,\r
362 IN CONST VOID *NotifyContext OPTIONAL,\r
363 IN CONST EFI_GUID *EventGroup OPTIONAL,\r
364 OUT EFI_EVENT *Event\r
670d4d88 365 )\r
28a00297 366{\r
1436aea4
MK
367 EFI_STATUS Status;\r
368 IEVENT *IEvent;\r
369 INTN Index;\r
28a00297 370\r
51b02d81 371 if (Event == NULL) {\r
28a00297 372 return EFI_INVALID_PARAMETER;\r
373 }\r
374\r
375 //\r
376 // Check to make sure no reserved flags are set\r
377 //\r
378 Status = EFI_INVALID_PARAMETER;\r
379 for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {\r
1436aea4
MK
380 if (Type == mEventTable[Index]) {\r
381 Status = EFI_SUCCESS;\r
382 break;\r
383 }\r
28a00297 384 }\r
1436aea4
MK
385\r
386 if (EFI_ERROR (Status)) {\r
28a00297 387 return EFI_INVALID_PARAMETER;\r
388 }\r
389\r
bb8ffffd 390 //\r
391 // Convert Event type for pre-defined Event groups\r
392 //\r
393 if (EventGroup != NULL) {\r
394 //\r
395 // For event group, type EVT_SIGNAL_EXIT_BOOT_SERVICES and EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE\r
396 // are not valid\r
397 //\r
398 if ((Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) || (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)) {\r
399 return EFI_INVALID_PARAMETER;\r
400 }\r
1436aea4 401\r
bb8ffffd 402 if (CompareGuid (EventGroup, &gEfiEventExitBootServicesGuid)) {\r
403 Type = EVT_SIGNAL_EXIT_BOOT_SERVICES;\r
404 } else if (CompareGuid (EventGroup, &gEfiEventVirtualAddressChangeGuid)) {\r
405 Type = EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE;\r
406 }\r
407 } else {\r
408 //\r
409 // Convert EFI 1.10 Events to their UEFI 2.0 CreateEventEx mapping\r
410 //\r
411 if (Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) {\r
412 EventGroup = &gEfiEventExitBootServicesGuid;\r
413 } else if (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {\r
414 EventGroup = &gEfiEventVirtualAddressChangeGuid;\r
415 }\r
416 }\r
417\r
28a00297 418 //\r
419 // If it's a notify type of event, check its parameters\r
420 //\r
71f68914 421 if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {\r
28a00297 422 //\r
423 // Check for an invalid NotifyFunction or NotifyTpl\r
424 //\r
425 if ((NotifyFunction == NULL) ||\r
51b02d81 426 (NotifyTpl <= TPL_APPLICATION) ||\r
1436aea4
MK
427 (NotifyTpl >= TPL_HIGH_LEVEL))\r
428 {\r
28a00297 429 return EFI_INVALID_PARAMETER;\r
430 }\r
28a00297 431 } else {\r
432 //\r
433 // No notification needed, zero ignored values\r
434 //\r
1436aea4 435 NotifyTpl = 0;\r
28a00297 436 NotifyFunction = NULL;\r
1436aea4 437 NotifyContext = NULL;\r
28a00297 438 }\r
439\r
440 //\r
b364eeb0 441 // Allocate and initialize a new event structure.\r
28a00297 442 //\r
b364eeb0 443 if ((Type & EVT_RUNTIME) != 0) {\r
444 IEvent = AllocateRuntimeZeroPool (sizeof (IEVENT));\r
445 } else {\r
446 IEvent = AllocateZeroPool (sizeof (IEVENT));\r
447 }\r
1436aea4 448\r
b364eeb0 449 if (IEvent == NULL) {\r
28a00297 450 return EFI_OUT_OF_RESOURCES;\r
451 }\r
452\r
28a00297 453 IEvent->Signature = EVENT_SIGNATURE;\r
1436aea4 454 IEvent->Type = Type;\r
28a00297 455\r
456 IEvent->NotifyTpl = NotifyTpl;\r
457 IEvent->NotifyFunction = NotifyFunction;\r
458 IEvent->NotifyContext = (VOID *)NotifyContext;\r
459 if (EventGroup != NULL) {\r
460 CopyGuid (&IEvent->EventGroup, EventGroup);\r
82f3edf2 461 IEvent->ExFlag |= EVT_EXFLAG_EVENT_GROUP;\r
28a00297 462 }\r
463\r
464 *Event = IEvent;\r
465\r
71f68914 466 if ((Type & EVT_RUNTIME) != 0) {\r
28a00297 467 //\r
468 // Keep a list of all RT events so we can tell the RT AP.\r
469 //\r
470 IEvent->RuntimeData.Type = Type;\r
471 IEvent->RuntimeData.NotifyTpl = NotifyTpl;\r
472 IEvent->RuntimeData.NotifyFunction = NotifyFunction;\r
1436aea4 473 IEvent->RuntimeData.NotifyContext = (VOID *)NotifyContext;\r
d342d318
LE
474 //\r
475 // Work around the bug in the Platform Init specification (v1.7), reported\r
476 // as Mantis#2017: "EFI_RUNTIME_EVENT_ENTRY.Event" should have type\r
477 // EFI_EVENT, not (EFI_EVENT*). The PI spec documents the field correctly\r
478 // as "The EFI_EVENT returned by CreateEvent()", but the type of the field\r
479 // doesn't match the natural language description. Therefore we need an\r
480 // explicit cast here.\r
481 //\r
1436aea4 482 IEvent->RuntimeData.Event = (EFI_EVENT *)IEvent;\r
28a00297 483 InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);\r
484 }\r
485\r
486 CoreAcquireEventLock ();\r
487\r
488 if ((Type & EVT_NOTIFY_SIGNAL) != 0x00000000) {\r
489 //\r
490 // The Event's NotifyFunction must be queued whenever the event is signaled\r
491 //\r
492 InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);\r
493 }\r
494\r
495 CoreReleaseEventLock ();\r
496\r
497 //\r
498 // Done\r
499 //\r
500 return EFI_SUCCESS;\r
501}\r
502\r
162ed594 503/**\r
e94a9ff7 504 Signals the event. Queues the event to be notified if needed.\r
28a00297 505\r
e94a9ff7 506 @param UserEvent The event to signal .\r
28a00297 507\r
022c6d45 508 @retval EFI_INVALID_PARAMETER Parameters are not valid.\r
162ed594 509 @retval EFI_SUCCESS The event was signaled.\r
28a00297 510\r
162ed594 511**/\r
512EFI_STATUS\r
513EFIAPI\r
514CoreSignalEvent (\r
1436aea4 515 IN EFI_EVENT UserEvent\r
162ed594 516 )\r
28a00297 517{\r
1436aea4 518 IEVENT *Event;\r
28a00297 519\r
520 Event = UserEvent;\r
521\r
522 if (Event == NULL) {\r
523 return EFI_INVALID_PARAMETER;\r
524 }\r
525\r
526 if (Event->Signature != EVENT_SIGNATURE) {\r
527 return EFI_INVALID_PARAMETER;\r
528 }\r
529\r
530 CoreAcquireEventLock ();\r
531\r
532 //\r
533 // If the event is not already signalled, do so\r
534 //\r
535\r
536 if (Event->SignalCount == 0x00000000) {\r
537 Event->SignalCount++;\r
538\r
539 //\r
540 // If signalling type is a notify function, queue it\r
541 //\r
6e536468 542 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
82f3edf2 543 if ((Event->ExFlag & EVT_EXFLAG_EVENT_GROUP) != 0) {\r
28a00297 544 //\r
545 // The CreateEventEx() style requires all members of the Event Group\r
546 // to be signaled.\r
547 //\r
548 CoreReleaseEventLock ();\r
549 CoreNotifySignalList (&Event->EventGroup);\r
550 CoreAcquireEventLock ();\r
1436aea4 551 } else {\r
28a00297 552 CoreNotifyEvent (Event);\r
553 }\r
554 }\r
555 }\r
556\r
557 CoreReleaseEventLock ();\r
558 return EFI_SUCCESS;\r
559}\r
560\r
162ed594 561/**\r
562 Check the status of an event.\r
563\r
022c6d45 564 @param UserEvent The event to check\r
162ed594 565\r
022c6d45 566 @retval EFI_SUCCESS The event is in the signaled state\r
567 @retval EFI_NOT_READY The event is not in the signaled state\r
162ed594 568 @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL\r
569\r
570**/\r
28a00297 571EFI_STATUS\r
572EFIAPI\r
573CoreCheckEvent (\r
1436aea4 574 IN EFI_EVENT UserEvent\r
28a00297 575 )\r
28a00297 576{\r
577 IEVENT *Event;\r
578 EFI_STATUS Status;\r
579\r
580 Event = UserEvent;\r
581\r
582 if (Event == NULL) {\r
583 return EFI_INVALID_PARAMETER;\r
584 }\r
585\r
586 if (Event->Signature != EVENT_SIGNATURE) {\r
587 return EFI_INVALID_PARAMETER;\r
588 }\r
589\r
e94a9ff7 590 if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {\r
28a00297 591 return EFI_INVALID_PARAMETER;\r
592 }\r
593\r
594 Status = EFI_NOT_READY;\r
595\r
6e536468 596 if ((Event->SignalCount == 0) && ((Event->Type & EVT_NOTIFY_WAIT) != 0)) {\r
28a00297 597 //\r
598 // Queue the wait notify function\r
599 //\r
28a00297 600 CoreAcquireEventLock ();\r
6e536468 601 if (Event->SignalCount == 0) {\r
28a00297 602 CoreNotifyEvent (Event);\r
603 }\r
1436aea4 604\r
28a00297 605 CoreReleaseEventLock ();\r
606 }\r
607\r
608 //\r
609 // If the even looks signalled, get the lock and clear it\r
610 //\r
611\r
6e536468 612 if (Event->SignalCount != 0) {\r
28a00297 613 CoreAcquireEventLock ();\r
614\r
6e536468 615 if (Event->SignalCount != 0) {\r
28a00297 616 Event->SignalCount = 0;\r
1436aea4 617 Status = EFI_SUCCESS;\r
28a00297 618 }\r
619\r
620 CoreReleaseEventLock ();\r
621 }\r
622\r
623 return Status;\r
624}\r
625\r
162ed594 626/**\r
627 Stops execution until an event is signaled.\r
628\r
022c6d45 629 @param NumberOfEvents The number of events in the UserEvents array\r
630 @param UserEvents An array of EFI_EVENT\r
631 @param UserIndex Pointer to the index of the event which\r
632 satisfied the wait condition\r
162ed594 633\r
022c6d45 634 @retval EFI_SUCCESS The event indicated by Index was signaled.\r
635 @retval EFI_INVALID_PARAMETER The event indicated by Index has a notification\r
636 function or Event was not a valid type\r
162ed594 637 @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION\r
638\r
639**/\r
28a00297 640EFI_STATUS\r
641EFIAPI\r
642CoreWaitForEvent (\r
1436aea4
MK
643 IN UINTN NumberOfEvents,\r
644 IN EFI_EVENT *UserEvents,\r
645 OUT UINTN *UserIndex\r
28a00297 646 )\r
28a00297 647{\r
1436aea4
MK
648 EFI_STATUS Status;\r
649 UINTN Index;\r
28a00297 650\r
651 //\r
652 // Can only WaitForEvent at TPL_APPLICATION\r
653 //\r
654 if (gEfiCurrentTpl != TPL_APPLICATION) {\r
655 return EFI_UNSUPPORTED;\r
656 }\r
657\r
720f84a9
OM
658 if (NumberOfEvents == 0) {\r
659 return EFI_INVALID_PARAMETER;\r
660 }\r
661\r
662 if (UserEvents == NULL) {\r
663 return EFI_INVALID_PARAMETER;\r
664 }\r
665\r
1436aea4
MK
666 for ( ; ;) {\r
667 for (Index = 0; Index < NumberOfEvents; Index++) {\r
28a00297 668 Status = CoreCheckEvent (UserEvents[Index]);\r
669\r
670 //\r
671 // provide index of event that caused problem\r
672 //\r
673 if (Status != EFI_NOT_READY) {\r
720f84a9
OM
674 if (UserIndex != NULL) {\r
675 *UserIndex = Index;\r
676 }\r
1436aea4 677\r
28a00297 678 return Status;\r
679 }\r
680 }\r
681\r
682 //\r
54cd17e9 683 // Signal the Idle event\r
28a00297 684 //\r
54cd17e9 685 CoreSignalEvent (gIdleLoopEvent);\r
28a00297 686 }\r
687}\r
688\r
162ed594 689/**\r
28a00297 690 Closes an event and frees the event structure.\r
691\r
022c6d45 692 @param UserEvent Event to close\r
28a00297 693\r
022c6d45 694 @retval EFI_INVALID_PARAMETER Parameters are not valid.\r
162ed594 695 @retval EFI_SUCCESS The event has been closed\r
28a00297 696\r
162ed594 697**/\r
698EFI_STATUS\r
699EFIAPI\r
700CoreCloseEvent (\r
1436aea4 701 IN EFI_EVENT UserEvent\r
162ed594 702 )\r
28a00297 703{\r
704 EFI_STATUS Status;\r
705 IEVENT *Event;\r
706\r
707 Event = UserEvent;\r
708\r
709 if (Event == NULL) {\r
710 return EFI_INVALID_PARAMETER;\r
711 }\r
712\r
713 if (Event->Signature != EVENT_SIGNATURE) {\r
714 return EFI_INVALID_PARAMETER;\r
715 }\r
716\r
717 //\r
718 // If it's a timer event, make sure it's not pending\r
719 //\r
e94a9ff7 720 if ((Event->Type & EVT_TIMER) != 0) {\r
28a00297 721 CoreSetTimer (Event, TimerCancel, 0);\r
722 }\r
723\r
724 CoreAcquireEventLock ();\r
725\r
726 //\r
727 // If the event is queued somewhere, remove it\r
728 //\r
729\r
730 if (Event->RuntimeData.Link.ForwardLink != NULL) {\r
731 RemoveEntryList (&Event->RuntimeData.Link);\r
732 }\r
733\r
734 if (Event->NotifyLink.ForwardLink != NULL) {\r
735 RemoveEntryList (&Event->NotifyLink);\r
736 }\r
737\r
738 if (Event->SignalLink.ForwardLink != NULL) {\r
739 RemoveEntryList (&Event->SignalLink);\r
740 }\r
741\r
742 CoreReleaseEventLock ();\r
743\r
744 //\r
745 // If the event is registered on a protocol notify, then remove it from the protocol database\r
746 //\r
82f3edf2
SEHM
747 if ((Event->ExFlag & EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION) != 0) {\r
748 CoreUnregisterProtocolNotify (Event);\r
749 }\r
28a00297 750\r
1a4acc11
SZ
751 //\r
752 // To avoid the Event to be signalled wrongly after closed,\r
753 // clear the Signature of Event before free pool.\r
754 //\r
755 Event->Signature = 0;\r
1436aea4 756 Status = CoreFreePool (Event);\r
28a00297 757 ASSERT_EFI_ERROR (Status);\r
758\r
759 return Status;\r
760}\r