OSDN Git Service

klibc基本機能実装. ACPICAの準備
[vaneos/DivergeMirror.git] / drivers / acpi / components / dispatcher / dsmethod.c
1 /******************************************************************************
2  *
3  * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
4  *
5  *****************************************************************************/
6
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2015, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115
116 #include "acpi.h"
117 #include "accommon.h"
118 #include "acdispat.h"
119 #include "acinterp.h"
120 #include "acnamesp.h"
121 #include "acdisasm.h"
122 #include "acparser.h"
123 #include "amlcode.h"
124
125
126 #define _COMPONENT          ACPI_DISPATCHER
127         ACPI_MODULE_NAME    ("dsmethod")
128
129 /* Local prototypes */
130
131 static ACPI_STATUS
132 AcpiDsDetectNamedOpcodes (
133     ACPI_WALK_STATE         *WalkState,
134     ACPI_PARSE_OBJECT       **OutOp);
135
136 static ACPI_STATUS
137 AcpiDsCreateMethodMutex (
138     ACPI_OPERAND_OBJECT     *MethodDesc);
139
140
141 /*******************************************************************************
142  *
143  * FUNCTION:    AcpiDsAutoSerializeMethod
144  *
145  * PARAMETERS:  Node                        - Namespace Node of the method
146  *              ObjDesc                     - Method object attached to node
147  *
148  * RETURN:      Status
149  *
150  * DESCRIPTION: Parse a control method AML to scan for control methods that
151  *              need serialization due to the creation of named objects.
152  *
153  * NOTE: It is a bit of overkill to mark all such methods serialized, since
154  * there is only a problem if the method actually blocks during execution.
155  * A blocking operation is, for example, a Sleep() operation, or any access
156  * to an operation region. However, it is probably not possible to easily
157  * detect whether a method will block or not, so we simply mark all suspicious
158  * methods as serialized.
159  *
160  * NOTE2: This code is essentially a generic routine for parsing a single
161  * control method.
162  *
163  ******************************************************************************/
164
165 ACPI_STATUS
166 AcpiDsAutoSerializeMethod (
167     ACPI_NAMESPACE_NODE     *Node,
168     ACPI_OPERAND_OBJECT     *ObjDesc)
169 {
170     ACPI_STATUS             Status;
171     ACPI_PARSE_OBJECT       *Op = NULL;
172     ACPI_WALK_STATE         *WalkState;
173
174
175     ACPI_FUNCTION_TRACE_PTR (DsAutoSerializeMethod, Node);
176
177
178     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
179         "Method auto-serialization parse [%4.4s] %p\n",
180         AcpiUtGetNodeName (Node), Node));
181
182     /* Create/Init a root op for the method parse tree */
183
184     Op = AcpiPsAllocOp (AML_METHOD_OP);
185     if (!Op)
186     {
187         return_ACPI_STATUS (AE_NO_MEMORY);
188     }
189
190     AcpiPsSetName (Op, Node->Name.Integer);
191     Op->Common.Node = Node;
192
193     /* Create and initialize a new walk state */
194
195     WalkState = AcpiDsCreateWalkState (Node->OwnerId, NULL, NULL, NULL);
196     if (!WalkState)
197     {
198         AcpiPsFreeOp (Op);
199         return_ACPI_STATUS (AE_NO_MEMORY);
200     }
201
202     Status = AcpiDsInitAmlWalk (WalkState, Op, Node, ObjDesc->Method.AmlStart,
203                 ObjDesc->Method.AmlLength, NULL, 0);
204     if (ACPI_FAILURE (Status))
205     {
206         AcpiDsDeleteWalkState (WalkState);
207         AcpiPsFreeOp (Op);
208         return_ACPI_STATUS (Status);
209     }
210
211     WalkState->DescendingCallback = AcpiDsDetectNamedOpcodes;
212
213     /* Parse the method, scan for creation of named objects */
214
215     Status = AcpiPsParseAml (WalkState);
216
217     AcpiPsDeleteParseTree (Op);
218     return_ACPI_STATUS (Status);
219 }
220
221
222 /*******************************************************************************
223  *
224  * FUNCTION:    AcpiDsDetectNamedOpcodes
225  *
226  * PARAMETERS:  WalkState       - Current state of the parse tree walk
227  *              OutOp           - Unused, required for parser interface
228  *
229  * RETURN:      Status
230  *
231  * DESCRIPTION: Descending callback used during the loading of ACPI tables.
232  *              Currently used to detect methods that must be marked serialized
233  *              in order to avoid problems with the creation of named objects.
234  *
235  ******************************************************************************/
236
237 static ACPI_STATUS
238 AcpiDsDetectNamedOpcodes (
239     ACPI_WALK_STATE         *WalkState,
240     ACPI_PARSE_OBJECT       **OutOp)
241 {
242
243     ACPI_FUNCTION_NAME (AcpiDsDetectNamedOpcodes);
244
245
246     /* We are only interested in opcodes that create a new name */
247
248     if (!(WalkState->OpInfo->Flags & (AML_NAMED | AML_CREATE | AML_FIELD)))
249     {
250         return (AE_OK);
251     }
252
253     /*
254      * At this point, we know we have a Named object opcode.
255      * Mark the method as serialized. Later code will create a mutex for
256      * this method to enforce serialization.
257      *
258      * Note, ACPI_METHOD_IGNORE_SYNC_LEVEL flag means that we will ignore the
259      * Sync Level mechanism for this method, even though it is now serialized.
260      * Otherwise, there can be conflicts with existing ASL code that actually
261      * uses sync levels.
262      */
263     WalkState->MethodDesc->Method.SyncLevel = 0;
264     WalkState->MethodDesc->Method.InfoFlags |=
265         (ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL);
266
267     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
268         "Method serialized [%4.4s] %p - [%s] (%4.4X)\n",
269         WalkState->MethodNode->Name.Ascii, WalkState->MethodNode,
270         WalkState->OpInfo->Name, WalkState->Opcode));
271
272     /* Abort the parse, no need to examine this method any further */
273
274     return (AE_CTRL_TERMINATE);
275 }
276
277
278 /*******************************************************************************
279  *
280  * FUNCTION:    AcpiDsMethodError
281  *
282  * PARAMETERS:  Status          - Execution status
283  *              WalkState       - Current state
284  *
285  * RETURN:      Status
286  *
287  * DESCRIPTION: Called on method error. Invoke the global exception handler if
288  *              present, dump the method data if the disassembler is configured
289  *
290  *              Note: Allows the exception handler to change the status code
291  *
292  ******************************************************************************/
293
294 ACPI_STATUS
295 AcpiDsMethodError (
296     ACPI_STATUS             Status,
297     ACPI_WALK_STATE         *WalkState)
298 {
299     ACPI_FUNCTION_ENTRY ();
300
301
302     /* Ignore AE_OK and control exception codes */
303
304     if (ACPI_SUCCESS (Status) ||
305         (Status & AE_CODE_CONTROL))
306     {
307         return (Status);
308     }
309
310     /* Invoke the global exception handler */
311
312     if (AcpiGbl_ExceptionHandler)
313     {
314         /* Exit the interpreter, allow handler to execute methods */
315
316         AcpiExExitInterpreter ();
317
318         /*
319          * Handler can map the exception code to anything it wants, including
320          * AE_OK, in which case the executing method will not be aborted.
321          */
322         Status = AcpiGbl_ExceptionHandler (Status,
323                     WalkState->MethodNode ?
324                         WalkState->MethodNode->Name.Integer : 0,
325                     WalkState->Opcode, WalkState->AmlOffset, NULL);
326         AcpiExEnterInterpreter ();
327     }
328
329     AcpiDsClearImplicitReturn (WalkState);
330
331 #ifdef ACPI_DISASSEMBLER
332     if (ACPI_FAILURE (Status))
333     {
334         /* Display method locals/args if disassembler is present */
335
336         AcpiDmDumpMethodInfo (Status, WalkState, WalkState->Op);
337     }
338 #endif
339
340     return (Status);
341 }
342
343
344 /*******************************************************************************
345  *
346  * FUNCTION:    AcpiDsCreateMethodMutex
347  *
348  * PARAMETERS:  ObjDesc             - The method object
349  *
350  * RETURN:      Status
351  *
352  * DESCRIPTION: Create a mutex object for a serialized control method
353  *
354  ******************************************************************************/
355
356 static ACPI_STATUS
357 AcpiDsCreateMethodMutex (
358     ACPI_OPERAND_OBJECT     *MethodDesc)
359 {
360     ACPI_OPERAND_OBJECT     *MutexDesc;
361     ACPI_STATUS             Status;
362
363
364     ACPI_FUNCTION_TRACE (DsCreateMethodMutex);
365
366
367     /* Create the new mutex object */
368
369     MutexDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX);
370     if (!MutexDesc)
371     {
372         return_ACPI_STATUS (AE_NO_MEMORY);
373     }
374
375     /* Create the actual OS Mutex */
376
377     Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex);
378     if (ACPI_FAILURE (Status))
379     {
380         AcpiUtDeleteObjectDesc (MutexDesc);
381         return_ACPI_STATUS (Status);
382     }
383
384     MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel;
385     MethodDesc->Method.Mutex = MutexDesc;
386     return_ACPI_STATUS (AE_OK);
387 }
388
389
390 /*******************************************************************************
391  *
392  * FUNCTION:    AcpiDsBeginMethodExecution
393  *
394  * PARAMETERS:  MethodNode          - Node of the method
395  *              ObjDesc             - The method object
396  *              WalkState           - current state, NULL if not yet executing
397  *                                    a method.
398  *
399  * RETURN:      Status
400  *
401  * DESCRIPTION: Prepare a method for execution. Parses the method if necessary,
402  *              increments the thread count, and waits at the method semaphore
403  *              for clearance to execute.
404  *
405  ******************************************************************************/
406
407 ACPI_STATUS
408 AcpiDsBeginMethodExecution (
409     ACPI_NAMESPACE_NODE     *MethodNode,
410     ACPI_OPERAND_OBJECT     *ObjDesc,
411     ACPI_WALK_STATE         *WalkState)
412 {
413     ACPI_STATUS             Status = AE_OK;
414
415
416     ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode);
417
418
419     if (!MethodNode)
420     {
421         return_ACPI_STATUS (AE_NULL_ENTRY);
422     }
423
424     /* Prevent wraparound of thread count */
425
426     if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX)
427     {
428         ACPI_ERROR ((AE_INFO,
429             "Method reached maximum reentrancy limit (255)"));
430         return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
431     }
432
433     /*
434      * If this method is serialized, we need to acquire the method mutex.
435      */
436     if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED)
437     {
438         /*
439          * Create a mutex for the method if it is defined to be Serialized
440          * and a mutex has not already been created. We defer the mutex creation
441          * until a method is actually executed, to minimize the object count
442          */
443         if (!ObjDesc->Method.Mutex)
444         {
445             Status = AcpiDsCreateMethodMutex (ObjDesc);
446             if (ACPI_FAILURE (Status))
447             {
448                 return_ACPI_STATUS (Status);
449             }
450         }
451
452         /*
453          * The CurrentSyncLevel (per-thread) must be less than or equal to
454          * the sync level of the method. This mechanism provides some
455          * deadlock prevention.
456          *
457          * If the method was auto-serialized, we just ignore the sync level
458          * mechanism, because auto-serialization of methods can interfere
459          * with ASL code that actually uses sync levels.
460          *
461          * Top-level method invocation has no walk state at this point
462          */
463         if (WalkState &&
464             (!(ObjDesc->Method.InfoFlags & ACPI_METHOD_IGNORE_SYNC_LEVEL)) &&
465             (WalkState->Thread->CurrentSyncLevel > ObjDesc->Method.Mutex->Mutex.SyncLevel))
466         {
467             ACPI_ERROR ((AE_INFO,
468                 "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)",
469                 AcpiUtGetNodeName (MethodNode),
470                 WalkState->Thread->CurrentSyncLevel));
471
472             return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
473         }
474
475         /*
476          * Obtain the method mutex if necessary. Do not acquire mutex for a
477          * recursive call.
478          */
479         if (!WalkState ||
480             !ObjDesc->Method.Mutex->Mutex.ThreadId ||
481             (WalkState->Thread->ThreadId != ObjDesc->Method.Mutex->Mutex.ThreadId))
482         {
483             /*
484              * Acquire the method mutex. This releases the interpreter if we
485              * block (and reacquires it before it returns)
486              */
487             Status = AcpiExSystemWaitMutex (ObjDesc->Method.Mutex->Mutex.OsMutex,
488                         ACPI_WAIT_FOREVER);
489             if (ACPI_FAILURE (Status))
490             {
491                 return_ACPI_STATUS (Status);
492             }
493
494             /* Update the mutex and walk info and save the original SyncLevel */
495
496             if (WalkState)
497             {
498                 ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
499                     WalkState->Thread->CurrentSyncLevel;
500
501                 ObjDesc->Method.Mutex->Mutex.ThreadId = WalkState->Thread->ThreadId;
502                 WalkState->Thread->CurrentSyncLevel = ObjDesc->Method.SyncLevel;
503             }
504             else
505             {
506                 ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
507                     ObjDesc->Method.Mutex->Mutex.SyncLevel;
508             }
509         }
510
511         /* Always increase acquisition depth */
512
513         ObjDesc->Method.Mutex->Mutex.AcquisitionDepth++;
514     }
515
516     /*
517      * Allocate an Owner ID for this method, only if this is the first thread
518      * to begin concurrent execution. We only need one OwnerId, even if the
519      * method is invoked recursively.
520      */
521     if (!ObjDesc->Method.OwnerId)
522     {
523         Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
524         if (ACPI_FAILURE (Status))
525         {
526             goto Cleanup;
527         }
528     }
529
530     /*
531      * Increment the method parse tree thread count since it has been
532      * reentered one more time (even if it is the same thread)
533      */
534     ObjDesc->Method.ThreadCount++;
535     AcpiMethodCount++;
536     return_ACPI_STATUS (Status);
537
538
539 Cleanup:
540     /* On error, must release the method mutex (if present) */
541
542     if (ObjDesc->Method.Mutex)
543     {
544         AcpiOsReleaseMutex (ObjDesc->Method.Mutex->Mutex.OsMutex);
545     }
546     return_ACPI_STATUS (Status);
547 }
548
549
550 /*******************************************************************************
551  *
552  * FUNCTION:    AcpiDsCallControlMethod
553  *
554  * PARAMETERS:  Thread              - Info for this thread
555  *              ThisWalkState       - Current walk state
556  *              Op                  - Current Op to be walked
557  *
558  * RETURN:      Status
559  *
560  * DESCRIPTION: Transfer execution to a called control method
561  *
562  ******************************************************************************/
563
564 ACPI_STATUS
565 AcpiDsCallControlMethod (
566     ACPI_THREAD_STATE       *Thread,
567     ACPI_WALK_STATE         *ThisWalkState,
568     ACPI_PARSE_OBJECT       *Op)
569 {
570     ACPI_STATUS             Status;
571     ACPI_NAMESPACE_NODE     *MethodNode;
572     ACPI_WALK_STATE         *NextWalkState = NULL;
573     ACPI_OPERAND_OBJECT     *ObjDesc;
574     ACPI_EVALUATE_INFO      *Info;
575     UINT32                  i;
576
577
578     ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState);
579
580     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Calling method %p, currentstate=%p\n",
581         ThisWalkState->PrevOp, ThisWalkState));
582
583     /*
584      * Get the namespace entry for the control method we are about to call
585      */
586     MethodNode = ThisWalkState->MethodCallNode;
587     if (!MethodNode)
588     {
589         return_ACPI_STATUS (AE_NULL_ENTRY);
590     }
591
592     ObjDesc = AcpiNsGetAttachedObject (MethodNode);
593     if (!ObjDesc)
594     {
595         return_ACPI_STATUS (AE_NULL_OBJECT);
596     }
597
598     /* Init for new method, possibly wait on method mutex */
599
600     Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc,
601                 ThisWalkState);
602     if (ACPI_FAILURE (Status))
603     {
604         return_ACPI_STATUS (Status);
605     }
606
607     /* Begin method parse/execution. Create a new walk state */
608
609     NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwnerId,
610                         NULL, ObjDesc, Thread);
611     if (!NextWalkState)
612     {
613         Status = AE_NO_MEMORY;
614         goto Cleanup;
615     }
616
617     /*
618      * The resolved arguments were put on the previous walk state's operand
619      * stack. Operands on the previous walk state stack always
620      * start at index 0. Also, null terminate the list of arguments
621      */
622     ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL;
623
624     /*
625      * Allocate and initialize the evaluation information block
626      * TBD: this is somewhat inefficient, should change interface to
627      * DsInitAmlWalk. For now, keeps this struct off the CPU stack
628      */
629     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
630     if (!Info)
631     {
632         Status = AE_NO_MEMORY;
633         goto Cleanup;
634     }
635
636     Info->Parameters = &ThisWalkState->Operands[0];
637
638     Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode,
639                 ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength,
640                 Info, ACPI_IMODE_EXECUTE);
641
642     ACPI_FREE (Info);
643     if (ACPI_FAILURE (Status))
644     {
645         goto Cleanup;
646     }
647
648     /*
649      * Delete the operands on the previous walkstate operand stack
650      * (they were copied to new objects)
651      */
652     for (i = 0; i < ObjDesc->Method.ParamCount; i++)
653     {
654         AcpiUtRemoveReference (ThisWalkState->Operands [i]);
655         ThisWalkState->Operands [i] = NULL;
656     }
657
658     /* Clear the operand stack */
659
660     ThisWalkState->NumOperands = 0;
661
662     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
663         "**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
664         MethodNode->Name.Ascii, NextWalkState));
665
666     /* Invoke an internal method if necessary */
667
668     if (ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY)
669     {
670         Status = ObjDesc->Method.Dispatch.Implementation (NextWalkState);
671         if (Status == AE_OK)
672         {
673             Status = AE_CTRL_TERMINATE;
674         }
675     }
676
677     return_ACPI_STATUS (Status);
678
679
680 Cleanup:
681
682     /* On error, we must terminate the method properly */
683
684     AcpiDsTerminateControlMethod (ObjDesc, NextWalkState);
685     if (NextWalkState)
686     {
687         AcpiDsDeleteWalkState (NextWalkState);
688     }
689
690     return_ACPI_STATUS (Status);
691 }
692
693
694 /*******************************************************************************
695  *
696  * FUNCTION:    AcpiDsRestartControlMethod
697  *
698  * PARAMETERS:  WalkState           - State for preempted method (caller)
699  *              ReturnDesc          - Return value from the called method
700  *
701  * RETURN:      Status
702  *
703  * DESCRIPTION: Restart a method that was preempted by another (nested) method
704  *              invocation. Handle the return value (if any) from the callee.
705  *
706  ******************************************************************************/
707
708 ACPI_STATUS
709 AcpiDsRestartControlMethod (
710     ACPI_WALK_STATE         *WalkState,
711     ACPI_OPERAND_OBJECT     *ReturnDesc)
712 {
713     ACPI_STATUS             Status;
714     int                     SameAsImplicitReturn;
715
716
717     ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState);
718
719
720     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
721         "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
722         AcpiUtGetNodeName (WalkState->MethodNode),
723         WalkState->MethodCallOp, ReturnDesc));
724
725     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
726         "    ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
727         WalkState->ReturnUsed,
728         WalkState->Results, WalkState));
729
730     /* Did the called method return a value? */
731
732     if (ReturnDesc)
733     {
734         /* Is the implicit return object the same as the return desc? */
735
736         SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc);
737
738         /* Are we actually going to use the return value? */
739
740         if (WalkState->ReturnUsed)
741         {
742             /* Save the return value from the previous method */
743
744             Status = AcpiDsResultPush (ReturnDesc, WalkState);
745             if (ACPI_FAILURE (Status))
746             {
747                 AcpiUtRemoveReference (ReturnDesc);
748                 return_ACPI_STATUS (Status);
749             }
750
751             /*
752              * Save as THIS method's return value in case it is returned
753              * immediately to yet another method
754              */
755             WalkState->ReturnDesc = ReturnDesc;
756         }
757
758         /*
759          * The following code is the optional support for the so-called
760          * "implicit return". Some AML code assumes that the last value of the
761          * method is "implicitly" returned to the caller, in the absence of an
762          * explicit return value.
763          *
764          * Just save the last result of the method as the return value.
765          *
766          * NOTE: this is optional because the ASL language does not actually
767          * support this behavior.
768          */
769         else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) ||
770                  SameAsImplicitReturn)
771         {
772             /*
773              * Delete the return value if it will not be used by the
774              * calling method or remove one reference if the explicit return
775              * is the same as the implicit return value.
776              */
777             AcpiUtRemoveReference (ReturnDesc);
778         }
779     }
780
781     return_ACPI_STATUS (AE_OK);
782 }
783
784
785 /*******************************************************************************
786  *
787  * FUNCTION:    AcpiDsTerminateControlMethod
788  *
789  * PARAMETERS:  MethodDesc          - Method object
790  *              WalkState           - State associated with the method
791  *
792  * RETURN:      None
793  *
794  * DESCRIPTION: Terminate a control method. Delete everything that the method
795  *              created, delete all locals and arguments, and delete the parse
796  *              tree if requested.
797  *
798  * MUTEX:       Interpreter is locked
799  *
800  ******************************************************************************/
801
802 void
803 AcpiDsTerminateControlMethod (
804     ACPI_OPERAND_OBJECT     *MethodDesc,
805     ACPI_WALK_STATE         *WalkState)
806 {
807
808     ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState);
809
810
811     /* MethodDesc is required, WalkState is optional */
812
813     if (!MethodDesc)
814     {
815         return_VOID;
816     }
817
818     if (WalkState)
819     {
820         /* Delete all arguments and locals */
821
822         AcpiDsMethodDataDeleteAll (WalkState);
823
824         /*
825          * If method is serialized, release the mutex and restore the
826          * current sync level for this thread
827          */
828         if (MethodDesc->Method.Mutex)
829         {
830             /* Acquisition Depth handles recursive calls */
831
832             MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--;
833             if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth)
834             {
835                 WalkState->Thread->CurrentSyncLevel =
836                     MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel;
837
838                 AcpiOsReleaseMutex (MethodDesc->Method.Mutex->Mutex.OsMutex);
839                 MethodDesc->Method.Mutex->Mutex.ThreadId = 0;
840             }
841         }
842
843         /*
844          * Delete any namespace objects created anywhere within the
845          * namespace by the execution of this method. Unless:
846          * 1) This method is a module-level executable code method, in which
847          *    case we want make the objects permanent.
848          * 2) There are other threads executing the method, in which case we
849          *    will wait until the last thread has completed.
850          */
851         if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) &&
852              (MethodDesc->Method.ThreadCount == 1))
853         {
854             /* Delete any direct children of (created by) this method */
855
856             AcpiNsDeleteNamespaceSubtree (WalkState->MethodNode);
857
858             /*
859              * Delete any objects that were created by this method
860              * elsewhere in the namespace (if any were created).
861              * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the
862              * deletion such that we don't have to perform an entire
863              * namespace walk for every control method execution.
864              */
865             if (MethodDesc->Method.InfoFlags & ACPI_METHOD_MODIFIED_NAMESPACE)
866             {
867                 AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId);
868                 MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_MODIFIED_NAMESPACE;
869             }
870         }
871     }
872
873     /* Decrement the thread count on the method */
874
875     if (MethodDesc->Method.ThreadCount)
876     {
877         MethodDesc->Method.ThreadCount--;
878     }
879     else
880     {
881         ACPI_ERROR ((AE_INFO,
882             "Invalid zero thread count in method"));
883     }
884
885     /* Are there any other threads currently executing this method? */
886
887     if (MethodDesc->Method.ThreadCount)
888     {
889         /*
890          * Additional threads. Do not release the OwnerId in this case,
891          * we immediately reuse it for the next thread executing this method
892          */
893         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
894             "*** Completed execution of one thread, %u threads remaining\n",
895             MethodDesc->Method.ThreadCount));
896     }
897     else
898     {
899         /* This is the only executing thread for this method */
900
901         /*
902          * Support to dynamically change a method from NotSerialized to
903          * Serialized if it appears that the method is incorrectly written and
904          * does not support multiple thread execution. The best example of this
905          * is if such a method creates namespace objects and blocks. A second
906          * thread will fail with an AE_ALREADY_EXISTS exception.
907          *
908          * This code is here because we must wait until the last thread exits
909          * before marking the method as serialized.
910          */
911         if (MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED_PENDING)
912         {
913             if (WalkState)
914             {
915                 ACPI_INFO ((AE_INFO,
916                     "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
917                     WalkState->MethodNode->Name.Ascii));
918             }
919
920             /*
921              * Method tried to create an object twice and was marked as
922              * "pending serialized". The probable cause is that the method
923              * cannot handle reentrancy.
924              *
925              * The method was created as NotSerialized, but it tried to create
926              * a named object and then blocked, causing the second thread
927              * entrance to begin and then fail. Workaround this problem by
928              * marking the method permanently as Serialized when the last
929              * thread exits here.
930              */
931             MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_SERIALIZED_PENDING;
932             MethodDesc->Method.InfoFlags |=
933                 (ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL);
934             MethodDesc->Method.SyncLevel = 0;
935         }
936
937         /* No more threads, we can free the OwnerId */
938
939         if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL))
940         {
941             AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId);
942         }
943     }
944
945     return_VOID;
946 }