ReactOS  0.4.13-dev-73-gcfe54aa
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 - 2019, 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 MERCHANTIBILITY 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 
59 static ACPI_STATUS
61  ACPI_WALK_STATE *WalkState,
62  ACPI_PARSE_OBJECT **OutOp);
63 
64 static 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 {
99  ACPI_PARSE_OBJECT *Op = NULL;
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 
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 
165 static 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 
300 static 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  */
382  if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED)
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  {
391  Status = AcpiDsCreateMethodMutex (ObjDesc);
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  {
447  ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
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  {
469  ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
470  ObjDesc->Method.Mutex->Mutex.SyncLevel;
471 
472  ObjDesc->Method.Mutex->Mutex.ThreadId =
474  }
475  }
476 
477  /* Always increase acquisition depth */
478 
479  ObjDesc->Method.Mutex->Mutex.AcquisitionDepth++;
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 
505 Cleanup:
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,
534  ACPI_PARSE_OBJECT *Op)
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 
659 Cleanup:
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 
778 void
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  {
791  return_VOID;
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 &=
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 &=
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 
933  return_VOID;
934 }
#define ACPI_DEBUG_PRINT_RAW(pl)
Definition: acoutput.h:476
#define AE_NULL_OBJECT
Definition: acexcep.h:117
#define ACPI_FREE(a)
Definition: actypes.h:386
ACPI_THREAD_STATE * Thread
Definition: acstruct.h:127
ACPI_STATUS AcpiDsMethodError(ACPI_STATUS Status, ACPI_WALK_STATE *WalkState)
Definition: dsmethod.c:223
char * MethodPathname
Definition: acstruct.h:117
UINT8 * AmlStart
Definition: acobject.h:220
void AcpiPsDeleteParseTree(ACPI_PARSE_OBJECT *root)
Definition: pswalk.c:67
ACPI_PARSE_OBJ_COMMON Common
Definition: aclocal.h:1078
#define AML_NAMED
Definition: amlcode.h:323
#define ACPI_ALLOCATE_ZEROED(a)
Definition: actypes.h:385
#define TRUE
Definition: types.h:120
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
union acpi_operand_object * ImplicitReturnObj
Definition: acstruct.h:112
ACPI_GENERIC_STATE * Results
Definition: acstruct.h:122
void AcpiDsDeleteWalkState(ACPI_WALK_STATE *WalkState)
Definition: dswstate.c:780
ACPI_PARSE_OBJECT * PrevOp
Definition: acstruct.h:125
#define ACPI_METHOD_IGNORE_SYNC_LEVEL
Definition: acobject.h:239
void AcpiUtReleaseOwnerId(ACPI_OWNER_ID *OwnerId)
Definition: utownerid.c:190
#define ACPI_SUCCESS(a)
Definition: acexcep.h:94
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
ACPI_THREAD_ID AcpiOsGetThreadId(void)
Definition: osl.c:217
ACPI_WALK_STATE * AcpiDsCreateWalkState(ACPI_OWNER_ID OwnerId, ACPI_PARSE_OBJECT *Origin, ACPI_OPERAND_OBJECT *MethodDesc, ACPI_THREAD_STATE *Thread)
Definition: dswstate.c:600
#define AE_NO_MEMORY
Definition: acexcep.h:112
ACPI_MUTEX OsMutex
Definition: acobject.h:188
#define ACPI_METHOD_SERIALIZED
Definition: acobject.h:237
UINT8 NumOperands
Definition: acstruct.h:80
ACPI_OBJECT_COMMON_HEADER UINT8 InfoFlags
Definition: acobject.h:215
ACPI_OBJECT_MUTEX Mutex
Definition: acobject.h:523
union acpi_object_method::@576 Dispatch
#define ACPI_PTR_DIFF(a, b)
Definition: actypes.h:548
#define AE_AML_METHOD_LIMIT
Definition: acexcep.h:198
struct acpi_namespace_node * DeferredNode
Definition: acstruct.h:111
void AcpiUtDeleteObjectDesc(ACPI_OPERAND_OBJECT *Object)
Definition: utobject.c:473
char Ascii[4]
Definition: actbl.h:394
ACPI_STATUS AcpiDsRestartControlMethod(ACPI_WALK_STATE *WalkState, ACPI_OPERAND_OBJECT *ReturnDesc)
Definition: dsmethod.c:685
ACPI_PARSE_OBJECT * AcpiPsAllocOp(UINT16 Opcode, UINT8 *Aml)
Definition: psutils.c:130
union acpi_operand_object * ReturnDesc
Definition: acstruct.h:123
#define ACPI_DB_PARSE
Definition: acoutput.h:162
UINT32 ACPI_STATUS
Definition: actypes.h:460
ACPI_OBJECT_COMMON_HEADER UINT8 SyncLevel
Definition: acobject.h:186
struct TraceInfo Info
UINT8 OriginalSyncLevel
Definition: acobject.h:194
ACPI_STATUS AcpiDsResultPush(ACPI_OPERAND_OBJECT *Object, ACPI_WALK_STATE *WalkState)
Definition: dswstate.c:160
UINT16 AcquisitionDepth
Definition: acobject.h:187
BOOLEAN AcpiDsDoImplicitReturn(ACPI_OPERAND_OBJECT *ReturnDesc, ACPI_WALK_STATE *WalkState, BOOLEAN AddReference)
Definition: dsutils.c:123
#define AE_AML_MUTEX_ORDER
Definition: acexcep.h:200
#define ACPI_FAILURE(a)
Definition: acexcep.h:95
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
#define AML_CREATE
Definition: amlcode.h:320
#define AE_CTRL_TERMINATE
Definition: acexcep.h:226
unsigned int UINT32
union node Node
Definition: types.h:1255
ACPI_STATUS AcpiExSystemWaitMutex(ACPI_MUTEX Mutex, UINT16 Timeout)
Definition: exsystem.c:120
#define ACPI_MODULE_NAME(Name)
Definition: acoutput.h:216
#define ACPI_METHOD_MODIFIED_NAMESPACE
Definition: acobject.h:240
#define ACPI_UINT8_MAX
Definition: actypes.h:64
#define AE_INFO
Definition: acoutput.h:230
smooth NULL
Definition: ftsmooth.c:416
void AcpiExStartTraceMethod(ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState)
Definition: extrace.c:224
struct acpi_namespace_node * MethodCallNode
Definition: acstruct.h:113
ACPI_NAME_UNION Name
Definition: aclocal.h:192
#define ACPI_METHOD_SERIALIZED_PENDING
Definition: acobject.h:238
#define ACPI_FUNCTION_ENTRY()
Definition: acoutput.h:484
#define ACPI_FUNCTION_TRACE_PTR(a, b)
Definition: acoutput.h:481
static ACPI_STATUS AcpiDsDetectNamedOpcodes(ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT **OutOp)
Definition: dsmethod.c:166
#define ACPI_DB_DISPATCH
Definition: acoutput.h:163
ACPI_STATUS AcpiDsAutoSerializeMethod(ACPI_NAMESPACE_NODE *Node, ACPI_OPERAND_OBJECT *ObjDesc)
Definition: dsmethod.c:94
void AcpiDsMethodDataDeleteAll(ACPI_WALK_STATE *WalkState)
Definition: dsmthdat.c:153
#define ACPI_METHOD_INTERNAL_ONLY
Definition: acobject.h:236
ACPI_STATE_COMMON UINT8 CurrentSyncLevel
Definition: aclocal.h:764
ACPI_STATUS AcpiDsBeginMethodExecution(ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState)
Definition: dsmethod.c:352
#define ACPI_WAIT_FOREVER
Definition: actypes.h:501
UINT16 MethodNestingDepth
Definition: acstruct.h:100
ACPI_PARSE_OBJECT * Op
Definition: acstruct.h:118
union acpi_operand_object * MethodDesc
Definition: acstruct.h:115
#define ACPI_DEBUG_PRINT(pl)
Definition: acoutput.h:475
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
void AcpiPsSetName(ACPI_PARSE_OBJECT *op, UINT32 name)
Definition: psutils.c:281
void AcpiDbDumpMethodInfo(ACPI_STATUS Status, ACPI_WALK_STATE *WalkState)
UINT8 * AmlStart
Definition: aclocal.h:1101
#define AML_FIELD
Definition: amlcode.h:321
ACPI_PARSE_OBJECT * MethodCallOp
Definition: acstruct.h:114
ACPI_OPERAND_OBJECT * AcpiNsGetAttachedObject(ACPI_NAMESPACE_NODE *Node)
Definition: nsobject.c:308
ACPI_INTERNAL_METHOD Implementation
Definition: acobject.h:223
static ACPI_STATUS AcpiDsCreateMethodMutex(ACPI_OPERAND_OBJECT *MethodDesc)
Definition: dsmethod.c:301
const ACPI_OPCODE_INFO * OpInfo
Definition: acstruct.h:119
#define return_VOID
Definition: acoutput.h:495
void AcpiNsDeleteNamespaceSubtree(ACPI_NAMESPACE_NODE *ParentHandle)
Definition: nsalloc.c:399
ACPI_THREAD_ID ThreadId
Definition: acobject.h:189
ACPI_PARSE_STATE ParserState
Definition: acstruct.h:97
UINT32 ACPI_NAME
Definition: actypes.h:461
#define ACPI_METHOD_MODULE_LEVEL
Definition: acobject.h:235
#define AML_METHOD_OP
Definition: amlcode.h:64
union acpi_operand_object * Mutex
Definition: acobject.h:218
static const WCHAR Cleanup[]
Definition: register.c:80
struct acpi_namespace_node * MethodNode
Definition: acstruct.h:116
#define ACPI_INFO(plist)
Definition: acoutput.h:237
Status
Definition: gdiplustypes.h:24
ACPI_OBJECT_METHOD Method
Definition: acobject.h:522
UINT8 ReturnUsed
Definition: acstruct.h:85
char * AcpiNsGetNormalizedPathname(ACPI_NAMESPACE_NODE *Node, BOOLEAN NoTrailing)
Definition: nsnames.c:373
union acpi_operand_object * Operands[ACPI_OBJ_NUM_OPERANDS+1]
Definition: acstruct.h:105
ACPI_PARSE_DOWNWARDS DescendingCallback
Definition: acstruct.h:128
#define ACPI_DB_INFO
Definition: acoutput.h:153
void AcpiExExitInterpreter(void)
Definition: exutils.c:139
ACPI_STATUS AcpiUtAllocateOwnerId(ACPI_OWNER_ID *OwnerId)
Definition: utownerid.c:68
void AcpiExEnterInterpreter(void)
Definition: exutils.c:91
#define return_ACPI_STATUS(s)
Definition: acoutput.h:496
#define ACPI_FUNCTION_TRACE(a)
Definition: acoutput.h:480
void AcpiExStopTraceMethod(ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState)
Definition: extrace.c:290
void AcpiUtRemoveReference(ACPI_OPERAND_OBJECT *Object)
Definition: utdelete.c:784
#define AE_NULL_ENTRY
Definition: acexcep.h:118
#define AE_CODE_CONTROL
Definition: acexcep.h:57
#define ACPI_TYPE_MUTEX
Definition: actypes.h:687
ACPI_STATUS AcpiDsCallControlMethod(ACPI_THREAD_STATE *Thread, ACPI_WALK_STATE *ThisWalkState, ACPI_PARSE_OBJECT *Op)
Definition: dsmethod.c:531
ACPI_STATUS AcpiOsCreateMutex(ACPI_MUTEX *OutHandle)
Definition: osl.c:271
#define ACPI_ERROR(plist)
Definition: acoutput.h:240
void AcpiDsDumpMethodStack(ACPI_STATUS Status, ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op)
Definition: dsdebug.c:249
ACPI_STATUS AcpiPsParseAml(ACPI_WALK_STATE *WalkState)
Definition: psparse.c:453
void AcpiPsFreeOp(ACPI_PARSE_OBJECT *Op)
Definition: psutils.c:212
const char * AcpiUtGetNodeName(void *Object)
Definition: utdecode.c:305
#define ACPI_DB_EVALUATION
Definition: acoutput.h:181
void AcpiOsReleaseMutex(ACPI_MUTEX Handle)
Definition: osl.c:333
ACPI_THREAD_ID ThreadId
Definition: aclocal.h:767
UINT16 Opcode
Definition: acstruct.h:78
#define ACPI_FUNCTION_NAME(a)
Definition: acoutput.h:479
ACPI_OWNER_ID OwnerId
Definition: acobject.h:229
void AcpiNsDeleteNamespaceByOwner(ACPI_OWNER_ID OwnerId)
Definition: nsalloc.c:497
#define AcpiUtCreateInternalObject(t)
Definition: acutils.h:654
UINT8 MethodIsNested
Definition: acstruct.h:101
#define AE_OK
Definition: acexcep.h:97
UINT16 Flags
Definition: aclocal.h:873
void AcpiDsTerminateControlMethod(ACPI_OPERAND_OBJECT *MethodDesc, ACPI_WALK_STATE *WalkState)
Definition: dsmethod.c:779
void AcpiDsClearImplicitReturn(ACPI_WALK_STATE *WalkState)
Definition: dsutils.c:73
union acpi_operand_object * Node
Definition: acobject.h:219
Definition: dlist.c:348
UINT8 * Aml
Definition: acstruct.h:91