dbexec.c revision 250838
167754Smsmith/******************************************************************************* 267754Smsmith * 367754Smsmith * Module Name: dbexec - debugger control method execution 4100966Siwasaki * 567754Smsmith ******************************************************************************/ 667754Smsmith 767754Smsmith/* 867754Smsmith * Copyright (C) 2000 - 2013, Intel Corp. 967754Smsmith * All rights reserved. 1067754Smsmith * 1167754Smsmith * Redistribution and use in source and binary forms, with or without 1291116Smsmith * modification, are permitted provided that the following conditions 1370243Smsmith * are met: 1467754Smsmith * 1. Redistributions of source code must retain the above copyright 1567754Smsmith * notice, this list of conditions, and the following disclaimer, 1667754Smsmith * without modification. 1767754Smsmith * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1867754Smsmith * substantially similar to the "NO WARRANTY" disclaimer below 1967754Smsmith * ("Disclaimer") and any redistribution must be conditioned upon 2067754Smsmith * including a substantially similar Disclaimer requirement for further 2167754Smsmith * binary redistribution. 2267754Smsmith * 3. Neither the names of the above-listed copyright holders nor the names 2367754Smsmith * of any contributors may be used to endorse or promote products derived 2467754Smsmith * from this software without specific prior written permission. 2567754Smsmith * 2667754Smsmith * Alternatively, this software may be distributed under the terms of the 2767754Smsmith * GNU General Public License ("GPL") version 2 as published by the Free 2867754Smsmith * Software Foundation. 2967754Smsmith * 3067754Smsmith * NO WARRANTY 3167754Smsmith * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3267754Smsmith * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3367754Smsmith * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3467754Smsmith * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3567754Smsmith * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3667754Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3767754Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3867754Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3967754Smsmith * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4067754Smsmith * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4167754Smsmith * POSSIBILITY OF SUCH DAMAGES. 4267754Smsmith */ 4367754Smsmith 4467754Smsmith 4567754Smsmith#include <contrib/dev/acpica/include/acpi.h> 4667754Smsmith#include <contrib/dev/acpica/include/accommon.h> 4767754Smsmith#include <contrib/dev/acpica/include/acdebug.h> 4867754Smsmith#include <contrib/dev/acpica/include/acnamesp.h> 4967754Smsmith 5067754Smsmith#ifdef ACPI_DEBUGGER 5167754Smsmith 5267754Smsmith#define _COMPONENT ACPI_CA_DEBUGGER 5367754Smsmith ACPI_MODULE_NAME ("dbexec") 5467754Smsmith 5567754Smsmith 5667754Smsmithstatic ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo; 5767754Smsmith 5867754Smsmith/* Local prototypes */ 5967754Smsmith 6067754Smsmithstatic ACPI_STATUS 6167754SmsmithAcpiDbExecuteMethod ( 6267754Smsmith ACPI_DB_METHOD_INFO *Info, 6367754Smsmith ACPI_BUFFER *ReturnObj); 6467754Smsmith 6567754Smsmithstatic void 6667754SmsmithAcpiDbExecuteSetup ( 6767754Smsmith ACPI_DB_METHOD_INFO *Info); 6867754Smsmith 6967754Smsmithstatic UINT32 7067754SmsmithAcpiDbGetOutstandingAllocations ( 7167754Smsmith void); 7267754Smsmith 7367754Smsmithstatic void ACPI_SYSTEM_XFACE 7467754SmsmithAcpiDbMethodThread ( 7567754Smsmith void *Context); 7667754Smsmith 7767754Smsmithstatic ACPI_STATUS 7867754SmsmithAcpiDbExecutionWalk ( 7967754Smsmith ACPI_HANDLE ObjHandle, 8067754Smsmith UINT32 NestingLevel, 8167754Smsmith void *Context, 8267754Smsmith void **ReturnValue); 8367754Smsmith 8467754Smsmith 8567754Smsmith/******************************************************************************* 8667754Smsmith * 8767754Smsmith * FUNCTION: AcpiDbDeleteObjects 8867754Smsmith * 8967754Smsmith * PARAMETERS: Count - Count of objects in the list 9067754Smsmith * Objects - Array of ACPI_OBJECTs to be deleted 9167754Smsmith * 9267754Smsmith * RETURN: None 9367754Smsmith * 9467754Smsmith * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested 9567754Smsmith * packages via recursion. 9667754Smsmith * 9767754Smsmith ******************************************************************************/ 9867754Smsmith 9967754Smsmithvoid 10067754SmsmithAcpiDbDeleteObjects ( 10167754Smsmith UINT32 Count, 10267754Smsmith ACPI_OBJECT *Objects) 10367754Smsmith{ 10467754Smsmith UINT32 i; 10567754Smsmith 10667754Smsmith 10767754Smsmith for (i = 0; i < Count; i++) 10867754Smsmith { 10967754Smsmith switch (Objects[i].Type) 11067754Smsmith { 11167754Smsmith case ACPI_TYPE_BUFFER: 11267754Smsmith 11367754Smsmith ACPI_FREE (Objects[i].Buffer.Pointer); 11467754Smsmith break; 11567754Smsmith 11667754Smsmith case ACPI_TYPE_PACKAGE: 11767754Smsmith 11867754Smsmith /* Recursive call to delete package elements */ 11967754Smsmith 12067754Smsmith AcpiDbDeleteObjects (Objects[i].Package.Count, 12167754Smsmith Objects[i].Package.Elements); 12267754Smsmith 12377424Smsmith /* Free the elements array */ 12491116Smsmith 12567754Smsmith ACPI_FREE (Objects[i].Package.Elements); 12667754Smsmith break; 12799679Siwasaki 12867754Smsmith default: 12967754Smsmith 13067754Smsmith break; 13167754Smsmith } 13267754Smsmith } 13367754Smsmith} 13467754Smsmith 13567754Smsmith 13667754Smsmith/******************************************************************************* 13767754Smsmith * 13867754Smsmith * FUNCTION: AcpiDbExecuteMethod 13967754Smsmith * 14067754Smsmith * PARAMETERS: Info - Valid info segment 14167754Smsmith * ReturnObj - Where to put return object 14267754Smsmith * 14367754Smsmith * RETURN: Status 14467754Smsmith * 14591116Smsmith * DESCRIPTION: Execute a control method. 14667754Smsmith * 14767754Smsmith ******************************************************************************/ 14867754Smsmith 14967754Smsmithstatic ACPI_STATUS 15067754SmsmithAcpiDbExecuteMethod ( 15167754Smsmith ACPI_DB_METHOD_INFO *Info, 15267754Smsmith ACPI_BUFFER *ReturnObj) 15367754Smsmith{ 15483174Smsmith ACPI_STATUS Status; 15567754Smsmith ACPI_OBJECT_LIST ParamObjects; 15667754Smsmith ACPI_OBJECT Params[ACPI_DEBUGGER_MAX_ARGS + 1]; 15767754Smsmith UINT32 i; 15867754Smsmith 15967754Smsmith 16067754Smsmith ACPI_FUNCTION_TRACE (DbExecuteMethod); 16167754Smsmith 16267754Smsmith 16367754Smsmith if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel) 16467754Smsmith { 16571867Smsmith AcpiOsPrintf ("Warning: debug output is not enabled!\n"); 16691116Smsmith } 16767754Smsmith 16867754Smsmith ParamObjects.Count = 0; 16967754Smsmith ParamObjects.Pointer = NULL; 17067754Smsmith 17167754Smsmith /* Pass through any command-line arguments */ 17267754Smsmith 17367754Smsmith if (Info->Args && Info->Args[0]) 17467754Smsmith { 17567754Smsmith /* Get arguments passed on the command line */ 17671867Smsmith 17771867Smsmith for (i = 0; (Info->Args[i] && *(Info->Args[i])); i++) 17867754Smsmith { 17967754Smsmith /* Convert input string (token) to an actual ACPI_OBJECT */ 18067754Smsmith 18167754Smsmith Status = AcpiDbConvertToObject (Info->Types[i], 18267754Smsmith Info->Args[i], &Params[i]); 18367754Smsmith if (ACPI_FAILURE (Status)) 18467754Smsmith { 18567754Smsmith ACPI_EXCEPTION ((AE_INFO, Status, 18667754Smsmith "While parsing method arguments")); 18767754Smsmith goto Cleanup; 18867754Smsmith } 18983174Smsmith } 19083174Smsmith 19167754Smsmith ParamObjects.Count = i; 19267754Smsmith ParamObjects.Pointer = Params; 19367754Smsmith } 19467754Smsmith 19567754Smsmith /* Prepare for a return object of arbitrary size */ 19667754Smsmith 19767754Smsmith ReturnObj->Pointer = AcpiGbl_DbBuffer; 19867754Smsmith ReturnObj->Length = ACPI_DEBUG_BUFFER_SIZE; 19967754Smsmith 20067754Smsmith /* Do the actual method execution */ 20167754Smsmith 20267754Smsmith AcpiGbl_MethodExecuting = TRUE; 20367754Smsmith Status = AcpiEvaluateObject (NULL, Info->Pathname, 20467754Smsmith &ParamObjects, ReturnObj); 20567754Smsmith 20667754Smsmith AcpiGbl_CmSingleStep = FALSE; 20767754Smsmith AcpiGbl_MethodExecuting = FALSE; 20867754Smsmith 20967754Smsmith if (ACPI_FAILURE (Status)) 21067754Smsmith { 21167754Smsmith ACPI_EXCEPTION ((AE_INFO, Status, 21267754Smsmith "while executing %s from debugger", Info->Pathname)); 21367754Smsmith 21467754Smsmith if (Status == AE_BUFFER_OVERFLOW) 21567754Smsmith { 21667754Smsmith ACPI_ERROR ((AE_INFO, 21799679Siwasaki "Possible overflow of internal debugger buffer (size 0x%X needed 0x%X)", 21867754Smsmith ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length)); 21967754Smsmith } 22067754Smsmith } 22167754Smsmith 22267754SmsmithCleanup: 22367754Smsmith AcpiDbDeleteObjects (ParamObjects.Count, Params); 22467754Smsmith return_ACPI_STATUS (Status); 22567754Smsmith} 22691116Smsmith 22767754Smsmith 22867754Smsmith/******************************************************************************* 22991116Smsmith * 23067754Smsmith * FUNCTION: AcpiDbExecuteSetup 23167754Smsmith * 23291116Smsmith * PARAMETERS: Info - Valid method info 23367754Smsmith * 23467754Smsmith * RETURN: None 23567754Smsmith * 23667754Smsmith * DESCRIPTION: Setup info segment prior to method execution 23767754Smsmith * 23891116Smsmith ******************************************************************************/ 23967754Smsmith 24067754Smsmithstatic void 24167754SmsmithAcpiDbExecuteSetup ( 24267754Smsmith ACPI_DB_METHOD_INFO *Info) 24367754Smsmith{ 24467754Smsmith 24591116Smsmith /* Catenate the current scope to the supplied name */ 24667754Smsmith 24767754Smsmith Info->Pathname[0] = 0; 24867754Smsmith if ((Info->Name[0] != '\\') && 24967754Smsmith (Info->Name[0] != '/')) 25067754Smsmith { 25167754Smsmith ACPI_STRCAT (Info->Pathname, AcpiGbl_DbScopeBuf); 25282367Smsmith } 25382367Smsmith 25482367Smsmith ACPI_STRCAT (Info->Pathname, Info->Name); 25582367Smsmith AcpiDbPrepNamestring (Info->Pathname); 25682367Smsmith 25782367Smsmith AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 25882367Smsmith AcpiOsPrintf ("Evaluating %s\n", Info->Pathname); 25982367Smsmith 26082367Smsmith if (Info->Flags & EX_SINGLE_STEP) 26182367Smsmith { 26282367Smsmith AcpiGbl_CmSingleStep = TRUE; 26382367Smsmith AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 26482367Smsmith } 26599679Siwasaki 26699679Siwasaki else 26782367Smsmith { 26882367Smsmith /* No single step, allow redirection to a file */ 26982367Smsmith 27082367Smsmith AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 27191116Smsmith } 27282367Smsmith} 27391116Smsmith 27482367Smsmith 27582367Smsmith#ifdef ACPI_DBG_TRACK_ALLOCATIONS 27683174SmsmithUINT32 27783174SmsmithAcpiDbGetCacheInfo ( 27882367Smsmith ACPI_MEMORY_LIST *Cache) 27982367Smsmith{ 28082367Smsmith 28182367Smsmith return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth); 28282367Smsmith} 28382367Smsmith#endif 28482367Smsmith 28582367Smsmith/******************************************************************************* 28682367Smsmith * 28782367Smsmith * FUNCTION: AcpiDbGetOutstandingAllocations 28867754Smsmith * 28967754Smsmith * PARAMETERS: None 29067754Smsmith * 29167754Smsmith * RETURN: Current global allocation count minus cache entries 29267754Smsmith * 29367754Smsmith * DESCRIPTION: Determine the current number of "outstanding" allocations -- 29467754Smsmith * those allocations that have not been freed and also are not 29567754Smsmith * in one of the various object caches. 29667754Smsmith * 29767754Smsmith ******************************************************************************/ 29867754Smsmith 29967754Smsmithstatic UINT32 30067754SmsmithAcpiDbGetOutstandingAllocations ( 30167754Smsmith void) 30267754Smsmith{ 30367754Smsmith UINT32 Outstanding = 0; 30467754Smsmith 30567754Smsmith#ifdef ACPI_DBG_TRACK_ALLOCATIONS 30667754Smsmith 30767754Smsmith Outstanding += AcpiDbGetCacheInfo (AcpiGbl_StateCache); 30869450Smsmith Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeCache); 30969450Smsmith Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeExtCache); 31069450Smsmith Outstanding += AcpiDbGetCacheInfo (AcpiGbl_OperandCache); 31169450Smsmith#endif 31267754Smsmith 31367754Smsmith return (Outstanding); 31467754Smsmith} 31567754Smsmith 31667754Smsmith 31767754Smsmith/******************************************************************************* 31882367Smsmith * 31969450Smsmith * FUNCTION: AcpiDbExecutionWalk 32067754Smsmith * 32183174Smsmith * PARAMETERS: WALK_CALLBACK 32283174Smsmith * 32383174Smsmith * RETURN: Status 32467754Smsmith * 325100966Siwasaki * DESCRIPTION: Execute a control method. Name is relative to the current 326100966Siwasaki * scope. 327100966Siwasaki * 32883174Smsmith ******************************************************************************/ 32983174Smsmith 33067754Smsmithstatic ACPI_STATUS 33182367SmsmithAcpiDbExecutionWalk ( 33282367Smsmith ACPI_HANDLE ObjHandle, 33382367Smsmith UINT32 NestingLevel, 33482367Smsmith void *Context, 33582367Smsmith void **ReturnValue) 33667754Smsmith{ 33782367Smsmith ACPI_OPERAND_OBJECT *ObjDesc; 33869450Smsmith ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 33969450Smsmith ACPI_BUFFER ReturnObj; 34067754Smsmith ACPI_STATUS Status; 34167754Smsmith 34282367Smsmith 34367754Smsmith ObjDesc = AcpiNsGetAttachedObject (Node); 34491116Smsmith if (ObjDesc->Method.ParamCount) 34567754Smsmith { 34667754Smsmith return (AE_OK); 34767754Smsmith } 34882367Smsmith 34982367Smsmith ReturnObj.Pointer = NULL; 35067754Smsmith ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 35169450Smsmith 35267754Smsmith AcpiNsPrintNodePathname (Node, "Evaluating"); 35367754Smsmith 35467754Smsmith /* Do the actual method execution */ 35583174Smsmith 35683174Smsmith AcpiOsPrintf ("\n"); 35767754Smsmith AcpiGbl_MethodExecuting = TRUE; 35867754Smsmith 35967754Smsmith Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj); 36067754Smsmith 36167754Smsmith AcpiOsPrintf ("Evaluation of [%4.4s] returned %s\n", AcpiUtGetNodeName (Node), 36267754Smsmith AcpiFormatException (Status)); 36367754Smsmith AcpiGbl_MethodExecuting = FALSE; 36467754Smsmith 36577424Smsmith return (AE_OK); 36683174Smsmith} 36767754Smsmith 36867754Smsmith 369100966Siwasaki/******************************************************************************* 370100966Siwasaki * 371100966Siwasaki * FUNCTION: AcpiDbExecute 372100966Siwasaki * 373100966Siwasaki * PARAMETERS: Name - Name of method to execute 37467754Smsmith * Args - Parameters to the method 37567754Smsmith * Flags - single step/no single step 37691116Smsmith * 37767754Smsmith * RETURN: None 37867754Smsmith * 37967754Smsmith * DESCRIPTION: Execute a control method. Name is relative to the current 38067754Smsmith * scope. 38167754Smsmith * 38267754Smsmith ******************************************************************************/ 38367754Smsmith 38467754Smsmithvoid 38567754SmsmithAcpiDbExecute ( 38667754Smsmith char *Name, 38767754Smsmith char **Args, 38867754Smsmith ACPI_OBJECT_TYPE *Types, 38967754Smsmith UINT32 Flags) 39067754Smsmith{ 39167754Smsmith ACPI_STATUS Status; 39267754Smsmith ACPI_BUFFER ReturnObj; 39392388Smsmith char *NameString; 39467754Smsmith 39567754Smsmith 39667754Smsmith#ifdef ACPI_DEBUG_OUTPUT 39767754Smsmith UINT32 PreviousAllocations; 39891116Smsmith UINT32 Allocations; 39967754Smsmith 40067754Smsmith 40167754Smsmith /* Memory allocation tracking */ 40267754Smsmith 40367754Smsmith PreviousAllocations = AcpiDbGetOutstandingAllocations (); 40467754Smsmith#endif 40567754Smsmith 40667754Smsmith if (*Name == '*') 40767754Smsmith { 40867754Smsmith (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT, 40967754Smsmith ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL); 41077424Smsmith return; 41177424Smsmith } 41267754Smsmith else 41367754Smsmith { 41467754Smsmith NameString = ACPI_ALLOCATE (ACPI_STRLEN (Name) + 1); 41567754Smsmith if (!NameString) 41667754Smsmith { 41767754Smsmith return; 41867754Smsmith } 41999679Siwasaki 42099679Siwasaki ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 42199679Siwasaki 42299679Siwasaki ACPI_STRCPY (NameString, Name); 42399679Siwasaki AcpiUtStrupr (NameString); 42467754Smsmith AcpiGbl_DbMethodInfo.Name = NameString; 42567754Smsmith AcpiGbl_DbMethodInfo.Args = Args; 42667754Smsmith AcpiGbl_DbMethodInfo.Types = Types; 42767754Smsmith AcpiGbl_DbMethodInfo.Flags = Flags; 42867754Smsmith 42967754Smsmith ReturnObj.Pointer = NULL; 43067754Smsmith ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 43167754Smsmith 43267754Smsmith AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 43367754Smsmith 43467754Smsmith /* Get the NS node, determines existence also */ 43567754Smsmith 43667754Smsmith Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname, 43767754Smsmith &AcpiGbl_DbMethodInfo.Method); 43867754Smsmith if (ACPI_SUCCESS (Status)) 43967754Smsmith { 44067754Smsmith Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj); 44167754Smsmith } 44267754Smsmith ACPI_FREE (NameString); 44367754Smsmith } 44467754Smsmith 44567754Smsmith /* 44667754Smsmith * Allow any handlers in separate threads to complete. 44767754Smsmith * (Such as Notify handlers invoked from AML executed above). 44867754Smsmith */ 44967754Smsmith AcpiOsSleep ((UINT64) 10); 45067754Smsmith 45167754Smsmith#ifdef ACPI_DEBUG_OUTPUT 45267754Smsmith 45367754Smsmith /* Memory allocation tracking */ 45467754Smsmith 45567754Smsmith Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations; 45691116Smsmith 45791116Smsmith AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 45867754Smsmith 45967754Smsmith if (Allocations > 0) 46067754Smsmith { 46169746Smsmith AcpiOsPrintf ("0x%X Outstanding allocations after evaluation of %s\n", 46267754Smsmith Allocations, AcpiGbl_DbMethodInfo.Pathname); 46367754Smsmith } 46467754Smsmith#endif 46567754Smsmith 46667754Smsmith if (ACPI_FAILURE (Status)) 46767754Smsmith { 46867754Smsmith AcpiOsPrintf ("Evaluation of %s failed with status %s\n", 46967754Smsmith AcpiGbl_DbMethodInfo.Pathname, AcpiFormatException (Status)); 47080062Smsmith } 47167754Smsmith else 47267754Smsmith { 47367754Smsmith /* Display a return object, if any */ 47467754Smsmith 47567754Smsmith if (ReturnObj.Length) 47683174Smsmith { 47783174Smsmith AcpiOsPrintf ( 47883174Smsmith "Evaluation of %s returned object %p, external buffer length %X\n", 47983174Smsmith AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer, 48083174Smsmith (UINT32) ReturnObj.Length); 48167754Smsmith AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 48283174Smsmith 48367754Smsmith /* Dump a _PLD buffer if present */ 48467754Smsmith 48567754Smsmith if (ACPI_COMPARE_NAME ((ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, 48669746Smsmith AcpiGbl_DbMethodInfo.Method)->Name.Ascii), METHOD_NAME__PLD)) 48767754Smsmith { 48867754Smsmith AcpiDbDumpPldBuffer (ReturnObj.Pointer); 48967754Smsmith } 49099679Siwasaki } 49199679Siwasaki else 49299679Siwasaki { 49399679Siwasaki AcpiOsPrintf ("No object was returned from evaluation of %s\n", 49499679Siwasaki AcpiGbl_DbMethodInfo.Pathname); 49567754Smsmith } 49667754Smsmith } 49767754Smsmith 49867754Smsmith AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 49967754Smsmith} 50067754Smsmith 50167754Smsmith 50267754Smsmith/******************************************************************************* 50367754Smsmith * 50467754Smsmith * FUNCTION: AcpiDbMethodThread 50567754Smsmith * 50667754Smsmith * PARAMETERS: Context - Execution info segment 50767754Smsmith * 50899679Siwasaki * RETURN: None 50967754Smsmith * 51091116Smsmith * DESCRIPTION: Debugger execute thread. Waits for a command line, then 51169746Smsmith * simply dispatches it. 51291116Smsmith * 51367754Smsmith ******************************************************************************/ 51467754Smsmith 51567754Smsmithstatic void ACPI_SYSTEM_XFACE 51667754SmsmithAcpiDbMethodThread ( 51767754Smsmith void *Context) 51867754Smsmith{ 519 ACPI_STATUS Status; 520 ACPI_DB_METHOD_INFO *Info = Context; 521 ACPI_DB_METHOD_INFO LocalInfo; 522 UINT32 i; 523 UINT8 Allow; 524 ACPI_BUFFER ReturnObj; 525 526 527 /* 528 * AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments. 529 * Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads 530 * concurrently. 531 * 532 * Note: The arguments we are passing are used by the ASL test suite 533 * (aslts). Do not change them without updating the tests. 534 */ 535 (void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER); 536 537 if (Info->InitArgs) 538 { 539 AcpiDbUint32ToHexString (Info->NumCreated, Info->IndexOfThreadStr); 540 AcpiDbUint32ToHexString ((UINT32) AcpiOsGetThreadId (), Info->IdOfThreadStr); 541 } 542 543 if (Info->Threads && (Info->NumCreated < Info->NumThreads)) 544 { 545 Info->Threads[Info->NumCreated++] = AcpiOsGetThreadId(); 546 } 547 548 LocalInfo = *Info; 549 LocalInfo.Args = LocalInfo.Arguments; 550 LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr; 551 LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr; 552 LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr; 553 LocalInfo.Arguments[3] = NULL; 554 555 LocalInfo.Types = LocalInfo.ArgTypes; 556 557 (void) AcpiOsSignalSemaphore (Info->InfoGate, 1); 558 559 for (i = 0; i < Info->NumLoops; i++) 560 { 561 Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj); 562 if (ACPI_FAILURE (Status)) 563 { 564 AcpiOsPrintf ("%s During evaluation of %s at iteration %X\n", 565 AcpiFormatException (Status), Info->Pathname, i); 566 if (Status == AE_ABORT_METHOD) 567 { 568 break; 569 } 570 } 571 572#if 0 573 if ((i % 100) == 0) 574 { 575 AcpiOsPrintf ("%u loops, Thread 0x%x\n", i, AcpiOsGetThreadId ()); 576 } 577 578 if (ReturnObj.Length) 579 { 580 AcpiOsPrintf ("Evaluation of %s returned object %p Buflen %X\n", 581 Info->Pathname, ReturnObj.Pointer, (UINT32) ReturnObj.Length); 582 AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 583 } 584#endif 585 } 586 587 /* Signal our completion */ 588 589 Allow = 0; 590 (void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate, 1, ACPI_WAIT_FOREVER); 591 Info->NumCompleted++; 592 593 if (Info->NumCompleted == Info->NumThreads) 594 { 595 /* Do signal for main thread once only */ 596 Allow = 1; 597 } 598 599 (void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1); 600 601 if (Allow) 602 { 603 Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1); 604 if (ACPI_FAILURE (Status)) 605 { 606 AcpiOsPrintf ("Could not signal debugger thread sync semaphore, %s\n", 607 AcpiFormatException (Status)); 608 } 609 } 610} 611 612 613/******************************************************************************* 614 * 615 * FUNCTION: AcpiDbCreateExecutionThreads 616 * 617 * PARAMETERS: NumThreadsArg - Number of threads to create 618 * NumLoopsArg - Loop count for the thread(s) 619 * MethodNameArg - Control method to execute 620 * 621 * RETURN: None 622 * 623 * DESCRIPTION: Create threads to execute method(s) 624 * 625 ******************************************************************************/ 626 627void 628AcpiDbCreateExecutionThreads ( 629 char *NumThreadsArg, 630 char *NumLoopsArg, 631 char *MethodNameArg) 632{ 633 ACPI_STATUS Status; 634 UINT32 NumThreads; 635 UINT32 NumLoops; 636 UINT32 i; 637 UINT32 Size; 638 ACPI_MUTEX MainThreadGate; 639 ACPI_MUTEX ThreadCompleteGate; 640 ACPI_MUTEX InfoGate; 641 642 643 /* Get the arguments */ 644 645 NumThreads = ACPI_STRTOUL (NumThreadsArg, NULL, 0); 646 NumLoops = ACPI_STRTOUL (NumLoopsArg, NULL, 0); 647 648 if (!NumThreads || !NumLoops) 649 { 650 AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n", 651 NumThreads, NumLoops); 652 return; 653 } 654 655 /* 656 * Create the semaphore for synchronization of 657 * the created threads with the main thread. 658 */ 659 Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate); 660 if (ACPI_FAILURE (Status)) 661 { 662 AcpiOsPrintf ("Could not create semaphore for synchronization with the main thread, %s\n", 663 AcpiFormatException (Status)); 664 return; 665 } 666 667 /* 668 * Create the semaphore for synchronization 669 * between the created threads. 670 */ 671 Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate); 672 if (ACPI_FAILURE (Status)) 673 { 674 AcpiOsPrintf ("Could not create semaphore for synchronization between the created threads, %s\n", 675 AcpiFormatException (Status)); 676 (void) AcpiOsDeleteSemaphore (MainThreadGate); 677 return; 678 } 679 680 Status = AcpiOsCreateSemaphore (1, 1, &InfoGate); 681 if (ACPI_FAILURE (Status)) 682 { 683 AcpiOsPrintf ("Could not create semaphore for synchronization of AcpiGbl_DbMethodInfo, %s\n", 684 AcpiFormatException (Status)); 685 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 686 (void) AcpiOsDeleteSemaphore (MainThreadGate); 687 return; 688 } 689 690 ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 691 692 /* Array to store IDs of threads */ 693 694 AcpiGbl_DbMethodInfo.NumThreads = NumThreads; 695 Size = sizeof (ACPI_THREAD_ID) * AcpiGbl_DbMethodInfo.NumThreads; 696 AcpiGbl_DbMethodInfo.Threads = AcpiOsAllocate (Size); 697 if (AcpiGbl_DbMethodInfo.Threads == NULL) 698 { 699 AcpiOsPrintf ("No memory for thread IDs array\n"); 700 (void) AcpiOsDeleteSemaphore (MainThreadGate); 701 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 702 (void) AcpiOsDeleteSemaphore (InfoGate); 703 return; 704 } 705 ACPI_MEMSET (AcpiGbl_DbMethodInfo.Threads, 0, Size); 706 707 /* Setup the context to be passed to each thread */ 708 709 AcpiGbl_DbMethodInfo.Name = MethodNameArg; 710 AcpiGbl_DbMethodInfo.Flags = 0; 711 AcpiGbl_DbMethodInfo.NumLoops = NumLoops; 712 AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate; 713 AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate; 714 AcpiGbl_DbMethodInfo.InfoGate = InfoGate; 715 716 /* Init arguments to be passed to method */ 717 718 AcpiGbl_DbMethodInfo.InitArgs = 1; 719 AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments; 720 AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr; 721 AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr; 722 AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr; 723 AcpiGbl_DbMethodInfo.Arguments[3] = NULL; 724 725 AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes; 726 AcpiGbl_DbMethodInfo.ArgTypes[0] = ACPI_TYPE_INTEGER; 727 AcpiGbl_DbMethodInfo.ArgTypes[1] = ACPI_TYPE_INTEGER; 728 AcpiGbl_DbMethodInfo.ArgTypes[2] = ACPI_TYPE_INTEGER; 729 730 AcpiDbUint32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr); 731 732 AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 733 734 /* Get the NS node, determines existence also */ 735 736 Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname, 737 &AcpiGbl_DbMethodInfo.Method); 738 if (ACPI_FAILURE (Status)) 739 { 740 AcpiOsPrintf ("%s Could not get handle for %s\n", 741 AcpiFormatException (Status), AcpiGbl_DbMethodInfo.Pathname); 742 goto CleanupAndExit; 743 } 744 745 /* Create the threads */ 746 747 AcpiOsPrintf ("Creating %X threads to execute %X times each\n", 748 NumThreads, NumLoops); 749 750 for (i = 0; i < (NumThreads); i++) 751 { 752 Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbMethodThread, 753 &AcpiGbl_DbMethodInfo); 754 if (ACPI_FAILURE (Status)) 755 { 756 break; 757 } 758 } 759 760 /* Wait for all threads to complete */ 761 762 (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER); 763 764 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 765 AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads); 766 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 767 768CleanupAndExit: 769 770 /* Cleanup and exit */ 771 772 (void) AcpiOsDeleteSemaphore (MainThreadGate); 773 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 774 (void) AcpiOsDeleteSemaphore (InfoGate); 775 776 AcpiOsFree (AcpiGbl_DbMethodInfo.Threads); 777 AcpiGbl_DbMethodInfo.Threads = NULL; 778} 779 780#endif /* ACPI_DEBUGGER */ 781