Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendsmethod.c
Go to the documentation of this file.
00001 /****************************************************************************** 00002 * 00003 * Module Name: dsmethod - Parser/Interpreter interface - control method parsing 00004 * 00005 *****************************************************************************/ 00006 00007 /****************************************************************************** 00008 * 00009 * 1. Copyright Notice 00010 * 00011 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. 00012 * All rights reserved. 00013 * 00014 * 2. License 00015 * 00016 * 2.1. This is your license from Intel Corp. under its intellectual property 00017 * rights. You may have additional license terms from the party that provided 00018 * you this software, covering your right to use that party's intellectual 00019 * property rights. 00020 * 00021 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 00022 * copy of the source code appearing in this file ("Covered Code") an 00023 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 00024 * base code distributed originally by Intel ("Original Intel Code") to copy, 00025 * make derivatives, distribute, use and display any portion of the Covered 00026 * Code in any form, with the right to sublicense such rights; and 00027 * 00028 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 00029 * license (with the right to sublicense), under only those claims of Intel 00030 * patents that are infringed by the Original Intel Code, to make, use, sell, 00031 * offer to sell, and import the Covered Code and derivative works thereof 00032 * solely to the minimum extent necessary to exercise the above copyright 00033 * license, and in no event shall the patent license extend to any additions 00034 * to or modifications of the Original Intel Code. No other license or right 00035 * is granted directly or by implication, estoppel or otherwise; 00036 * 00037 * The above copyright and patent license is granted only if the following 00038 * conditions are met: 00039 * 00040 * 3. Conditions 00041 * 00042 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 00043 * Redistribution of source code of any substantial portion of the Covered 00044 * Code or modification with rights to further distribute source must include 00045 * the above Copyright Notice, the above License, this list of Conditions, 00046 * and the following Disclaimer and Export Compliance provision. In addition, 00047 * Licensee must cause all Covered Code to which Licensee contributes to 00048 * contain a file documenting the changes Licensee made to create that Covered 00049 * Code and the date of any change. Licensee must include in that file the 00050 * documentation of any changes made by any predecessor Licensee. Licensee 00051 * must include a prominent statement that the modification is derived, 00052 * directly or indirectly, from Original Intel Code. 00053 * 00054 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 00055 * Redistribution of source code of any substantial portion of the Covered 00056 * Code or modification without rights to further distribute source must 00057 * include the following Disclaimer and Export Compliance provision in the 00058 * documentation and/or other materials provided with distribution. In 00059 * addition, Licensee may not authorize further sublicense of source of any 00060 * portion of the Covered Code, and must include terms to the effect that the 00061 * license from Licensee to its licensee is limited to the intellectual 00062 * property embodied in the software Licensee provides to its licensee, and 00063 * not to intellectual property embodied in modifications its licensee may 00064 * make. 00065 * 00066 * 3.3. Redistribution of Executable. Redistribution in executable form of any 00067 * substantial portion of the Covered Code or modification must reproduce the 00068 * above Copyright Notice, and the following Disclaimer and Export Compliance 00069 * provision in the documentation and/or other materials provided with the 00070 * distribution. 00071 * 00072 * 3.4. Intel retains all right, title, and interest in and to the Original 00073 * Intel Code. 00074 * 00075 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 00076 * Intel shall be used in advertising or otherwise to promote the sale, use or 00077 * other dealings in products derived from or relating to the Covered Code 00078 * without prior written authorization from Intel. 00079 * 00080 * 4. Disclaimer and Export Compliance 00081 * 00082 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 00083 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 00084 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 00085 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 00086 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 00087 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 00088 * PARTICULAR PURPOSE. 00089 * 00090 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 00091 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 00092 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 00093 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 00094 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 00095 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 00096 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 00097 * LIMITED REMEDY. 00098 * 00099 * 4.3. Licensee shall not export, either directly or indirectly, any of this 00100 * software or system incorporating such software without first obtaining any 00101 * required license or other approval from the U. S. Department of Commerce or 00102 * any other agency or department of the United States Government. In the 00103 * event Licensee exports any such software from the United States or 00104 * re-exports any such software from a foreign destination, Licensee shall 00105 * ensure that the distribution and export/re-export of the software is in 00106 * compliance with all laws, regulations, orders, or other restrictions of the 00107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 00108 * any of its subsidiaries will export/re-export any technical data, process, 00109 * software, or service, directly or indirectly, to any country for which the 00110 * United States government or any agency thereof requires an export license, 00111 * other governmental approval, or letter of assurance, without first obtaining 00112 * such license, approval or letter. 00113 * 00114 *****************************************************************************/ 00115 00116 #define __DSMETHOD_C__ 00117 00118 #include "acpi.h" 00119 #include "accommon.h" 00120 #include "acdispat.h" 00121 #include "acinterp.h" 00122 #include "acnamesp.h" 00123 #include "acdisasm.h" 00124 00125 00126 #define _COMPONENT ACPI_DISPATCHER 00127 ACPI_MODULE_NAME ("dsmethod") 00128 00129 /* Local prototypes */ 00130 00131 static ACPI_STATUS 00132 AcpiDsCreateMethodMutex ( 00133 ACPI_OPERAND_OBJECT *MethodDesc); 00134 00135 00136 /******************************************************************************* 00137 * 00138 * FUNCTION: AcpiDsMethodError 00139 * 00140 * PARAMETERS: Status - Execution status 00141 * WalkState - Current state 00142 * 00143 * RETURN: Status 00144 * 00145 * DESCRIPTION: Called on method error. Invoke the global exception handler if 00146 * present, dump the method data if the disassembler is configured 00147 * 00148 * Note: Allows the exception handler to change the status code 00149 * 00150 ******************************************************************************/ 00151 00152 ACPI_STATUS 00153 AcpiDsMethodError ( 00154 ACPI_STATUS Status, 00155 ACPI_WALK_STATE *WalkState) 00156 { 00157 ACPI_FUNCTION_ENTRY (); 00158 00159 00160 /* Ignore AE_OK and control exception codes */ 00161 00162 if (ACPI_SUCCESS (Status) || 00163 (Status & AE_CODE_CONTROL)) 00164 { 00165 return (Status); 00166 } 00167 00168 /* Invoke the global exception handler */ 00169 00170 if (AcpiGbl_ExceptionHandler) 00171 { 00172 /* Exit the interpreter, allow handler to execute methods */ 00173 00174 AcpiExExitInterpreter (); 00175 00176 /* 00177 * Handler can map the exception code to anything it wants, including 00178 * AE_OK, in which case the executing method will not be aborted. 00179 */ 00180 Status = AcpiGbl_ExceptionHandler (Status, 00181 WalkState->MethodNode ? 00182 WalkState->MethodNode->Name.Integer : 0, 00183 WalkState->Opcode, WalkState->AmlOffset, NULL); 00184 AcpiExEnterInterpreter (); 00185 } 00186 00187 AcpiDsClearImplicitReturn (WalkState); 00188 00189 #ifdef ACPI_DISASSEMBLER 00190 if (ACPI_FAILURE (Status)) 00191 { 00192 /* Display method locals/args if disassembler is present */ 00193 00194 AcpiDmDumpMethodInfo (Status, WalkState, WalkState->Op); 00195 } 00196 #endif 00197 00198 return (Status); 00199 } 00200 00201 00202 /******************************************************************************* 00203 * 00204 * FUNCTION: AcpiDsCreateMethodMutex 00205 * 00206 * PARAMETERS: ObjDesc - The method object 00207 * 00208 * RETURN: Status 00209 * 00210 * DESCRIPTION: Create a mutex object for a serialized control method 00211 * 00212 ******************************************************************************/ 00213 00214 static ACPI_STATUS 00215 AcpiDsCreateMethodMutex ( 00216 ACPI_OPERAND_OBJECT *MethodDesc) 00217 { 00218 ACPI_OPERAND_OBJECT *MutexDesc; 00219 ACPI_STATUS Status; 00220 00221 00222 ACPI_FUNCTION_TRACE (DsCreateMethodMutex); 00223 00224 00225 /* Create the new mutex object */ 00226 00227 MutexDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX); 00228 if (!MutexDesc) 00229 { 00230 return_ACPI_STATUS (AE_NO_MEMORY); 00231 } 00232 00233 /* Create the actual OS Mutex */ 00234 00235 Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex); 00236 if (ACPI_FAILURE (Status)) 00237 { 00238 return_ACPI_STATUS (Status); 00239 } 00240 00241 MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel; 00242 MethodDesc->Method.Mutex = MutexDesc; 00243 return_ACPI_STATUS (AE_OK); 00244 } 00245 00246 00247 /******************************************************************************* 00248 * 00249 * FUNCTION: AcpiDsBeginMethodExecution 00250 * 00251 * PARAMETERS: MethodNode - Node of the method 00252 * ObjDesc - The method object 00253 * WalkState - current state, NULL if not yet executing 00254 * a method. 00255 * 00256 * RETURN: Status 00257 * 00258 * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, 00259 * increments the thread count, and waits at the method semaphore 00260 * for clearance to execute. 00261 * 00262 ******************************************************************************/ 00263 00264 ACPI_STATUS 00265 AcpiDsBeginMethodExecution ( 00266 ACPI_NAMESPACE_NODE *MethodNode, 00267 ACPI_OPERAND_OBJECT *ObjDesc, 00268 ACPI_WALK_STATE *WalkState) 00269 { 00270 ACPI_STATUS Status = AE_OK; 00271 00272 00273 ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode); 00274 00275 00276 if (!MethodNode) 00277 { 00278 return_ACPI_STATUS (AE_NULL_ENTRY); 00279 } 00280 00281 /* Prevent wraparound of thread count */ 00282 00283 if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX) 00284 { 00285 ACPI_ERROR ((AE_INFO, 00286 "Method reached maximum reentrancy limit (255)")); 00287 return_ACPI_STATUS (AE_AML_METHOD_LIMIT); 00288 } 00289 00290 /* 00291 * If this method is serialized, we need to acquire the method mutex. 00292 */ 00293 if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED) 00294 { 00295 /* 00296 * Create a mutex for the method if it is defined to be Serialized 00297 * and a mutex has not already been created. We defer the mutex creation 00298 * until a method is actually executed, to minimize the object count 00299 */ 00300 if (!ObjDesc->Method.Mutex) 00301 { 00302 Status = AcpiDsCreateMethodMutex (ObjDesc); 00303 if (ACPI_FAILURE (Status)) 00304 { 00305 return_ACPI_STATUS (Status); 00306 } 00307 } 00308 00309 /* 00310 * The CurrentSyncLevel (per-thread) must be less than or equal to 00311 * the sync level of the method. This mechanism provides some 00312 * deadlock prevention 00313 * 00314 * Top-level method invocation has no walk state at this point 00315 */ 00316 if (WalkState && 00317 (WalkState->Thread->CurrentSyncLevel > ObjDesc->Method.Mutex->Mutex.SyncLevel)) 00318 { 00319 ACPI_ERROR ((AE_INFO, 00320 "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)", 00321 AcpiUtGetNodeName (MethodNode), 00322 WalkState->Thread->CurrentSyncLevel)); 00323 00324 return_ACPI_STATUS (AE_AML_MUTEX_ORDER); 00325 } 00326 00327 /* 00328 * Obtain the method mutex if necessary. Do not acquire mutex for a 00329 * recursive call. 00330 */ 00331 if (!WalkState || 00332 !ObjDesc->Method.Mutex->Mutex.ThreadId || 00333 (WalkState->Thread->ThreadId != ObjDesc->Method.Mutex->Mutex.ThreadId)) 00334 { 00335 /* 00336 * Acquire the method mutex. This releases the interpreter if we 00337 * block (and reacquires it before it returns) 00338 */ 00339 Status = AcpiExSystemWaitMutex (ObjDesc->Method.Mutex->Mutex.OsMutex, 00340 ACPI_WAIT_FOREVER); 00341 if (ACPI_FAILURE (Status)) 00342 { 00343 return_ACPI_STATUS (Status); 00344 } 00345 00346 /* Update the mutex and walk info and save the original SyncLevel */ 00347 00348 if (WalkState) 00349 { 00350 ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel = 00351 WalkState->Thread->CurrentSyncLevel; 00352 00353 ObjDesc->Method.Mutex->Mutex.ThreadId = WalkState->Thread->ThreadId; 00354 WalkState->Thread->CurrentSyncLevel = ObjDesc->Method.SyncLevel; 00355 } 00356 else 00357 { 00358 ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel = 00359 ObjDesc->Method.Mutex->Mutex.SyncLevel; 00360 } 00361 } 00362 00363 /* Always increase acquisition depth */ 00364 00365 ObjDesc->Method.Mutex->Mutex.AcquisitionDepth++; 00366 } 00367 00368 /* 00369 * Allocate an Owner ID for this method, only if this is the first thread 00370 * to begin concurrent execution. We only need one OwnerId, even if the 00371 * method is invoked recursively. 00372 */ 00373 if (!ObjDesc->Method.OwnerId) 00374 { 00375 Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId); 00376 if (ACPI_FAILURE (Status)) 00377 { 00378 goto Cleanup; 00379 } 00380 } 00381 00382 /* 00383 * Increment the method parse tree thread count since it has been 00384 * reentered one more time (even if it is the same thread) 00385 */ 00386 ObjDesc->Method.ThreadCount++; 00387 AcpiMethodCount++; 00388 return_ACPI_STATUS (Status); 00389 00390 00391 Cleanup: 00392 /* On error, must release the method mutex (if present) */ 00393 00394 if (ObjDesc->Method.Mutex) 00395 { 00396 AcpiOsReleaseMutex (ObjDesc->Method.Mutex->Mutex.OsMutex); 00397 } 00398 return_ACPI_STATUS (Status); 00399 } 00400 00401 00402 /******************************************************************************* 00403 * 00404 * FUNCTION: AcpiDsCallControlMethod 00405 * 00406 * PARAMETERS: Thread - Info for this thread 00407 * ThisWalkState - Current walk state 00408 * Op - Current Op to be walked 00409 * 00410 * RETURN: Status 00411 * 00412 * DESCRIPTION: Transfer execution to a called control method 00413 * 00414 ******************************************************************************/ 00415 00416 ACPI_STATUS 00417 AcpiDsCallControlMethod ( 00418 ACPI_THREAD_STATE *Thread, 00419 ACPI_WALK_STATE *ThisWalkState, 00420 ACPI_PARSE_OBJECT *Op) 00421 { 00422 ACPI_STATUS Status; 00423 ACPI_NAMESPACE_NODE *MethodNode; 00424 ACPI_WALK_STATE *NextWalkState = NULL; 00425 ACPI_OPERAND_OBJECT *ObjDesc; 00426 ACPI_EVALUATE_INFO *Info; 00427 UINT32 i; 00428 00429 00430 ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState); 00431 00432 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Calling method %p, currentstate=%p\n", 00433 ThisWalkState->PrevOp, ThisWalkState)); 00434 00435 /* 00436 * Get the namespace entry for the control method we are about to call 00437 */ 00438 MethodNode = ThisWalkState->MethodCallNode; 00439 if (!MethodNode) 00440 { 00441 return_ACPI_STATUS (AE_NULL_ENTRY); 00442 } 00443 00444 ObjDesc = AcpiNsGetAttachedObject (MethodNode); 00445 if (!ObjDesc) 00446 { 00447 return_ACPI_STATUS (AE_NULL_OBJECT); 00448 } 00449 00450 /* Init for new method, possibly wait on method mutex */ 00451 00452 Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc, 00453 ThisWalkState); 00454 if (ACPI_FAILURE (Status)) 00455 { 00456 return_ACPI_STATUS (Status); 00457 } 00458 00459 /* Begin method parse/execution. Create a new walk state */ 00460 00461 NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwnerId, 00462 NULL, ObjDesc, Thread); 00463 if (!NextWalkState) 00464 { 00465 Status = AE_NO_MEMORY; 00466 goto Cleanup; 00467 } 00468 00469 /* 00470 * The resolved arguments were put on the previous walk state's operand 00471 * stack. Operands on the previous walk state stack always 00472 * start at index 0. Also, null terminate the list of arguments 00473 */ 00474 ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL; 00475 00476 /* 00477 * Allocate and initialize the evaluation information block 00478 * TBD: this is somewhat inefficient, should change interface to 00479 * DsInitAmlWalk. For now, keeps this struct off the CPU stack 00480 */ 00481 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 00482 if (!Info) 00483 { 00484 return_ACPI_STATUS (AE_NO_MEMORY); 00485 } 00486 00487 Info->Parameters = &ThisWalkState->Operands[0]; 00488 00489 Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode, 00490 ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, 00491 Info, ACPI_IMODE_EXECUTE); 00492 00493 ACPI_FREE (Info); 00494 if (ACPI_FAILURE (Status)) 00495 { 00496 goto Cleanup; 00497 } 00498 00499 /* 00500 * Delete the operands on the previous walkstate operand stack 00501 * (they were copied to new objects) 00502 */ 00503 for (i = 0; i < ObjDesc->Method.ParamCount; i++) 00504 { 00505 AcpiUtRemoveReference (ThisWalkState->Operands [i]); 00506 ThisWalkState->Operands [i] = NULL; 00507 } 00508 00509 /* Clear the operand stack */ 00510 00511 ThisWalkState->NumOperands = 0; 00512 00513 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 00514 "**** Begin nested execution of [%4.4s] **** WalkState=%p\n", 00515 MethodNode->Name.Ascii, NextWalkState)); 00516 00517 /* Invoke an internal method if necessary */ 00518 00519 if (ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY) 00520 { 00521 Status = ObjDesc->Method.Dispatch.Implementation (NextWalkState); 00522 if (Status == AE_OK) 00523 { 00524 Status = AE_CTRL_TERMINATE; 00525 } 00526 } 00527 00528 return_ACPI_STATUS (Status); 00529 00530 00531 Cleanup: 00532 00533 /* On error, we must terminate the method properly */ 00534 00535 AcpiDsTerminateControlMethod (ObjDesc, NextWalkState); 00536 if (NextWalkState) 00537 { 00538 AcpiDsDeleteWalkState (NextWalkState); 00539 } 00540 00541 return_ACPI_STATUS (Status); 00542 } 00543 00544 00545 /******************************************************************************* 00546 * 00547 * FUNCTION: AcpiDsRestartControlMethod 00548 * 00549 * PARAMETERS: WalkState - State for preempted method (caller) 00550 * ReturnDesc - Return value from the called method 00551 * 00552 * RETURN: Status 00553 * 00554 * DESCRIPTION: Restart a method that was preempted by another (nested) method 00555 * invocation. Handle the return value (if any) from the callee. 00556 * 00557 ******************************************************************************/ 00558 00559 ACPI_STATUS 00560 AcpiDsRestartControlMethod ( 00561 ACPI_WALK_STATE *WalkState, 00562 ACPI_OPERAND_OBJECT *ReturnDesc) 00563 { 00564 ACPI_STATUS Status; 00565 int SameAsImplicitReturn; 00566 00567 00568 ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState); 00569 00570 00571 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 00572 "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n", 00573 AcpiUtGetNodeName (WalkState->MethodNode), 00574 WalkState->MethodCallOp, ReturnDesc)); 00575 00576 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 00577 " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n", 00578 WalkState->ReturnUsed, 00579 WalkState->Results, WalkState)); 00580 00581 /* Did the called method return a value? */ 00582 00583 if (ReturnDesc) 00584 { 00585 /* Is the implicit return object the same as the return desc? */ 00586 00587 SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc); 00588 00589 /* Are we actually going to use the return value? */ 00590 00591 if (WalkState->ReturnUsed) 00592 { 00593 /* Save the return value from the previous method */ 00594 00595 Status = AcpiDsResultPush (ReturnDesc, WalkState); 00596 if (ACPI_FAILURE (Status)) 00597 { 00598 AcpiUtRemoveReference (ReturnDesc); 00599 return_ACPI_STATUS (Status); 00600 } 00601 00602 /* 00603 * Save as THIS method's return value in case it is returned 00604 * immediately to yet another method 00605 */ 00606 WalkState->ReturnDesc = ReturnDesc; 00607 } 00608 00609 /* 00610 * The following code is the optional support for the so-called 00611 * "implicit return". Some AML code assumes that the last value of the 00612 * method is "implicitly" returned to the caller, in the absence of an 00613 * explicit return value. 00614 * 00615 * Just save the last result of the method as the return value. 00616 * 00617 * NOTE: this is optional because the ASL language does not actually 00618 * support this behavior. 00619 */ 00620 else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) || 00621 SameAsImplicitReturn) 00622 { 00623 /* 00624 * Delete the return value if it will not be used by the 00625 * calling method or remove one reference if the explicit return 00626 * is the same as the implicit return value. 00627 */ 00628 AcpiUtRemoveReference (ReturnDesc); 00629 } 00630 } 00631 00632 return_ACPI_STATUS (AE_OK); 00633 } 00634 00635 00636 /******************************************************************************* 00637 * 00638 * FUNCTION: AcpiDsTerminateControlMethod 00639 * 00640 * PARAMETERS: MethodDesc - Method object 00641 * WalkState - State associated with the method 00642 * 00643 * RETURN: None 00644 * 00645 * DESCRIPTION: Terminate a control method. Delete everything that the method 00646 * created, delete all locals and arguments, and delete the parse 00647 * tree if requested. 00648 * 00649 * MUTEX: Interpreter is locked 00650 * 00651 ******************************************************************************/ 00652 00653 void 00654 AcpiDsTerminateControlMethod ( 00655 ACPI_OPERAND_OBJECT *MethodDesc, 00656 ACPI_WALK_STATE *WalkState) 00657 { 00658 00659 ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState); 00660 00661 00662 /* MethodDesc is required, WalkState is optional */ 00663 00664 if (!MethodDesc) 00665 { 00666 return_VOID; 00667 } 00668 00669 if (WalkState) 00670 { 00671 /* Delete all arguments and locals */ 00672 00673 AcpiDsMethodDataDeleteAll (WalkState); 00674 00675 /* 00676 * If method is serialized, release the mutex and restore the 00677 * current sync level for this thread 00678 */ 00679 if (MethodDesc->Method.Mutex) 00680 { 00681 /* Acquisition Depth handles recursive calls */ 00682 00683 MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--; 00684 if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth) 00685 { 00686 WalkState->Thread->CurrentSyncLevel = 00687 MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel; 00688 00689 AcpiOsReleaseMutex (MethodDesc->Method.Mutex->Mutex.OsMutex); 00690 MethodDesc->Method.Mutex->Mutex.ThreadId = 0; 00691 } 00692 } 00693 00694 /* 00695 * Delete any namespace objects created anywhere within the 00696 * namespace by the execution of this method. Unless: 00697 * 1) This method is a module-level executable code method, in which 00698 * case we want make the objects permanent. 00699 * 2) There are other threads executing the method, in which case we 00700 * will wait until the last thread has completed. 00701 */ 00702 if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) && 00703 (MethodDesc->Method.ThreadCount == 1)) 00704 { 00705 /* Delete any direct children of (created by) this method */ 00706 00707 AcpiNsDeleteNamespaceSubtree (WalkState->MethodNode); 00708 00709 /* 00710 * Delete any objects that were created by this method 00711 * elsewhere in the namespace (if any were created). 00712 * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the 00713 * deletion such that we don't have to perform an entire 00714 * namespace walk for every control method execution. 00715 */ 00716 if (MethodDesc->Method.InfoFlags & ACPI_METHOD_MODIFIED_NAMESPACE) 00717 { 00718 AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId); 00719 MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_MODIFIED_NAMESPACE; 00720 } 00721 } 00722 } 00723 00724 /* Decrement the thread count on the method */ 00725 00726 if (MethodDesc->Method.ThreadCount) 00727 { 00728 MethodDesc->Method.ThreadCount--; 00729 } 00730 else 00731 { 00732 ACPI_ERROR ((AE_INFO, 00733 "Invalid zero thread count in method")); 00734 } 00735 00736 /* Are there any other threads currently executing this method? */ 00737 00738 if (MethodDesc->Method.ThreadCount) 00739 { 00740 /* 00741 * Additional threads. Do not release the OwnerId in this case, 00742 * we immediately reuse it for the next thread executing this method 00743 */ 00744 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 00745 "*** Completed execution of one thread, %u threads remaining\n", 00746 MethodDesc->Method.ThreadCount)); 00747 } 00748 else 00749 { 00750 /* This is the only executing thread for this method */ 00751 00752 /* 00753 * Support to dynamically change a method from NotSerialized to 00754 * Serialized if it appears that the method is incorrectly written and 00755 * does not support multiple thread execution. The best example of this 00756 * is if such a method creates namespace objects and blocks. A second 00757 * thread will fail with an AE_ALREADY_EXISTS exception. 00758 * 00759 * This code is here because we must wait until the last thread exits 00760 * before marking the method as serialized. 00761 */ 00762 if (MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED_PENDING) 00763 { 00764 if (WalkState) 00765 { 00766 ACPI_INFO ((AE_INFO, 00767 "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", 00768 WalkState->MethodNode->Name.Ascii)); 00769 } 00770 00771 /* 00772 * Method tried to create an object twice and was marked as 00773 * "pending serialized". The probable cause is that the method 00774 * cannot handle reentrancy. 00775 * 00776 * The method was created as NotSerialized, but it tried to create 00777 * a named object and then blocked, causing the second thread 00778 * entrance to begin and then fail. Workaround this problem by 00779 * marking the method permanently as Serialized when the last 00780 * thread exits here. 00781 */ 00782 MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_SERIALIZED_PENDING; 00783 MethodDesc->Method.InfoFlags |= ACPI_METHOD_SERIALIZED; 00784 MethodDesc->Method.SyncLevel = 0; 00785 } 00786 00787 /* No more threads, we can free the OwnerId */ 00788 00789 if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL)) 00790 { 00791 AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId); 00792 } 00793 } 00794 00795 return_VOID; 00796 } 00797 00798 Generated on Fri May 25 2012 04:25:27 for ReactOS by
1.7.6.1
|