17851SDana.Myers@Sun.COM /****************************************************************************** 27851SDana.Myers@Sun.COM * 37851SDana.Myers@Sun.COM * Module Name: dsmethod - Parser/Interpreter interface - control method parsing 47851SDana.Myers@Sun.COM * 57851SDana.Myers@Sun.COM *****************************************************************************/ 67851SDana.Myers@Sun.COM 77851SDana.Myers@Sun.COM /****************************************************************************** 87851SDana.Myers@Sun.COM * 97851SDana.Myers@Sun.COM * 1. Copyright Notice 107851SDana.Myers@Sun.COM * 11*9980SDana.Myers@Sun.COM * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp. 127851SDana.Myers@Sun.COM * All rights reserved. 137851SDana.Myers@Sun.COM * 147851SDana.Myers@Sun.COM * 2. License 157851SDana.Myers@Sun.COM * 167851SDana.Myers@Sun.COM * 2.1. This is your license from Intel Corp. under its intellectual property 177851SDana.Myers@Sun.COM * rights. You may have additional license terms from the party that provided 187851SDana.Myers@Sun.COM * you this software, covering your right to use that party's intellectual 197851SDana.Myers@Sun.COM * property rights. 207851SDana.Myers@Sun.COM * 217851SDana.Myers@Sun.COM * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 227851SDana.Myers@Sun.COM * copy of the source code appearing in this file ("Covered Code") an 237851SDana.Myers@Sun.COM * irrevocable, perpetual, worldwide license under Intel's copyrights in the 247851SDana.Myers@Sun.COM * base code distributed originally by Intel ("Original Intel Code") to copy, 257851SDana.Myers@Sun.COM * make derivatives, distribute, use and display any portion of the Covered 267851SDana.Myers@Sun.COM * Code in any form, with the right to sublicense such rights; and 277851SDana.Myers@Sun.COM * 287851SDana.Myers@Sun.COM * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 297851SDana.Myers@Sun.COM * license (with the right to sublicense), under only those claims of Intel 307851SDana.Myers@Sun.COM * patents that are infringed by the Original Intel Code, to make, use, sell, 317851SDana.Myers@Sun.COM * offer to sell, and import the Covered Code and derivative works thereof 327851SDana.Myers@Sun.COM * solely to the minimum extent necessary to exercise the above copyright 337851SDana.Myers@Sun.COM * license, and in no event shall the patent license extend to any additions 347851SDana.Myers@Sun.COM * to or modifications of the Original Intel Code. No other license or right 357851SDana.Myers@Sun.COM * is granted directly or by implication, estoppel or otherwise; 367851SDana.Myers@Sun.COM * 377851SDana.Myers@Sun.COM * The above copyright and patent license is granted only if the following 387851SDana.Myers@Sun.COM * conditions are met: 397851SDana.Myers@Sun.COM * 407851SDana.Myers@Sun.COM * 3. Conditions 417851SDana.Myers@Sun.COM * 427851SDana.Myers@Sun.COM * 3.1. Redistribution of Source with Rights to Further Distribute Source. 437851SDana.Myers@Sun.COM * Redistribution of source code of any substantial portion of the Covered 447851SDana.Myers@Sun.COM * Code or modification with rights to further distribute source must include 457851SDana.Myers@Sun.COM * the above Copyright Notice, the above License, this list of Conditions, 467851SDana.Myers@Sun.COM * and the following Disclaimer and Export Compliance provision. In addition, 477851SDana.Myers@Sun.COM * Licensee must cause all Covered Code to which Licensee contributes to 487851SDana.Myers@Sun.COM * contain a file documenting the changes Licensee made to create that Covered 497851SDana.Myers@Sun.COM * Code and the date of any change. Licensee must include in that file the 507851SDana.Myers@Sun.COM * documentation of any changes made by any predecessor Licensee. Licensee 517851SDana.Myers@Sun.COM * must include a prominent statement that the modification is derived, 527851SDana.Myers@Sun.COM * directly or indirectly, from Original Intel Code. 537851SDana.Myers@Sun.COM * 547851SDana.Myers@Sun.COM * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 557851SDana.Myers@Sun.COM * Redistribution of source code of any substantial portion of the Covered 567851SDana.Myers@Sun.COM * Code or modification without rights to further distribute source must 577851SDana.Myers@Sun.COM * include the following Disclaimer and Export Compliance provision in the 587851SDana.Myers@Sun.COM * documentation and/or other materials provided with distribution. In 597851SDana.Myers@Sun.COM * addition, Licensee may not authorize further sublicense of source of any 607851SDana.Myers@Sun.COM * portion of the Covered Code, and must include terms to the effect that the 617851SDana.Myers@Sun.COM * license from Licensee to its licensee is limited to the intellectual 627851SDana.Myers@Sun.COM * property embodied in the software Licensee provides to its licensee, and 637851SDana.Myers@Sun.COM * not to intellectual property embodied in modifications its licensee may 647851SDana.Myers@Sun.COM * make. 657851SDana.Myers@Sun.COM * 667851SDana.Myers@Sun.COM * 3.3. Redistribution of Executable. Redistribution in executable form of any 677851SDana.Myers@Sun.COM * substantial portion of the Covered Code or modification must reproduce the 687851SDana.Myers@Sun.COM * above Copyright Notice, and the following Disclaimer and Export Compliance 697851SDana.Myers@Sun.COM * provision in the documentation and/or other materials provided with the 707851SDana.Myers@Sun.COM * distribution. 717851SDana.Myers@Sun.COM * 727851SDana.Myers@Sun.COM * 3.4. Intel retains all right, title, and interest in and to the Original 737851SDana.Myers@Sun.COM * Intel Code. 747851SDana.Myers@Sun.COM * 757851SDana.Myers@Sun.COM * 3.5. Neither the name Intel nor any other trademark owned or controlled by 767851SDana.Myers@Sun.COM * Intel shall be used in advertising or otherwise to promote the sale, use or 777851SDana.Myers@Sun.COM * other dealings in products derived from or relating to the Covered Code 787851SDana.Myers@Sun.COM * without prior written authorization from Intel. 797851SDana.Myers@Sun.COM * 807851SDana.Myers@Sun.COM * 4. Disclaimer and Export Compliance 817851SDana.Myers@Sun.COM * 827851SDana.Myers@Sun.COM * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 837851SDana.Myers@Sun.COM * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 847851SDana.Myers@Sun.COM * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 857851SDana.Myers@Sun.COM * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 867851SDana.Myers@Sun.COM * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 877851SDana.Myers@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 887851SDana.Myers@Sun.COM * PARTICULAR PURPOSE. 897851SDana.Myers@Sun.COM * 907851SDana.Myers@Sun.COM * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 917851SDana.Myers@Sun.COM * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 927851SDana.Myers@Sun.COM * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 937851SDana.Myers@Sun.COM * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 947851SDana.Myers@Sun.COM * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 957851SDana.Myers@Sun.COM * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 967851SDana.Myers@Sun.COM * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 977851SDana.Myers@Sun.COM * LIMITED REMEDY. 987851SDana.Myers@Sun.COM * 997851SDana.Myers@Sun.COM * 4.3. Licensee shall not export, either directly or indirectly, any of this 1007851SDana.Myers@Sun.COM * software or system incorporating such software without first obtaining any 1017851SDana.Myers@Sun.COM * required license or other approval from the U. S. Department of Commerce or 1027851SDana.Myers@Sun.COM * any other agency or department of the United States Government. In the 1037851SDana.Myers@Sun.COM * event Licensee exports any such software from the United States or 1047851SDana.Myers@Sun.COM * re-exports any such software from a foreign destination, Licensee shall 1057851SDana.Myers@Sun.COM * ensure that the distribution and export/re-export of the software is in 1067851SDana.Myers@Sun.COM * compliance with all laws, regulations, orders, or other restrictions of the 1077851SDana.Myers@Sun.COM * U.S. Export Administration Regulations. Licensee agrees that neither it nor 1087851SDana.Myers@Sun.COM * any of its subsidiaries will export/re-export any technical data, process, 1097851SDana.Myers@Sun.COM * software, or service, directly or indirectly, to any country for which the 1107851SDana.Myers@Sun.COM * United States government or any agency thereof requires an export license, 1117851SDana.Myers@Sun.COM * other governmental approval, or letter of assurance, without first obtaining 1127851SDana.Myers@Sun.COM * such license, approval or letter. 1137851SDana.Myers@Sun.COM * 1147851SDana.Myers@Sun.COM *****************************************************************************/ 1157851SDana.Myers@Sun.COM 1167851SDana.Myers@Sun.COM #define __DSMETHOD_C__ 1177851SDana.Myers@Sun.COM 1187851SDana.Myers@Sun.COM #include "acpi.h" 119*9980SDana.Myers@Sun.COM #include "accommon.h" 1207851SDana.Myers@Sun.COM #include "amlcode.h" 1217851SDana.Myers@Sun.COM #include "acdispat.h" 1227851SDana.Myers@Sun.COM #include "acinterp.h" 1237851SDana.Myers@Sun.COM #include "acnamesp.h" 1247851SDana.Myers@Sun.COM #include "acdisasm.h" 1257851SDana.Myers@Sun.COM 1267851SDana.Myers@Sun.COM 1277851SDana.Myers@Sun.COM #define _COMPONENT ACPI_DISPATCHER 1287851SDana.Myers@Sun.COM ACPI_MODULE_NAME ("dsmethod") 1297851SDana.Myers@Sun.COM 1307851SDana.Myers@Sun.COM /* Local prototypes */ 1317851SDana.Myers@Sun.COM 1327851SDana.Myers@Sun.COM static ACPI_STATUS 1337851SDana.Myers@Sun.COM AcpiDsCreateMethodMutex ( 1347851SDana.Myers@Sun.COM ACPI_OPERAND_OBJECT *MethodDesc); 1357851SDana.Myers@Sun.COM 1367851SDana.Myers@Sun.COM 1377851SDana.Myers@Sun.COM /******************************************************************************* 1387851SDana.Myers@Sun.COM * 1397851SDana.Myers@Sun.COM * FUNCTION: AcpiDsMethodError 1407851SDana.Myers@Sun.COM * 1417851SDana.Myers@Sun.COM * PARAMETERS: Status - Execution status 1427851SDana.Myers@Sun.COM * WalkState - Current state 1437851SDana.Myers@Sun.COM * 1447851SDana.Myers@Sun.COM * RETURN: Status 1457851SDana.Myers@Sun.COM * 1467851SDana.Myers@Sun.COM * DESCRIPTION: Called on method error. Invoke the global exception handler if 1477851SDana.Myers@Sun.COM * present, dump the method data if the disassembler is configured 1487851SDana.Myers@Sun.COM * 1497851SDana.Myers@Sun.COM * Note: Allows the exception handler to change the status code 1507851SDana.Myers@Sun.COM * 1517851SDana.Myers@Sun.COM ******************************************************************************/ 1527851SDana.Myers@Sun.COM 1537851SDana.Myers@Sun.COM ACPI_STATUS 1547851SDana.Myers@Sun.COM AcpiDsMethodError ( 1557851SDana.Myers@Sun.COM ACPI_STATUS Status, 1567851SDana.Myers@Sun.COM ACPI_WALK_STATE *WalkState) 1577851SDana.Myers@Sun.COM { 1587851SDana.Myers@Sun.COM ACPI_FUNCTION_ENTRY (); 1597851SDana.Myers@Sun.COM 1607851SDana.Myers@Sun.COM 1617851SDana.Myers@Sun.COM /* Ignore AE_OK and control exception codes */ 1627851SDana.Myers@Sun.COM 1637851SDana.Myers@Sun.COM if (ACPI_SUCCESS (Status) || 1647851SDana.Myers@Sun.COM (Status & AE_CODE_CONTROL)) 1657851SDana.Myers@Sun.COM { 1667851SDana.Myers@Sun.COM return (Status); 1677851SDana.Myers@Sun.COM } 1687851SDana.Myers@Sun.COM 1697851SDana.Myers@Sun.COM /* Invoke the global exception handler */ 1707851SDana.Myers@Sun.COM 1717851SDana.Myers@Sun.COM if (AcpiGbl_ExceptionHandler) 1727851SDana.Myers@Sun.COM { 1737851SDana.Myers@Sun.COM /* Exit the interpreter, allow handler to execute methods */ 1747851SDana.Myers@Sun.COM 1757851SDana.Myers@Sun.COM AcpiExExitInterpreter (); 1767851SDana.Myers@Sun.COM 1777851SDana.Myers@Sun.COM /* 1787851SDana.Myers@Sun.COM * Handler can map the exception code to anything it wants, including 1797851SDana.Myers@Sun.COM * AE_OK, in which case the executing method will not be aborted. 1807851SDana.Myers@Sun.COM */ 1817851SDana.Myers@Sun.COM Status = AcpiGbl_ExceptionHandler (Status, 1827851SDana.Myers@Sun.COM WalkState->MethodNode ? 1837851SDana.Myers@Sun.COM WalkState->MethodNode->Name.Integer : 0, 1847851SDana.Myers@Sun.COM WalkState->Opcode, WalkState->AmlOffset, NULL); 1857851SDana.Myers@Sun.COM AcpiExEnterInterpreter (); 1867851SDana.Myers@Sun.COM } 1877851SDana.Myers@Sun.COM 1887851SDana.Myers@Sun.COM AcpiDsClearImplicitReturn (WalkState); 1897851SDana.Myers@Sun.COM 1907851SDana.Myers@Sun.COM #ifdef ACPI_DISASSEMBLER 1917851SDana.Myers@Sun.COM if (ACPI_FAILURE (Status)) 1927851SDana.Myers@Sun.COM { 1937851SDana.Myers@Sun.COM /* Display method locals/args if disassembler is present */ 1947851SDana.Myers@Sun.COM 1957851SDana.Myers@Sun.COM AcpiDmDumpMethodInfo (Status, WalkState, WalkState->Op); 1967851SDana.Myers@Sun.COM } 1977851SDana.Myers@Sun.COM #endif 1987851SDana.Myers@Sun.COM 1997851SDana.Myers@Sun.COM return (Status); 2007851SDana.Myers@Sun.COM } 2017851SDana.Myers@Sun.COM 2027851SDana.Myers@Sun.COM 2037851SDana.Myers@Sun.COM /******************************************************************************* 2047851SDana.Myers@Sun.COM * 2057851SDana.Myers@Sun.COM * FUNCTION: AcpiDsCreateMethodMutex 2067851SDana.Myers@Sun.COM * 2077851SDana.Myers@Sun.COM * PARAMETERS: ObjDesc - The method object 2087851SDana.Myers@Sun.COM * 2097851SDana.Myers@Sun.COM * RETURN: Status 2107851SDana.Myers@Sun.COM * 2117851SDana.Myers@Sun.COM * DESCRIPTION: Create a mutex object for a serialized control method 2127851SDana.Myers@Sun.COM * 2137851SDana.Myers@Sun.COM ******************************************************************************/ 2147851SDana.Myers@Sun.COM 2157851SDana.Myers@Sun.COM static ACPI_STATUS 2167851SDana.Myers@Sun.COM AcpiDsCreateMethodMutex ( 2177851SDana.Myers@Sun.COM ACPI_OPERAND_OBJECT *MethodDesc) 2187851SDana.Myers@Sun.COM { 2197851SDana.Myers@Sun.COM ACPI_OPERAND_OBJECT *MutexDesc; 2207851SDana.Myers@Sun.COM ACPI_STATUS Status; 2217851SDana.Myers@Sun.COM 2227851SDana.Myers@Sun.COM 2237851SDana.Myers@Sun.COM ACPI_FUNCTION_TRACE (DsCreateMethodMutex); 2247851SDana.Myers@Sun.COM 2257851SDana.Myers@Sun.COM 2267851SDana.Myers@Sun.COM /* Create the new mutex object */ 2277851SDana.Myers@Sun.COM 2287851SDana.Myers@Sun.COM MutexDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX); 2297851SDana.Myers@Sun.COM if (!MutexDesc) 2307851SDana.Myers@Sun.COM { 2317851SDana.Myers@Sun.COM return_ACPI_STATUS (AE_NO_MEMORY); 2327851SDana.Myers@Sun.COM } 2337851SDana.Myers@Sun.COM 2347851SDana.Myers@Sun.COM /* Create the actual OS Mutex */ 2357851SDana.Myers@Sun.COM 2367851SDana.Myers@Sun.COM Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex); 2377851SDana.Myers@Sun.COM if (ACPI_FAILURE (Status)) 2387851SDana.Myers@Sun.COM { 2397851SDana.Myers@Sun.COM return_ACPI_STATUS (Status); 2407851SDana.Myers@Sun.COM } 2417851SDana.Myers@Sun.COM 2427851SDana.Myers@Sun.COM MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel; 2437851SDana.Myers@Sun.COM MethodDesc->Method.Mutex = MutexDesc; 2447851SDana.Myers@Sun.COM return_ACPI_STATUS (AE_OK); 2457851SDana.Myers@Sun.COM } 2467851SDana.Myers@Sun.COM 2477851SDana.Myers@Sun.COM 2487851SDana.Myers@Sun.COM /******************************************************************************* 2497851SDana.Myers@Sun.COM * 2507851SDana.Myers@Sun.COM * FUNCTION: AcpiDsBeginMethodExecution 2517851SDana.Myers@Sun.COM * 2527851SDana.Myers@Sun.COM * PARAMETERS: MethodNode - Node of the method 2537851SDana.Myers@Sun.COM * ObjDesc - The method object 2547851SDana.Myers@Sun.COM * WalkState - current state, NULL if not yet executing 2557851SDana.Myers@Sun.COM * a method. 2567851SDana.Myers@Sun.COM * 2577851SDana.Myers@Sun.COM * RETURN: Status 2587851SDana.Myers@Sun.COM * 2597851SDana.Myers@Sun.COM * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, 2607851SDana.Myers@Sun.COM * increments the thread count, and waits at the method semaphore 2617851SDana.Myers@Sun.COM * for clearance to execute. 2627851SDana.Myers@Sun.COM * 2637851SDana.Myers@Sun.COM ******************************************************************************/ 2647851SDana.Myers@Sun.COM 2657851SDana.Myers@Sun.COM ACPI_STATUS 2667851SDana.Myers@Sun.COM AcpiDsBeginMethodExecution ( 2677851SDana.Myers@Sun.COM ACPI_NAMESPACE_NODE *MethodNode, 2687851SDana.Myers@Sun.COM ACPI_OPERAND_OBJECT *ObjDesc, 2697851SDana.Myers@Sun.COM ACPI_WALK_STATE *WalkState) 2707851SDana.Myers@Sun.COM { 2717851SDana.Myers@Sun.COM ACPI_STATUS Status = AE_OK; 2727851SDana.Myers@Sun.COM 2737851SDana.Myers@Sun.COM 2747851SDana.Myers@Sun.COM ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode); 2757851SDana.Myers@Sun.COM 2767851SDana.Myers@Sun.COM 2777851SDana.Myers@Sun.COM if (!MethodNode) 2787851SDana.Myers@Sun.COM { 2797851SDana.Myers@Sun.COM return_ACPI_STATUS (AE_NULL_ENTRY); 2807851SDana.Myers@Sun.COM } 2817851SDana.Myers@Sun.COM 2827851SDana.Myers@Sun.COM /* Prevent wraparound of thread count */ 2837851SDana.Myers@Sun.COM 2847851SDana.Myers@Sun.COM if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX) 2857851SDana.Myers@Sun.COM { 2867851SDana.Myers@Sun.COM ACPI_ERROR ((AE_INFO, 2877851SDana.Myers@Sun.COM "Method reached maximum reentrancy limit (255)")); 2887851SDana.Myers@Sun.COM return_ACPI_STATUS (AE_AML_METHOD_LIMIT); 2897851SDana.Myers@Sun.COM } 2907851SDana.Myers@Sun.COM 2917851SDana.Myers@Sun.COM /* 2927851SDana.Myers@Sun.COM * If this method is serialized, we need to acquire the method mutex. 2937851SDana.Myers@Sun.COM */ 2947851SDana.Myers@Sun.COM if (ObjDesc->Method.MethodFlags & AML_METHOD_SERIALIZED) 2957851SDana.Myers@Sun.COM { 2967851SDana.Myers@Sun.COM /* 2977851SDana.Myers@Sun.COM * Create a mutex for the method if it is defined to be Serialized 2987851SDana.Myers@Sun.COM * and a mutex has not already been created. We defer the mutex creation 2997851SDana.Myers@Sun.COM * until a method is actually executed, to minimize the object count 3007851SDana.Myers@Sun.COM */ 3017851SDana.Myers@Sun.COM if (!ObjDesc->Method.Mutex) 3027851SDana.Myers@Sun.COM { 3037851SDana.Myers@Sun.COM Status = AcpiDsCreateMethodMutex (ObjDesc); 3047851SDana.Myers@Sun.COM if (ACPI_FAILURE (Status)) 3057851SDana.Myers@Sun.COM { 3067851SDana.Myers@Sun.COM return_ACPI_STATUS (Status); 3077851SDana.Myers@Sun.COM } 3087851SDana.Myers@Sun.COM } 3097851SDana.Myers@Sun.COM 3107851SDana.Myers@Sun.COM /* 3117851SDana.Myers@Sun.COM * The CurrentSyncLevel (per-thread) must be less than or equal to 3127851SDana.Myers@Sun.COM * the sync level of the method. This mechanism provides some 3137851SDana.Myers@Sun.COM * deadlock prevention 3147851SDana.Myers@Sun.COM * 3157851SDana.Myers@Sun.COM * Top-level method invocation has no walk state at this point 3167851SDana.Myers@Sun.COM */ 3177851SDana.Myers@Sun.COM if (WalkState && 3187851SDana.Myers@Sun.COM (WalkState->Thread->CurrentSyncLevel > ObjDesc->Method.Mutex->Mutex.SyncLevel)) 3197851SDana.Myers@Sun.COM { 3207851SDana.Myers@Sun.COM ACPI_ERROR ((AE_INFO, 3217851SDana.Myers@Sun.COM "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%d)", 3227851SDana.Myers@Sun.COM AcpiUtGetNodeName (MethodNode), 3237851SDana.Myers@Sun.COM WalkState->Thread->CurrentSyncLevel)); 3247851SDana.Myers@Sun.COM 3257851SDana.Myers@Sun.COM return_ACPI_STATUS (AE_AML_MUTEX_ORDER); 3267851SDana.Myers@Sun.COM } 3277851SDana.Myers@Sun.COM 3287851SDana.Myers@Sun.COM /* 3297851SDana.Myers@Sun.COM * Obtain the method mutex if necessary. Do not acquire mutex for a 3307851SDana.Myers@Sun.COM * recursive call. 3317851SDana.Myers@Sun.COM */ 3327851SDana.Myers@Sun.COM if (!WalkState || 3337851SDana.Myers@Sun.COM !ObjDesc->Method.Mutex->Mutex.ThreadId || 3347851SDana.Myers@Sun.COM (WalkState->Thread->ThreadId != ObjDesc->Method.Mutex->Mutex.ThreadId)) 3357851SDana.Myers@Sun.COM { 3367851SDana.Myers@Sun.COM /* 3377851SDana.Myers@Sun.COM * Acquire the method mutex. This releases the interpreter if we 3387851SDana.Myers@Sun.COM * block (and reacquires it before it returns) 3397851SDana.Myers@Sun.COM */ 3407851SDana.Myers@Sun.COM Status = AcpiExSystemWaitMutex (ObjDesc->Method.Mutex->Mutex.OsMutex, 3417851SDana.Myers@Sun.COM ACPI_WAIT_FOREVER); 3427851SDana.Myers@Sun.COM if (ACPI_FAILURE (Status)) 3437851SDana.Myers@Sun.COM { 3447851SDana.Myers@Sun.COM return_ACPI_STATUS (Status); 3457851SDana.Myers@Sun.COM } 3467851SDana.Myers@Sun.COM 3477851SDana.Myers@Sun.COM /* Update the mutex and walk info and save the original SyncLevel */ 3487851SDana.Myers@Sun.COM 3497851SDana.Myers@Sun.COM if (WalkState) 3507851SDana.Myers@Sun.COM { 3517851SDana.Myers@Sun.COM ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel = 3527851SDana.Myers@Sun.COM WalkState->Thread->CurrentSyncLevel; 3537851SDana.Myers@Sun.COM 3547851SDana.Myers@Sun.COM ObjDesc->Method.Mutex->Mutex.ThreadId = WalkState->Thread->ThreadId; 3557851SDana.Myers@Sun.COM WalkState->Thread->CurrentSyncLevel = ObjDesc->Method.SyncLevel; 3567851SDana.Myers@Sun.COM } 3577851SDana.Myers@Sun.COM else 3587851SDana.Myers@Sun.COM { 3597851SDana.Myers@Sun.COM ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel = 3607851SDana.Myers@Sun.COM ObjDesc->Method.Mutex->Mutex.SyncLevel; 3617851SDana.Myers@Sun.COM } 3627851SDana.Myers@Sun.COM } 3637851SDana.Myers@Sun.COM 3647851SDana.Myers@Sun.COM /* Always increase acquisition depth */ 3657851SDana.Myers@Sun.COM 3667851SDana.Myers@Sun.COM ObjDesc->Method.Mutex->Mutex.AcquisitionDepth++; 3677851SDana.Myers@Sun.COM } 3687851SDana.Myers@Sun.COM 3697851SDana.Myers@Sun.COM /* 3707851SDana.Myers@Sun.COM * Allocate an Owner ID for this method, only if this is the first thread 3717851SDana.Myers@Sun.COM * to begin concurrent execution. We only need one OwnerId, even if the 3727851SDana.Myers@Sun.COM * method is invoked recursively. 3737851SDana.Myers@Sun.COM */ 3747851SDana.Myers@Sun.COM if (!ObjDesc->Method.OwnerId) 3757851SDana.Myers@Sun.COM { 3767851SDana.Myers@Sun.COM Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId); 3777851SDana.Myers@Sun.COM if (ACPI_FAILURE (Status)) 3787851SDana.Myers@Sun.COM { 3797851SDana.Myers@Sun.COM goto Cleanup; 3807851SDana.Myers@Sun.COM } 3817851SDana.Myers@Sun.COM } 3827851SDana.Myers@Sun.COM 3837851SDana.Myers@Sun.COM /* 3847851SDana.Myers@Sun.COM * Increment the method parse tree thread count since it has been 3857851SDana.Myers@Sun.COM * reentered one more time (even if it is the same thread) 3867851SDana.Myers@Sun.COM */ 3877851SDana.Myers@Sun.COM ObjDesc->Method.ThreadCount++; 3887851SDana.Myers@Sun.COM AcpiMethodCount++; 3897851SDana.Myers@Sun.COM return_ACPI_STATUS (Status); 3907851SDana.Myers@Sun.COM 3917851SDana.Myers@Sun.COM 3927851SDana.Myers@Sun.COM Cleanup: 3937851SDana.Myers@Sun.COM /* On error, must release the method mutex (if present) */ 3947851SDana.Myers@Sun.COM 3957851SDana.Myers@Sun.COM if (ObjDesc->Method.Mutex) 3967851SDana.Myers@Sun.COM { 3977851SDana.Myers@Sun.COM AcpiOsReleaseMutex (ObjDesc->Method.Mutex->Mutex.OsMutex); 3987851SDana.Myers@Sun.COM } 3997851SDana.Myers@Sun.COM return_ACPI_STATUS (Status); 4007851SDana.Myers@Sun.COM } 4017851SDana.Myers@Sun.COM 4027851SDana.Myers@Sun.COM 4037851SDana.Myers@Sun.COM /******************************************************************************* 4047851SDana.Myers@Sun.COM * 4057851SDana.Myers@Sun.COM * FUNCTION: AcpiDsCallControlMethod 4067851SDana.Myers@Sun.COM * 4077851SDana.Myers@Sun.COM * PARAMETERS: Thread - Info for this thread 4087851SDana.Myers@Sun.COM * ThisWalkState - Current walk state 4097851SDana.Myers@Sun.COM * Op - Current Op to be walked 4107851SDana.Myers@Sun.COM * 4117851SDana.Myers@Sun.COM * RETURN: Status 4127851SDana.Myers@Sun.COM * 4137851SDana.Myers@Sun.COM * DESCRIPTION: Transfer execution to a called control method 4147851SDana.Myers@Sun.COM * 4157851SDana.Myers@Sun.COM ******************************************************************************/ 4167851SDana.Myers@Sun.COM 4177851SDana.Myers@Sun.COM ACPI_STATUS 4187851SDana.Myers@Sun.COM AcpiDsCallControlMethod ( 4197851SDana.Myers@Sun.COM ACPI_THREAD_STATE *Thread, 4207851SDana.Myers@Sun.COM ACPI_WALK_STATE *ThisWalkState, 4217851SDana.Myers@Sun.COM ACPI_PARSE_OBJECT *Op) 4227851SDana.Myers@Sun.COM { 4237851SDana.Myers@Sun.COM ACPI_STATUS Status; 4247851SDana.Myers@Sun.COM ACPI_NAMESPACE_NODE *MethodNode; 4257851SDana.Myers@Sun.COM ACPI_WALK_STATE *NextWalkState = NULL; 4267851SDana.Myers@Sun.COM ACPI_OPERAND_OBJECT *ObjDesc; 4277851SDana.Myers@Sun.COM ACPI_EVALUATE_INFO *Info; 4287851SDana.Myers@Sun.COM UINT32 i; 4297851SDana.Myers@Sun.COM 4307851SDana.Myers@Sun.COM 4317851SDana.Myers@Sun.COM ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState); 4327851SDana.Myers@Sun.COM 4337851SDana.Myers@Sun.COM ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Calling method %p, currentstate=%p\n", 4347851SDana.Myers@Sun.COM ThisWalkState->PrevOp, ThisWalkState)); 4357851SDana.Myers@Sun.COM 4367851SDana.Myers@Sun.COM /* 4377851SDana.Myers@Sun.COM * Get the namespace entry for the control method we are about to call 4387851SDana.Myers@Sun.COM */ 4397851SDana.Myers@Sun.COM MethodNode = ThisWalkState->MethodCallNode; 4407851SDana.Myers@Sun.COM if (!MethodNode) 4417851SDana.Myers@Sun.COM { 4427851SDana.Myers@Sun.COM return_ACPI_STATUS (AE_NULL_ENTRY); 4437851SDana.Myers@Sun.COM } 4447851SDana.Myers@Sun.COM 4457851SDana.Myers@Sun.COM ObjDesc = AcpiNsGetAttachedObject (MethodNode); 4467851SDana.Myers@Sun.COM if (!ObjDesc) 4477851SDana.Myers@Sun.COM { 4487851SDana.Myers@Sun.COM return_ACPI_STATUS (AE_NULL_OBJECT); 4497851SDana.Myers@Sun.COM } 4507851SDana.Myers@Sun.COM 4517851SDana.Myers@Sun.COM /* Init for new method, possibly wait on method mutex */ 4527851SDana.Myers@Sun.COM 4537851SDana.Myers@Sun.COM Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc, 4547851SDana.Myers@Sun.COM ThisWalkState); 4557851SDana.Myers@Sun.COM if (ACPI_FAILURE (Status)) 4567851SDana.Myers@Sun.COM { 4577851SDana.Myers@Sun.COM return_ACPI_STATUS (Status); 4587851SDana.Myers@Sun.COM } 4597851SDana.Myers@Sun.COM 4607851SDana.Myers@Sun.COM /* Begin method parse/execution. Create a new walk state */ 4617851SDana.Myers@Sun.COM 4627851SDana.Myers@Sun.COM NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwnerId, 4637851SDana.Myers@Sun.COM NULL, ObjDesc, Thread); 4647851SDana.Myers@Sun.COM if (!NextWalkState) 4657851SDana.Myers@Sun.COM { 4667851SDana.Myers@Sun.COM Status = AE_NO_MEMORY; 4677851SDana.Myers@Sun.COM goto Cleanup; 4687851SDana.Myers@Sun.COM } 4697851SDana.Myers@Sun.COM 4707851SDana.Myers@Sun.COM /* 4717851SDana.Myers@Sun.COM * The resolved arguments were put on the previous walk state's operand 4727851SDana.Myers@Sun.COM * stack. Operands on the previous walk state stack always 4737851SDana.Myers@Sun.COM * start at index 0. Also, null terminate the list of arguments 4747851SDana.Myers@Sun.COM */ 4757851SDana.Myers@Sun.COM ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL; 4767851SDana.Myers@Sun.COM 4777851SDana.Myers@Sun.COM /* 4787851SDana.Myers@Sun.COM * Allocate and initialize the evaluation information block 4797851SDana.Myers@Sun.COM * TBD: this is somewhat inefficient, should change interface to 4807851SDana.Myers@Sun.COM * DsInitAmlWalk. For now, keeps this struct off the CPU stack 4817851SDana.Myers@Sun.COM */ 4827851SDana.Myers@Sun.COM Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 4837851SDana.Myers@Sun.COM if (!Info) 4847851SDana.Myers@Sun.COM { 4857851SDana.Myers@Sun.COM return_ACPI_STATUS (AE_NO_MEMORY); 4867851SDana.Myers@Sun.COM } 4877851SDana.Myers@Sun.COM 4887851SDana.Myers@Sun.COM Info->Parameters = &ThisWalkState->Operands[0]; 4897851SDana.Myers@Sun.COM 4907851SDana.Myers@Sun.COM Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode, 4917851SDana.Myers@Sun.COM ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, 4927851SDana.Myers@Sun.COM Info, ACPI_IMODE_EXECUTE); 4937851SDana.Myers@Sun.COM 4947851SDana.Myers@Sun.COM ACPI_FREE (Info); 4957851SDana.Myers@Sun.COM if (ACPI_FAILURE (Status)) 4967851SDana.Myers@Sun.COM { 4977851SDana.Myers@Sun.COM goto Cleanup; 4987851SDana.Myers@Sun.COM } 4997851SDana.Myers@Sun.COM 5007851SDana.Myers@Sun.COM /* 5017851SDana.Myers@Sun.COM * Delete the operands on the previous walkstate operand stack 5027851SDana.Myers@Sun.COM * (they were copied to new objects) 5037851SDana.Myers@Sun.COM */ 5047851SDana.Myers@Sun.COM for (i = 0; i < ObjDesc->Method.ParamCount; i++) 5057851SDana.Myers@Sun.COM { 5067851SDana.Myers@Sun.COM AcpiUtRemoveReference (ThisWalkState->Operands [i]); 5077851SDana.Myers@Sun.COM ThisWalkState->Operands [i] = NULL; 5087851SDana.Myers@Sun.COM } 5097851SDana.Myers@Sun.COM 5107851SDana.Myers@Sun.COM /* Clear the operand stack */ 5117851SDana.Myers@Sun.COM 5127851SDana.Myers@Sun.COM ThisWalkState->NumOperands = 0; 5137851SDana.Myers@Sun.COM 5147851SDana.Myers@Sun.COM ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 5157851SDana.Myers@Sun.COM "**** Begin nested execution of [%4.4s] **** WalkState=%p\n", 5167851SDana.Myers@Sun.COM MethodNode->Name.Ascii, NextWalkState)); 5177851SDana.Myers@Sun.COM 5187851SDana.Myers@Sun.COM /* Invoke an internal method if necessary */ 5197851SDana.Myers@Sun.COM 5207851SDana.Myers@Sun.COM if (ObjDesc->Method.MethodFlags & AML_METHOD_INTERNAL_ONLY) 5217851SDana.Myers@Sun.COM { 5227851SDana.Myers@Sun.COM Status = ObjDesc->Method.Implementation (NextWalkState); 523*9980SDana.Myers@Sun.COM if (Status == AE_OK) 524*9980SDana.Myers@Sun.COM { 525*9980SDana.Myers@Sun.COM Status = AE_CTRL_TERMINATE; 526*9980SDana.Myers@Sun.COM } 5277851SDana.Myers@Sun.COM } 5287851SDana.Myers@Sun.COM 5297851SDana.Myers@Sun.COM return_ACPI_STATUS (Status); 5307851SDana.Myers@Sun.COM 5317851SDana.Myers@Sun.COM 5327851SDana.Myers@Sun.COM Cleanup: 5337851SDana.Myers@Sun.COM 5347851SDana.Myers@Sun.COM /* On error, we must terminate the method properly */ 5357851SDana.Myers@Sun.COM 5367851SDana.Myers@Sun.COM AcpiDsTerminateControlMethod (ObjDesc, NextWalkState); 5377851SDana.Myers@Sun.COM if (NextWalkState) 5387851SDana.Myers@Sun.COM { 5397851SDana.Myers@Sun.COM AcpiDsDeleteWalkState (NextWalkState); 5407851SDana.Myers@Sun.COM } 5417851SDana.Myers@Sun.COM 5427851SDana.Myers@Sun.COM return_ACPI_STATUS (Status); 5437851SDana.Myers@Sun.COM } 5447851SDana.Myers@Sun.COM 5457851SDana.Myers@Sun.COM 5467851SDana.Myers@Sun.COM /******************************************************************************* 5477851SDana.Myers@Sun.COM * 5487851SDana.Myers@Sun.COM * FUNCTION: AcpiDsRestartControlMethod 5497851SDana.Myers@Sun.COM * 5507851SDana.Myers@Sun.COM * PARAMETERS: WalkState - State for preempted method (caller) 5517851SDana.Myers@Sun.COM * ReturnDesc - Return value from the called method 5527851SDana.Myers@Sun.COM * 5537851SDana.Myers@Sun.COM * RETURN: Status 5547851SDana.Myers@Sun.COM * 5557851SDana.Myers@Sun.COM * DESCRIPTION: Restart a method that was preempted by another (nested) method 5567851SDana.Myers@Sun.COM * invocation. Handle the return value (if any) from the callee. 5577851SDana.Myers@Sun.COM * 5587851SDana.Myers@Sun.COM ******************************************************************************/ 5597851SDana.Myers@Sun.COM 5607851SDana.Myers@Sun.COM ACPI_STATUS 5617851SDana.Myers@Sun.COM AcpiDsRestartControlMethod ( 5627851SDana.Myers@Sun.COM ACPI_WALK_STATE *WalkState, 5637851SDana.Myers@Sun.COM ACPI_OPERAND_OBJECT *ReturnDesc) 5647851SDana.Myers@Sun.COM { 5657851SDana.Myers@Sun.COM ACPI_STATUS Status; 5667851SDana.Myers@Sun.COM int SameAsImplicitReturn; 5677851SDana.Myers@Sun.COM 5687851SDana.Myers@Sun.COM 5697851SDana.Myers@Sun.COM ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState); 5707851SDana.Myers@Sun.COM 5717851SDana.Myers@Sun.COM 5727851SDana.Myers@Sun.COM ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 5737851SDana.Myers@Sun.COM "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n", 5747851SDana.Myers@Sun.COM AcpiUtGetNodeName (WalkState->MethodNode), 5757851SDana.Myers@Sun.COM WalkState->MethodCallOp, ReturnDesc)); 5767851SDana.Myers@Sun.COM 5777851SDana.Myers@Sun.COM ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 5787851SDana.Myers@Sun.COM " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n", 5797851SDana.Myers@Sun.COM WalkState->ReturnUsed, 5807851SDana.Myers@Sun.COM WalkState->Results, WalkState)); 5817851SDana.Myers@Sun.COM 5827851SDana.Myers@Sun.COM /* Did the called method return a value? */ 5837851SDana.Myers@Sun.COM 5847851SDana.Myers@Sun.COM if (ReturnDesc) 5857851SDana.Myers@Sun.COM { 5867851SDana.Myers@Sun.COM /* Is the implicit return object the same as the return desc? */ 5877851SDana.Myers@Sun.COM 5887851SDana.Myers@Sun.COM SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc); 5897851SDana.Myers@Sun.COM 5907851SDana.Myers@Sun.COM /* Are we actually going to use the return value? */ 5917851SDana.Myers@Sun.COM 5927851SDana.Myers@Sun.COM if (WalkState->ReturnUsed) 5937851SDana.Myers@Sun.COM { 5947851SDana.Myers@Sun.COM /* Save the return value from the previous method */ 5957851SDana.Myers@Sun.COM 5967851SDana.Myers@Sun.COM Status = AcpiDsResultPush (ReturnDesc, WalkState); 5977851SDana.Myers@Sun.COM if (ACPI_FAILURE (Status)) 5987851SDana.Myers@Sun.COM { 5997851SDana.Myers@Sun.COM AcpiUtRemoveReference (ReturnDesc); 6007851SDana.Myers@Sun.COM return_ACPI_STATUS (Status); 6017851SDana.Myers@Sun.COM } 6027851SDana.Myers@Sun.COM 6037851SDana.Myers@Sun.COM /* 6047851SDana.Myers@Sun.COM * Save as THIS method's return value in case it is returned 6057851SDana.Myers@Sun.COM * immediately to yet another method 6067851SDana.Myers@Sun.COM */ 6077851SDana.Myers@Sun.COM WalkState->ReturnDesc = ReturnDesc; 6087851SDana.Myers@Sun.COM } 6097851SDana.Myers@Sun.COM 6107851SDana.Myers@Sun.COM /* 6117851SDana.Myers@Sun.COM * The following code is the optional support for the so-called 6127851SDana.Myers@Sun.COM * "implicit return". Some AML code assumes that the last value of the 6137851SDana.Myers@Sun.COM * method is "implicitly" returned to the caller, in the absence of an 6147851SDana.Myers@Sun.COM * explicit return value. 6157851SDana.Myers@Sun.COM * 6167851SDana.Myers@Sun.COM * Just save the last result of the method as the return value. 6177851SDana.Myers@Sun.COM * 6187851SDana.Myers@Sun.COM * NOTE: this is optional because the ASL language does not actually 6197851SDana.Myers@Sun.COM * support this behavior. 6207851SDana.Myers@Sun.COM */ 6217851SDana.Myers@Sun.COM else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) || 6227851SDana.Myers@Sun.COM SameAsImplicitReturn) 6237851SDana.Myers@Sun.COM { 6247851SDana.Myers@Sun.COM /* 6257851SDana.Myers@Sun.COM * Delete the return value if it will not be used by the 6267851SDana.Myers@Sun.COM * calling method or remove one reference if the explicit return 6277851SDana.Myers@Sun.COM * is the same as the implicit return value. 6287851SDana.Myers@Sun.COM */ 6297851SDana.Myers@Sun.COM AcpiUtRemoveReference (ReturnDesc); 6307851SDana.Myers@Sun.COM } 6317851SDana.Myers@Sun.COM } 6327851SDana.Myers@Sun.COM 6337851SDana.Myers@Sun.COM return_ACPI_STATUS (AE_OK); 6347851SDana.Myers@Sun.COM } 6357851SDana.Myers@Sun.COM 6367851SDana.Myers@Sun.COM 6377851SDana.Myers@Sun.COM /******************************************************************************* 6387851SDana.Myers@Sun.COM * 6397851SDana.Myers@Sun.COM * FUNCTION: AcpiDsTerminateControlMethod 6407851SDana.Myers@Sun.COM * 6417851SDana.Myers@Sun.COM * PARAMETERS: MethodDesc - Method object 6427851SDana.Myers@Sun.COM * WalkState - State associated with the method 6437851SDana.Myers@Sun.COM * 6447851SDana.Myers@Sun.COM * RETURN: None 6457851SDana.Myers@Sun.COM * 6467851SDana.Myers@Sun.COM * DESCRIPTION: Terminate a control method. Delete everything that the method 6477851SDana.Myers@Sun.COM * created, delete all locals and arguments, and delete the parse 6487851SDana.Myers@Sun.COM * tree if requested. 6497851SDana.Myers@Sun.COM * 6507851SDana.Myers@Sun.COM * MUTEX: Interpreter is locked 6517851SDana.Myers@Sun.COM * 6527851SDana.Myers@Sun.COM ******************************************************************************/ 6537851SDana.Myers@Sun.COM 6547851SDana.Myers@Sun.COM void 6557851SDana.Myers@Sun.COM AcpiDsTerminateControlMethod ( 6567851SDana.Myers@Sun.COM ACPI_OPERAND_OBJECT *MethodDesc, 6577851SDana.Myers@Sun.COM ACPI_WALK_STATE *WalkState) 6587851SDana.Myers@Sun.COM { 6597851SDana.Myers@Sun.COM 6607851SDana.Myers@Sun.COM ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState); 6617851SDana.Myers@Sun.COM 6627851SDana.Myers@Sun.COM 6637851SDana.Myers@Sun.COM /* MethodDesc is required, WalkState is optional */ 6647851SDana.Myers@Sun.COM 6657851SDana.Myers@Sun.COM if (!MethodDesc) 6667851SDana.Myers@Sun.COM { 6677851SDana.Myers@Sun.COM return_VOID; 6687851SDana.Myers@Sun.COM } 6697851SDana.Myers@Sun.COM 6707851SDana.Myers@Sun.COM if (WalkState) 6717851SDana.Myers@Sun.COM { 6727851SDana.Myers@Sun.COM /* Delete all arguments and locals */ 6737851SDana.Myers@Sun.COM 6747851SDana.Myers@Sun.COM AcpiDsMethodDataDeleteAll (WalkState); 6757851SDana.Myers@Sun.COM 6767851SDana.Myers@Sun.COM /* 6777851SDana.Myers@Sun.COM * If method is serialized, release the mutex and restore the 6787851SDana.Myers@Sun.COM * current sync level for this thread 6797851SDana.Myers@Sun.COM */ 6807851SDana.Myers@Sun.COM if (MethodDesc->Method.Mutex) 6817851SDana.Myers@Sun.COM { 6827851SDana.Myers@Sun.COM /* Acquisition Depth handles recursive calls */ 6837851SDana.Myers@Sun.COM 6847851SDana.Myers@Sun.COM MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--; 6857851SDana.Myers@Sun.COM if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth) 6867851SDana.Myers@Sun.COM { 6877851SDana.Myers@Sun.COM WalkState->Thread->CurrentSyncLevel = 6887851SDana.Myers@Sun.COM MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel; 6897851SDana.Myers@Sun.COM 6907851SDana.Myers@Sun.COM AcpiOsReleaseMutex (MethodDesc->Method.Mutex->Mutex.OsMutex); 6917851SDana.Myers@Sun.COM MethodDesc->Method.Mutex->Mutex.ThreadId = 0; 6927851SDana.Myers@Sun.COM } 6937851SDana.Myers@Sun.COM } 6947851SDana.Myers@Sun.COM 6957851SDana.Myers@Sun.COM /* 6967851SDana.Myers@Sun.COM * Delete any namespace objects created anywhere within 6977851SDana.Myers@Sun.COM * the namespace by the execution of this method 6987851SDana.Myers@Sun.COM */ 6997851SDana.Myers@Sun.COM AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId); 7007851SDana.Myers@Sun.COM } 7017851SDana.Myers@Sun.COM 7027851SDana.Myers@Sun.COM /* Decrement the thread count on the method */ 7037851SDana.Myers@Sun.COM 7047851SDana.Myers@Sun.COM if (MethodDesc->Method.ThreadCount) 7057851SDana.Myers@Sun.COM { 7067851SDana.Myers@Sun.COM MethodDesc->Method.ThreadCount--; 7077851SDana.Myers@Sun.COM } 7087851SDana.Myers@Sun.COM else 7097851SDana.Myers@Sun.COM { 7107851SDana.Myers@Sun.COM ACPI_ERROR ((AE_INFO, 7117851SDana.Myers@Sun.COM "Invalid zero thread count in method")); 7127851SDana.Myers@Sun.COM } 7137851SDana.Myers@Sun.COM 7147851SDana.Myers@Sun.COM /* Are there any other threads currently executing this method? */ 7157851SDana.Myers@Sun.COM 7167851SDana.Myers@Sun.COM if (MethodDesc->Method.ThreadCount) 7177851SDana.Myers@Sun.COM { 7187851SDana.Myers@Sun.COM /* 7197851SDana.Myers@Sun.COM * Additional threads. Do not release the OwnerId in this case, 7207851SDana.Myers@Sun.COM * we immediately reuse it for the next thread executing this method 7217851SDana.Myers@Sun.COM */ 7227851SDana.Myers@Sun.COM ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 7237851SDana.Myers@Sun.COM "*** Completed execution of one thread, %d threads remaining\n", 7247851SDana.Myers@Sun.COM MethodDesc->Method.ThreadCount)); 7257851SDana.Myers@Sun.COM } 7267851SDana.Myers@Sun.COM else 7277851SDana.Myers@Sun.COM { 7287851SDana.Myers@Sun.COM /* This is the only executing thread for this method */ 7297851SDana.Myers@Sun.COM 7307851SDana.Myers@Sun.COM /* 7317851SDana.Myers@Sun.COM * Support to dynamically change a method from NotSerialized to 7327851SDana.Myers@Sun.COM * Serialized if it appears that the method is incorrectly written and 7337851SDana.Myers@Sun.COM * does not support multiple thread execution. The best example of this 7347851SDana.Myers@Sun.COM * is if such a method creates namespace objects and blocks. A second 7357851SDana.Myers@Sun.COM * thread will fail with an AE_ALREADY_EXISTS exception 7367851SDana.Myers@Sun.COM * 7377851SDana.Myers@Sun.COM * This code is here because we must wait until the last thread exits 7387851SDana.Myers@Sun.COM * before creating the synchronization semaphore. 7397851SDana.Myers@Sun.COM */ 7407851SDana.Myers@Sun.COM if ((MethodDesc->Method.MethodFlags & AML_METHOD_SERIALIZED) && 7417851SDana.Myers@Sun.COM (!MethodDesc->Method.Mutex)) 7427851SDana.Myers@Sun.COM { 7437851SDana.Myers@Sun.COM (void) AcpiDsCreateMethodMutex (MethodDesc); 7447851SDana.Myers@Sun.COM } 7457851SDana.Myers@Sun.COM 7467851SDana.Myers@Sun.COM /* No more threads, we can free the OwnerId */ 7477851SDana.Myers@Sun.COM 7487851SDana.Myers@Sun.COM AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId); 7497851SDana.Myers@Sun.COM } 7507851SDana.Myers@Sun.COM 7517851SDana.Myers@Sun.COM return_VOID; 7527851SDana.Myers@Sun.COM } 7537851SDana.Myers@Sun.COM 7547851SDana.Myers@Sun.COM 755