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