ReactOS 0.4.15-dev-7958-gcd0bb1a
dsmethod.c
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2022, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include "acpi.h"
45#include "accommon.h"
46#include "acdispat.h"
47#include "acinterp.h"
48#include "acnamesp.h"
49#include "acparser.h"
50#include "amlcode.h"
51#include "acdebug.h"
52
53
54#define _COMPONENT ACPI_DISPATCHER
55 ACPI_MODULE_NAME ("dsmethod")
56
57/* Local prototypes */
58
59static ACPI_STATUS
61 ACPI_WALK_STATE *WalkState,
62 ACPI_PARSE_OBJECT **OutOp);
63
64static ACPI_STATUS
66 ACPI_OPERAND_OBJECT *MethodDesc);
67
68
69/*******************************************************************************
70 *
71 * FUNCTION: AcpiDsAutoSerializeMethod
72 *
73 * PARAMETERS: Node - Namespace Node of the method
74 * ObjDesc - Method object attached to node
75 *
76 * RETURN: Status
77 *
78 * DESCRIPTION: Parse a control method AML to scan for control methods that
79 * need serialization due to the creation of named objects.
80 *
81 * NOTE: It is a bit of overkill to mark all such methods serialized, since
82 * there is only a problem if the method actually blocks during execution.
83 * A blocking operation is, for example, a Sleep() operation, or any access
84 * to an operation region. However, it is probably not possible to easily
85 * detect whether a method will block or not, so we simply mark all suspicious
86 * methods as serialized.
87 *
88 * NOTE2: This code is essentially a generic routine for parsing a single
89 * control method.
90 *
91 ******************************************************************************/
92
96 ACPI_OPERAND_OBJECT *ObjDesc)
97{
100 ACPI_WALK_STATE *WalkState;
101
102
103 ACPI_FUNCTION_TRACE_PTR (DsAutoSerializeMethod, Node);
104
105
107 "Method auto-serialization parse [%4.4s] %p\n",
109
110 /* Create/Init a root op for the method parse tree */
111
112 Op = AcpiPsAllocOp (AML_METHOD_OP, ObjDesc->Method.AmlStart);
113 if (!Op)
114 {
116 }
117
118 AcpiPsSetName (Op, Node->Name.Integer);
119 Op->Common.Node = Node;
120
121 /* Create and initialize a new walk state */
122
123 WalkState = AcpiDsCreateWalkState (Node->OwnerId, NULL, NULL, NULL);
124 if (!WalkState)
125 {
126 AcpiPsFreeOp (Op);
128 }
129
130 Status = AcpiDsInitAmlWalk (WalkState, Op, Node,
131 ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, NULL, 0);
132 if (ACPI_FAILURE (Status))
133 {
134 AcpiDsDeleteWalkState (WalkState);
135 AcpiPsFreeOp (Op);
137 }
138
139 WalkState->DescendingCallback = AcpiDsDetectNamedOpcodes;
140
141 /* Parse the method, scan for creation of named objects */
142
143 Status = AcpiPsParseAml (WalkState);
144
147}
148
149
150/*******************************************************************************
151 *
152 * FUNCTION: AcpiDsDetectNamedOpcodes
153 *
154 * PARAMETERS: WalkState - Current state of the parse tree walk
155 * OutOp - Unused, required for parser interface
156 *
157 * RETURN: Status
158 *
159 * DESCRIPTION: Descending callback used during the loading of ACPI tables.
160 * Currently used to detect methods that must be marked serialized
161 * in order to avoid problems with the creation of named objects.
162 *
163 ******************************************************************************/
164
165static ACPI_STATUS
167 ACPI_WALK_STATE *WalkState,
168 ACPI_PARSE_OBJECT **OutOp)
169{
170
172
173
174 /* We are only interested in opcodes that create a new name */
175
176 if (!(WalkState->OpInfo->Flags & (AML_NAMED | AML_CREATE | AML_FIELD)))
177 {
178 return (AE_OK);
179 }
180
181 /*
182 * At this point, we know we have a Named object opcode.
183 * Mark the method as serialized. Later code will create a mutex for
184 * this method to enforce serialization.
185 *
186 * Note, ACPI_METHOD_IGNORE_SYNC_LEVEL flag means that we will ignore the
187 * Sync Level mechanism for this method, even though it is now serialized.
188 * Otherwise, there can be conflicts with existing ASL code that actually
189 * uses sync levels.
190 */
191 WalkState->MethodDesc->Method.SyncLevel = 0;
192 WalkState->MethodDesc->Method.InfoFlags |=
194
196 "Method serialized [%4.4s] %p - [%s] (%4.4X)\n",
197 WalkState->MethodNode->Name.Ascii, WalkState->MethodNode,
198 WalkState->OpInfo->Name, WalkState->Opcode));
199
200 /* Abort the parse, no need to examine this method any further */
201
202 return (AE_CTRL_TERMINATE);
203}
204
205
206/*******************************************************************************
207 *
208 * FUNCTION: AcpiDsMethodError
209 *
210 * PARAMETERS: Status - Execution status
211 * WalkState - Current state
212 *
213 * RETURN: Status
214 *
215 * DESCRIPTION: Called on method error. Invoke the global exception handler if
216 * present, dump the method data if the debugger is configured
217 *
218 * Note: Allows the exception handler to change the status code
219 *
220 ******************************************************************************/
221
225 ACPI_WALK_STATE *WalkState)
226{
227 UINT32 AmlOffset;
228 ACPI_NAME Name = 0;
229
230
232
233
234 /* Ignore AE_OK and control exception codes */
235
236 if (ACPI_SUCCESS (Status) ||
238 {
239 return (Status);
240 }
241
242 /* Invoke the global exception handler */
243
244 if (AcpiGbl_ExceptionHandler)
245 {
246 /* Exit the interpreter, allow handler to execute methods */
247
249
250 /*
251 * Handler can map the exception code to anything it wants, including
252 * AE_OK, in which case the executing method will not be aborted.
253 */
254 AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->Aml,
255 WalkState->ParserState.AmlStart);
256
257 if (WalkState->MethodNode)
258 {
259 Name = WalkState->MethodNode->Name.Integer;
260 }
261 else if (WalkState->DeferredNode)
262 {
263 Name = WalkState->DeferredNode->Name.Integer;
264 }
265
266 Status = AcpiGbl_ExceptionHandler (Status, Name,
267 WalkState->Opcode, AmlOffset, NULL);
269 }
270
271 AcpiDsClearImplicitReturn (WalkState);
272
273 if (ACPI_FAILURE (Status))
274 {
275 AcpiDsDumpMethodStack (Status, WalkState, WalkState->Op);
276
277 /* Display method locals/args if debugger is present */
278
279#ifdef ACPI_DEBUGGER
280 AcpiDbDumpMethodInfo (Status, WalkState);
281#endif
282 }
283
284 return (Status);
285}
286
287
288/*******************************************************************************
289 *
290 * FUNCTION: AcpiDsCreateMethodMutex
291 *
292 * PARAMETERS: ObjDesc - The method object
293 *
294 * RETURN: Status
295 *
296 * DESCRIPTION: Create a mutex object for a serialized control method
297 *
298 ******************************************************************************/
299
300static ACPI_STATUS
302 ACPI_OPERAND_OBJECT *MethodDesc)
303{
304 ACPI_OPERAND_OBJECT *MutexDesc;
306
307
308 ACPI_FUNCTION_TRACE (DsCreateMethodMutex);
309
310
311 /* Create the new mutex object */
312
314 if (!MutexDesc)
315 {
317 }
318
319 /* Create the actual OS Mutex */
320
321 Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex);
322 if (ACPI_FAILURE (Status))
323 {
324 AcpiUtDeleteObjectDesc (MutexDesc);
326 }
327
328 MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel;
329 MethodDesc->Method.Mutex = MutexDesc;
331}
332
333
334/*******************************************************************************
335 *
336 * FUNCTION: AcpiDsBeginMethodExecution
337 *
338 * PARAMETERS: MethodNode - Node of the method
339 * ObjDesc - The method object
340 * WalkState - current state, NULL if not yet executing
341 * a method.
342 *
343 * RETURN: Status
344 *
345 * DESCRIPTION: Prepare a method for execution. Parses the method if necessary,
346 * increments the thread count, and waits at the method semaphore
347 * for clearance to execute.
348 *
349 ******************************************************************************/
350
353 ACPI_NAMESPACE_NODE *MethodNode,
354 ACPI_OPERAND_OBJECT *ObjDesc,
355 ACPI_WALK_STATE *WalkState)
356{
358
359
360 ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode);
361
362
363 if (!MethodNode)
364 {
366 }
367
368 AcpiExStartTraceMethod (MethodNode, ObjDesc, WalkState);
369
370 /* Prevent wraparound of thread count */
371
372 if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX)
373 {
375 "Method reached maximum reentrancy limit (255)"));
377 }
378
379 /*
380 * If this method is serialized, we need to acquire the method mutex.
381 */
383 {
384 /*
385 * Create a mutex for the method if it is defined to be Serialized
386 * and a mutex has not already been created. We defer the mutex creation
387 * until a method is actually executed, to minimize the object count
388 */
389 if (!ObjDesc->Method.Mutex)
390 {
392 if (ACPI_FAILURE (Status))
393 {
395 }
396 }
397
398 /*
399 * The CurrentSyncLevel (per-thread) must be less than or equal to
400 * the sync level of the method. This mechanism provides some
401 * deadlock prevention.
402 *
403 * If the method was auto-serialized, we just ignore the sync level
404 * mechanism, because auto-serialization of methods can interfere
405 * with ASL code that actually uses sync levels.
406 *
407 * Top-level method invocation has no walk state at this point
408 */
409 if (WalkState &&
411 (WalkState->Thread->CurrentSyncLevel >
412 ObjDesc->Method.Mutex->Mutex.SyncLevel))
413 {
415 "Cannot acquire Mutex for method [%4.4s]"
416 ", current SyncLevel is too large (%u)",
417 AcpiUtGetNodeName (MethodNode),
418 WalkState->Thread->CurrentSyncLevel));
419
421 }
422
423 /*
424 * Obtain the method mutex if necessary. Do not acquire mutex for a
425 * recursive call.
426 */
427 if (!WalkState ||
428 !ObjDesc->Method.Mutex->Mutex.ThreadId ||
429 (WalkState->Thread->ThreadId !=
430 ObjDesc->Method.Mutex->Mutex.ThreadId))
431 {
432 /*
433 * Acquire the method mutex. This releases the interpreter if we
434 * block (and reacquires it before it returns)
435 */
438 if (ACPI_FAILURE (Status))
439 {
441 }
442
443 /* Update the mutex and walk info and save the original SyncLevel */
444
445 if (WalkState)
446 {
448 WalkState->Thread->CurrentSyncLevel;
449
450 ObjDesc->Method.Mutex->Mutex.ThreadId =
451 WalkState->Thread->ThreadId;
452
453 /*
454 * Update the current SyncLevel only if this is not an auto-
455 * serialized method. In the auto case, we have to ignore
456 * the sync level for the method mutex (created for the
457 * auto-serialization) because we have no idea of what the
458 * sync level should be. Therefore, just ignore it.
459 */
460 if (!(ObjDesc->Method.InfoFlags &
462 {
463 WalkState->Thread->CurrentSyncLevel =
464 ObjDesc->Method.SyncLevel;
465 }
466 }
467 else
468 {
470 ObjDesc->Method.Mutex->Mutex.SyncLevel;
471
472 ObjDesc->Method.Mutex->Mutex.ThreadId =
474 }
475 }
476
477 /* Always increase acquisition depth */
478
480 }
481
482 /*
483 * Allocate an Owner ID for this method, only if this is the first thread
484 * to begin concurrent execution. We only need one OwnerId, even if the
485 * method is invoked recursively.
486 */
487 if (!ObjDesc->Method.OwnerId)
488 {
490 if (ACPI_FAILURE (Status))
491 {
492 goto Cleanup;
493 }
494 }
495
496 /*
497 * Increment the method parse tree thread count since it has been
498 * reentered one more time (even if it is the same thread)
499 */
500 ObjDesc->Method.ThreadCount++;
501 AcpiMethodCount++;
503
504
505Cleanup:
506 /* On error, must release the method mutex (if present) */
507
508 if (ObjDesc->Method.Mutex)
509 {
511 }
513}
514
515
516/*******************************************************************************
517 *
518 * FUNCTION: AcpiDsCallControlMethod
519 *
520 * PARAMETERS: Thread - Info for this thread
521 * ThisWalkState - Current walk state
522 * Op - Current Op to be walked
523 *
524 * RETURN: Status
525 *
526 * DESCRIPTION: Transfer execution to a called control method
527 *
528 ******************************************************************************/
529
533 ACPI_WALK_STATE *ThisWalkState,
535{
537 ACPI_NAMESPACE_NODE *MethodNode;
538 ACPI_WALK_STATE *NextWalkState = NULL;
539 ACPI_OPERAND_OBJECT *ObjDesc;
541 UINT32 i;
542
543
544 ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState);
545
547 "Calling method %p, currentstate=%p\n",
548 ThisWalkState->PrevOp, ThisWalkState));
549
550 /*
551 * Get the namespace entry for the control method we are about to call
552 */
553 MethodNode = ThisWalkState->MethodCallNode;
554 if (!MethodNode)
555 {
557 }
558
559 ObjDesc = AcpiNsGetAttachedObject (MethodNode);
560 if (!ObjDesc)
561 {
563 }
564
565 /* Init for new method, possibly wait on method mutex */
566
568 MethodNode, ObjDesc, ThisWalkState);
569 if (ACPI_FAILURE (Status))
570 {
572 }
573
574 /* Begin method parse/execution. Create a new walk state */
575
576 NextWalkState = AcpiDsCreateWalkState (
577 ObjDesc->Method.OwnerId, NULL, ObjDesc, Thread);
578 if (!NextWalkState)
579 {
581 goto Cleanup;
582 }
583
584 /*
585 * The resolved arguments were put on the previous walk state's operand
586 * stack. Operands on the previous walk state stack always
587 * start at index 0. Also, null terminate the list of arguments
588 */
589 ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL;
590
591 /*
592 * Allocate and initialize the evaluation information block
593 * TBD: this is somewhat inefficient, should change interface to
594 * DsInitAmlWalk. For now, keeps this struct off the CPU stack
595 */
597 if (!Info)
598 {
600 goto Cleanup;
601 }
602
603 Info->Parameters = &ThisWalkState->Operands[0];
604
605 Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode,
606 ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength,
608
609 ACPI_FREE (Info);
610 if (ACPI_FAILURE (Status))
611 {
612 goto Cleanup;
613 }
614
615 NextWalkState->MethodNestingDepth = ThisWalkState->MethodNestingDepth + 1;
616
617 /*
618 * Delete the operands on the previous walkstate operand stack
619 * (they were copied to new objects)
620 */
621 for (i = 0; i < ObjDesc->Method.ParamCount; i++)
622 {
623 AcpiUtRemoveReference (ThisWalkState->Operands [i]);
624 ThisWalkState->Operands [i] = NULL;
625 }
626
627 /* Clear the operand stack */
628
629 ThisWalkState->NumOperands = 0;
630
632 "**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
633 MethodNode->Name.Ascii, NextWalkState));
634
635 ThisWalkState->MethodPathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE);
636 ThisWalkState->MethodIsNested = TRUE;
637
638 /* Optional object evaluation log */
639
641 "%-26s: %*s%s\n", " Nested method call",
642 NextWalkState->MethodNestingDepth * 3, " ",
643 &ThisWalkState->MethodPathname[1]));
644
645 /* Invoke an internal method if necessary */
646
648 {
649 Status = ObjDesc->Method.Dispatch.Implementation (NextWalkState);
650 if (Status == AE_OK)
651 {
653 }
654 }
655
657
658
659Cleanup:
660
661 /* On error, we must terminate the method properly */
662
663 AcpiDsTerminateControlMethod (ObjDesc, NextWalkState);
664 AcpiDsDeleteWalkState (NextWalkState);
665
667}
668
669
670/*******************************************************************************
671 *
672 * FUNCTION: AcpiDsRestartControlMethod
673 *
674 * PARAMETERS: WalkState - State for preempted method (caller)
675 * ReturnDesc - Return value from the called method
676 *
677 * RETURN: Status
678 *
679 * DESCRIPTION: Restart a method that was preempted by another (nested) method
680 * invocation. Handle the return value (if any) from the callee.
681 *
682 ******************************************************************************/
683
686 ACPI_WALK_STATE *WalkState,
687 ACPI_OPERAND_OBJECT *ReturnDesc)
688{
690 int SameAsImplicitReturn;
691
692
693 ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState);
694
695
697 "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
698 AcpiUtGetNodeName (WalkState->MethodNode),
699 WalkState->MethodCallOp, ReturnDesc));
700
702 " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
703 WalkState->ReturnUsed,
704 WalkState->Results, WalkState));
705
706 /* Did the called method return a value? */
707
708 if (ReturnDesc)
709 {
710 /* Is the implicit return object the same as the return desc? */
711
712 SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc);
713
714 /* Are we actually going to use the return value? */
715
716 if (WalkState->ReturnUsed)
717 {
718 /* Save the return value from the previous method */
719
720 Status = AcpiDsResultPush (ReturnDesc, WalkState);
721 if (ACPI_FAILURE (Status))
722 {
723 AcpiUtRemoveReference (ReturnDesc);
725 }
726
727 /*
728 * Save as THIS method's return value in case it is returned
729 * immediately to yet another method
730 */
731 WalkState->ReturnDesc = ReturnDesc;
732 }
733
734 /*
735 * The following code is the optional support for the so-called
736 * "implicit return". Some AML code assumes that the last value of the
737 * method is "implicitly" returned to the caller, in the absence of an
738 * explicit return value.
739 *
740 * Just save the last result of the method as the return value.
741 *
742 * NOTE: this is optional because the ASL language does not actually
743 * support this behavior.
744 */
745 else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) ||
746 SameAsImplicitReturn)
747 {
748 /*
749 * Delete the return value if it will not be used by the
750 * calling method or remove one reference if the explicit return
751 * is the same as the implicit return value.
752 */
753 AcpiUtRemoveReference (ReturnDesc);
754 }
755 }
756
758}
759
760
761/*******************************************************************************
762 *
763 * FUNCTION: AcpiDsTerminateControlMethod
764 *
765 * PARAMETERS: MethodDesc - Method object
766 * WalkState - State associated with the method
767 *
768 * RETURN: None
769 *
770 * DESCRIPTION: Terminate a control method. Delete everything that the method
771 * created, delete all locals and arguments, and delete the parse
772 * tree if requested.
773 *
774 * MUTEX: Interpreter is locked
775 *
776 ******************************************************************************/
777
778void
780 ACPI_OPERAND_OBJECT *MethodDesc,
781 ACPI_WALK_STATE *WalkState)
782{
783
784 ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState);
785
786
787 /* MethodDesc is required, WalkState is optional */
788
789 if (!MethodDesc)
790 {
792 }
793
794 if (WalkState)
795 {
796 /* Delete all arguments and locals */
797
798 AcpiDsMethodDataDeleteAll (WalkState);
799
800 /*
801 * Delete any namespace objects created anywhere within the
802 * namespace by the execution of this method. Unless:
803 * 1) This method is a module-level executable code method, in which
804 * case we want make the objects permanent.
805 * 2) There are other threads executing the method, in which case we
806 * will wait until the last thread has completed.
807 */
808 if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) &&
809 (MethodDesc->Method.ThreadCount == 1))
810 {
811 /* Delete any direct children of (created by) this method */
812
816
817 /*
818 * Delete any objects that were created by this method
819 * elsewhere in the namespace (if any were created).
820 * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the
821 * deletion such that we don't have to perform an entire
822 * namespace walk for every control method execution.
823 */
825 {
829 MethodDesc->Method.InfoFlags &=
830 ~ACPI_METHOD_MODIFIED_NAMESPACE;
831 }
832 }
833
834 /*
835 * If method is serialized, release the mutex and restore the
836 * current sync level for this thread
837 */
838 if (MethodDesc->Method.Mutex)
839 {
840 /* Acquisition Depth handles recursive calls */
841
842 MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--;
843 if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth)
844 {
845 WalkState->Thread->CurrentSyncLevel =
846 MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel;
847
849 MethodDesc->Method.Mutex->Mutex.OsMutex);
850 MethodDesc->Method.Mutex->Mutex.ThreadId = 0;
851 }
852 }
853 }
854
855 /* Decrement the thread count on the method */
856
857 if (MethodDesc->Method.ThreadCount)
858 {
859 MethodDesc->Method.ThreadCount--;
860 }
861 else
862 {
864 "Invalid zero thread count in method"));
865 }
866
867 /* Are there any other threads currently executing this method? */
868
869 if (MethodDesc->Method.ThreadCount)
870 {
871 /*
872 * Additional threads. Do not release the OwnerId in this case,
873 * we immediately reuse it for the next thread executing this method
874 */
876 "*** Completed execution of one thread, %u threads remaining\n",
877 MethodDesc->Method.ThreadCount));
878 }
879 else
880 {
881 /* This is the only executing thread for this method */
882
883 /*
884 * Support to dynamically change a method from NotSerialized to
885 * Serialized if it appears that the method is incorrectly written and
886 * does not support multiple thread execution. The best example of this
887 * is if such a method creates namespace objects and blocks. A second
888 * thread will fail with an AE_ALREADY_EXISTS exception.
889 *
890 * This code is here because we must wait until the last thread exits
891 * before marking the method as serialized.
892 */
894 {
895 if (WalkState)
896 {
897 ACPI_INFO ((
898 "Marking method %4.4s as Serialized "
899 "because of AE_ALREADY_EXISTS error",
900 WalkState->MethodNode->Name.Ascii));
901 }
902
903 /*
904 * Method tried to create an object twice and was marked as
905 * "pending serialized". The probable cause is that the method
906 * cannot handle reentrancy.
907 *
908 * The method was created as NotSerialized, but it tried to create
909 * a named object and then blocked, causing the second thread
910 * entrance to begin and then fail. Workaround this problem by
911 * marking the method permanently as Serialized when the last
912 * thread exits here.
913 */
914 MethodDesc->Method.InfoFlags &=
915 ~ACPI_METHOD_SERIALIZED_PENDING;
916
917 MethodDesc->Method.InfoFlags |=
919 MethodDesc->Method.SyncLevel = 0;
920 }
921
922 /* No more threads, we can free the OwnerId */
923
924 if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL))
925 {
926 AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId);
927 }
928 }
929
931 MethodDesc, WalkState);
932
934}
unsigned int UINT32
void AcpiDbDumpMethodInfo(ACPI_STATUS Status, ACPI_WALK_STATE *WalkState)
#define ACPI_FAILURE(a)
Definition: acexcep.h:95
#define AE_CODE_CONTROL
Definition: acexcep.h:57
#define AE_NULL_ENTRY
Definition: acexcep.h:118
#define AE_CTRL_TERMINATE
Definition: acexcep.h:226
#define AE_NULL_OBJECT
Definition: acexcep.h:117
#define AE_AML_MUTEX_ORDER
Definition: acexcep.h:200
#define AE_NO_MEMORY
Definition: acexcep.h:112
#define AE_AML_METHOD_LIMIT
Definition: acexcep.h:198
#define ACPI_SUCCESS(a)
Definition: acexcep.h:94
#define AE_OK
Definition: acexcep.h:97
@ ACPI_IMODE_EXECUTE
Definition: aclocal.h:169
char * AcpiNsGetNormalizedPathname(ACPI_NAMESPACE_NODE *Node, BOOLEAN NoTrailing)
Definition: nsnames.c:367
void AcpiNsDeleteNamespaceSubtree(ACPI_NAMESPACE_NODE *ParentHandle)
Definition: nsalloc.c:399
ACPI_OPERAND_OBJECT * AcpiNsGetAttachedObject(ACPI_NAMESPACE_NODE *Node)
Definition: nsobject.c:308
void AcpiNsDeleteNamespaceByOwner(ACPI_OWNER_ID OwnerId)
Definition: nsalloc.c:497
#define ACPI_METHOD_IGNORE_SYNC_LEVEL
Definition: acobject.h:240
#define ACPI_METHOD_MODIFIED_NAMESPACE
Definition: acobject.h:241
#define ACPI_METHOD_MODULE_LEVEL
Definition: acobject.h:236
#define ACPI_METHOD_SERIALIZED
Definition: acobject.h:238
#define ACPI_METHOD_SERIALIZED_PENDING
Definition: acobject.h:239
#define ACPI_METHOD_INTERNAL_ONLY
Definition: acobject.h:237
#define ACPI_DB_DISPATCH
Definition: acoutput.h:163
#define ACPI_DEBUG_PRINT(pl)
Definition: acoutput.h:475
#define ACPI_DB_PARSE
Definition: acoutput.h:162
#define ACPI_MODULE_NAME(Name)
Definition: acoutput.h:216
#define ACPI_FUNCTION_ENTRY()
Definition: acoutput.h:484
#define ACPI_FUNCTION_TRACE_PTR(a, b)
Definition: acoutput.h:481
#define return_ACPI_STATUS(s)
Definition: acoutput.h:496
#define ACPI_FUNCTION_TRACE(a)
Definition: acoutput.h:480
#define ACPI_ERROR(plist)
Definition: acoutput.h:240
#define AE_INFO
Definition: acoutput.h:230
#define ACPI_INFO(plist)
Definition: acoutput.h:237
#define ACPI_DEBUG_PRINT_RAW(pl)
Definition: acoutput.h:476
#define return_VOID
Definition: acoutput.h:495
#define ACPI_DB_INFO
Definition: acoutput.h:153
#define ACPI_DB_EVALUATION
Definition: acoutput.h:181
#define ACPI_FUNCTION_NAME(a)
Definition: acoutput.h:479
void AcpiPsSetName(ACPI_PARSE_OBJECT *op, UINT32 name)
Definition: psutils.c:281
void AcpiPsDeleteParseTree(ACPI_PARSE_OBJECT *root)
Definition: pswalk.c:67
void AcpiPsFreeOp(ACPI_PARSE_OBJECT *Op)
Definition: psutils.c:212
ACPI_STATUS AcpiPsParseAml(ACPI_WALK_STATE *WalkState)
Definition: psparse.c:453
ACPI_PARSE_OBJECT * AcpiPsAllocOp(UINT16 Opcode, UINT8 *Aml)
Definition: psutils.c:130
ACPI_THREAD_ID AcpiOsGetThreadId(void)
Definition: osl.c:217
#define ACPI_TYPE_MUTEX
Definition: actypes.h:696
#define ACPI_FREE(a)
Definition: actypes.h:386
UINT32 ACPI_STATUS
Definition: actypes.h:460
#define AcpiOsReleaseMutex(Handle)
Definition: actypes.h:277
#define ACPI_WAIT_FOREVER
Definition: actypes.h:501
#define ACPI_ALLOCATE_ZEROED(a)
Definition: actypes.h:385
#define ACPI_PTR_DIFF(a, b)
Definition: actypes.h:548
#define ACPI_UINT8_MAX
Definition: actypes.h:64
#define AcpiOsCreateMutex(OutHandle)
Definition: actypes.h:274
UINT32 ACPI_NAME
Definition: actypes.h:461
#define AcpiUtCreateInternalObject(t)
Definition: acutils.h:681
void AcpiUtReleaseOwnerId(ACPI_OWNER_ID *OwnerId)
Definition: utownerid.c:190
ACPI_STATUS AcpiUtAllocateOwnerId(ACPI_OWNER_ID *OwnerId)
Definition: utownerid.c:68
const char * AcpiUtGetNodeName(void *Object)
Definition: utdecode.c:306
void AcpiUtRemoveReference(ACPI_OPERAND_OBJECT *Object)
Definition: utdelete.c:790
void AcpiUtDeleteObjectDesc(ACPI_OPERAND_OBJECT *Object)
Definition: utobject.c:473
#define AML_FIELD
Definition: amlcode.h:321
#define AML_METHOD_OP
Definition: amlcode.h:64
#define AML_CREATE
Definition: amlcode.h:320
#define AML_NAMED
Definition: amlcode.h:323
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
union node Node
Definition: types.h:1255
static const WCHAR Cleanup[]
Definition: register.c:80
void AcpiDsDumpMethodStack(ACPI_STATUS Status, ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op)
Definition: dsdebug.c:249
ACPI_STATUS AcpiDsRestartControlMethod(ACPI_WALK_STATE *WalkState, ACPI_OPERAND_OBJECT *ReturnDesc)
Definition: dsmethod.c:685
ACPI_STATUS AcpiDsAutoSerializeMethod(ACPI_NAMESPACE_NODE *Node, ACPI_OPERAND_OBJECT *ObjDesc)
Definition: dsmethod.c:94
ACPI_STATUS AcpiDsMethodError(ACPI_STATUS Status, ACPI_WALK_STATE *WalkState)
Definition: dsmethod.c:223
void AcpiDsTerminateControlMethod(ACPI_OPERAND_OBJECT *MethodDesc, ACPI_WALK_STATE *WalkState)
Definition: dsmethod.c:779
ACPI_STATUS AcpiDsBeginMethodExecution(ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState)
Definition: dsmethod.c:352
ACPI_STATUS AcpiDsCallControlMethod(ACPI_THREAD_STATE *Thread, ACPI_WALK_STATE *ThisWalkState, ACPI_PARSE_OBJECT *Op)
Definition: dsmethod.c:531
static ACPI_STATUS AcpiDsDetectNamedOpcodes(ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT **OutOp)
Definition: dsmethod.c:166
static ACPI_STATUS AcpiDsCreateMethodMutex(ACPI_OPERAND_OBJECT *MethodDesc)
Definition: dsmethod.c:301
void AcpiDsMethodDataDeleteAll(ACPI_WALK_STATE *WalkState)
Definition: dsmthdat.c:153
void AcpiDsClearImplicitReturn(ACPI_WALK_STATE *WalkState)
Definition: dsutils.c:73
BOOLEAN AcpiDsDoImplicitReturn(ACPI_OPERAND_OBJECT *ReturnDesc, ACPI_WALK_STATE *WalkState, BOOLEAN AddReference)
Definition: dsutils.c:123
ACPI_WALK_STATE * AcpiDsCreateWalkState(ACPI_OWNER_ID OwnerId, ACPI_PARSE_OBJECT *Origin, ACPI_OPERAND_OBJECT *MethodDesc, ACPI_THREAD_STATE *Thread)
Definition: dswstate.c:600
ACPI_STATUS AcpiDsInitAmlWalk(ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op, ACPI_NAMESPACE_NODE *MethodNode, UINT8 *AmlStart, UINT32 AmlLength, ACPI_EVALUATE_INFO *Info, UINT8 PassNumber)
Definition: dswstate.c:662
ACPI_STATUS AcpiDsResultPush(ACPI_OPERAND_OBJECT *Object, ACPI_WALK_STATE *WalkState)
Definition: dswstate.c:160
void AcpiDsDeleteWalkState(ACPI_WALK_STATE *WalkState)
Definition: dswstate.c:780
ACPI_STATUS AcpiExSystemWaitMutex(ACPI_MUTEX Mutex, UINT16 Timeout)
Definition: exsystem.c:120
void AcpiExStopTraceMethod(ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState)
Definition: extrace.c:290
void AcpiExStartTraceMethod(ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState)
Definition: extrace.c:224
void AcpiExExitInterpreter(void)
Definition: exutils.c:139
void AcpiExEnterInterpreter(void)
Definition: exutils.c:91
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ACPI_NAME_UNION Name
Definition: aclocal.h:191
ACPI_OWNER_ID OwnerId
Definition: acobject.h:229
UINT8 * AmlStart
Definition: acobject.h:221
union acpi_object_method::@610 Dispatch
ACPI_OBJECT_COMMON_HEADER UINT8 InfoFlags
Definition: acobject.h:216
ACPI_INTERNAL_METHOD Implementation
Definition: acobject.h:224
union acpi_operand_object * Mutex
Definition: acobject.h:219
union acpi_operand_object * Node
Definition: acobject.h:220
ACPI_OBJECT_COMMON_HEADER UINT8 SyncLevel
Definition: acobject.h:186
UINT16 AcquisitionDepth
Definition: acobject.h:187
ACPI_THREAD_ID ThreadId
Definition: acobject.h:189
ACPI_MUTEX OsMutex
Definition: acobject.h:188
UINT8 OriginalSyncLevel
Definition: acobject.h:194
UINT16 Flags
Definition: aclocal.h:873
UINT8 * AmlStart
Definition: aclocal.h:1101
ACPI_STATE_COMMON UINT8 CurrentSyncLevel
Definition: aclocal.h:764
ACPI_THREAD_ID ThreadId
Definition: aclocal.h:767
UINT8 * Aml
Definition: acstruct.h:91
union acpi_operand_object * ImplicitReturnObj
Definition: acstruct.h:112
union acpi_operand_object * MethodDesc
Definition: acstruct.h:115
union acpi_operand_object * Operands[ACPI_OBJ_NUM_OPERANDS+1]
Definition: acstruct.h:105
ACPI_GENERIC_STATE * Results
Definition: acstruct.h:122
union acpi_operand_object * ReturnDesc
Definition: acstruct.h:123
char * MethodPathname
Definition: acstruct.h:117
struct acpi_namespace_node * MethodNode
Definition: acstruct.h:116
ACPI_PARSE_OBJECT * Op
Definition: acstruct.h:118
UINT16 MethodNestingDepth
Definition: acstruct.h:100
UINT8 MethodIsNested
Definition: acstruct.h:101
ACPI_PARSE_OBJECT * PrevOp
Definition: acstruct.h:125
ACPI_PARSE_OBJECT * MethodCallOp
Definition: acstruct.h:114
UINT16 Opcode
Definition: acstruct.h:78
const ACPI_OPCODE_INFO * OpInfo
Definition: acstruct.h:119
UINT8 ReturnUsed
Definition: acstruct.h:85
UINT8 NumOperands
Definition: acstruct.h:80
struct acpi_namespace_node * DeferredNode
Definition: acstruct.h:111
ACPI_THREAD_STATE * Thread
Definition: acstruct.h:127
ACPI_PARSE_STATE ParserState
Definition: acstruct.h:97
struct acpi_namespace_node * MethodCallNode
Definition: acstruct.h:113
char Ascii[4]
Definition: actbl.h:394
ACPI_OBJECT_METHOD Method
Definition: acobject.h:525
ACPI_OBJECT_MUTEX Mutex
Definition: acobject.h:526
ACPI_PARSE_OBJ_COMMON Common
Definition: aclocal.h:1078
Definition: dlist.c:348
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690