Path: blob/main/sys/contrib/dev/acpica/components/debugger/dbexec.c
48406 views
/*******************************************************************************1*2* Module Name: dbexec - debugger control method execution3*4******************************************************************************/56/******************************************************************************7*8* 1. Copyright Notice9*10* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.11* All rights reserved.12*13* 2. License14*15* 2.1. This is your license from Intel Corp. under its intellectual property16* rights. You may have additional license terms from the party that provided17* you this software, covering your right to use that party's intellectual18* property rights.19*20* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a21* copy of the source code appearing in this file ("Covered Code") an22* irrevocable, perpetual, worldwide license under Intel's copyrights in the23* base code distributed originally by Intel ("Original Intel Code") to copy,24* make derivatives, distribute, use and display any portion of the Covered25* Code in any form, with the right to sublicense such rights; and26*27* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent28* license (with the right to sublicense), under only those claims of Intel29* patents that are infringed by the Original Intel Code, to make, use, sell,30* offer to sell, and import the Covered Code and derivative works thereof31* solely to the minimum extent necessary to exercise the above copyright32* license, and in no event shall the patent license extend to any additions33* to or modifications of the Original Intel Code. No other license or right34* is granted directly or by implication, estoppel or otherwise;35*36* The above copyright and patent license is granted only if the following37* conditions are met:38*39* 3. Conditions40*41* 3.1. Redistribution of Source with Rights to Further Distribute Source.42* Redistribution of source code of any substantial portion of the Covered43* Code or modification with rights to further distribute source must include44* the above Copyright Notice, the above License, this list of Conditions,45* and the following Disclaimer and Export Compliance provision. In addition,46* Licensee must cause all Covered Code to which Licensee contributes to47* contain a file documenting the changes Licensee made to create that Covered48* Code and the date of any change. Licensee must include in that file the49* documentation of any changes made by any predecessor Licensee. Licensee50* must include a prominent statement that the modification is derived,51* directly or indirectly, from Original Intel Code.52*53* 3.2. Redistribution of Source with no Rights to Further Distribute Source.54* Redistribution of source code of any substantial portion of the Covered55* Code or modification without rights to further distribute source must56* include the following Disclaimer and Export Compliance provision in the57* documentation and/or other materials provided with distribution. In58* addition, Licensee may not authorize further sublicense of source of any59* portion of the Covered Code, and must include terms to the effect that the60* license from Licensee to its licensee is limited to the intellectual61* property embodied in the software Licensee provides to its licensee, and62* not to intellectual property embodied in modifications its licensee may63* make.64*65* 3.3. Redistribution of Executable. Redistribution in executable form of any66* substantial portion of the Covered Code or modification must reproduce the67* above Copyright Notice, and the following Disclaimer and Export Compliance68* provision in the documentation and/or other materials provided with the69* distribution.70*71* 3.4. Intel retains all right, title, and interest in and to the Original72* Intel Code.73*74* 3.5. Neither the name Intel nor any other trademark owned or controlled by75* Intel shall be used in advertising or otherwise to promote the sale, use or76* other dealings in products derived from or relating to the Covered Code77* without prior written authorization from Intel.78*79* 4. Disclaimer and Export Compliance80*81* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED82* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE83* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,84* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY85* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY86* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A87* PARTICULAR PURPOSE.88*89* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES90* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR91* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,92* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY93* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL94* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS95* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY96* LIMITED REMEDY.97*98* 4.3. Licensee shall not export, either directly or indirectly, any of this99* software or system incorporating such software without first obtaining any100* required license or other approval from the U. S. Department of Commerce or101* any other agency or department of the United States Government. In the102* event Licensee exports any such software from the United States or103* re-exports any such software from a foreign destination, Licensee shall104* ensure that the distribution and export/re-export of the software is in105* compliance with all laws, regulations, orders, or other restrictions of the106* U.S. Export Administration Regulations. Licensee agrees that neither it nor107* any of its subsidiaries will export/re-export any technical data, process,108* software, or service, directly or indirectly, to any country for which the109* United States government or any agency thereof requires an export license,110* other governmental approval, or letter of assurance, without first obtaining111* such license, approval or letter.112*113*****************************************************************************114*115* Alternatively, you may choose to be licensed under the terms of the116* following license:117*118* Redistribution and use in source and binary forms, with or without119* modification, are permitted provided that the following conditions120* are met:121* 1. Redistributions of source code must retain the above copyright122* notice, this list of conditions, and the following disclaimer,123* without modification.124* 2. Redistributions in binary form must reproduce at minimum a disclaimer125* substantially similar to the "NO WARRANTY" disclaimer below126* ("Disclaimer") and any redistribution must be conditioned upon127* including a substantially similar Disclaimer requirement for further128* binary redistribution.129* 3. Neither the names of the above-listed copyright holders nor the names130* of any contributors may be used to endorse or promote products derived131* from this software without specific prior written permission.132*133* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS134* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT135* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR136* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT137* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,138* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT139* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,140* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY141* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT142* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE143* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.144*145* Alternatively, you may choose to be licensed under the terms of the146* GNU General Public License ("GPL") version 2 as published by the Free147* Software Foundation.148*149*****************************************************************************/150151#include <contrib/dev/acpica/include/acpi.h>152#include <contrib/dev/acpica/include/accommon.h>153#include <contrib/dev/acpica/include/acdebug.h>154#include <contrib/dev/acpica/include/acnamesp.h>155156157#define _COMPONENT ACPI_CA_DEBUGGER158ACPI_MODULE_NAME ("dbexec")159160161static ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo;162163/* Local prototypes */164165static ACPI_STATUS166AcpiDbExecuteMethod (167ACPI_DB_METHOD_INFO *Info,168ACPI_BUFFER *ReturnObj);169170static ACPI_STATUS171AcpiDbExecuteSetup (172ACPI_DB_METHOD_INFO *Info);173174static UINT32175AcpiDbGetOutstandingAllocations (176void);177178static void ACPI_SYSTEM_XFACE179AcpiDbMethodThread (180void *Context);181182static ACPI_STATUS183AcpiDbExecutionWalk (184ACPI_HANDLE ObjHandle,185UINT32 NestingLevel,186void *Context,187void **ReturnValue);188189static void ACPI_SYSTEM_XFACE190AcpiDbSingleExecutionThread (191void *Context);192193194/*******************************************************************************195*196* FUNCTION: AcpiDbDeleteObjects197*198* PARAMETERS: Count - Count of objects in the list199* Objects - Array of ACPI_OBJECTs to be deleted200*201* RETURN: None202*203* DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested204* packages via recursion.205*206******************************************************************************/207208void209AcpiDbDeleteObjects (210UINT32 Count,211ACPI_OBJECT *Objects)212{213UINT32 i;214215216for (i = 0; i < Count; i++)217{218switch (Objects[i].Type)219{220case ACPI_TYPE_BUFFER:221222ACPI_FREE (Objects[i].Buffer.Pointer);223break;224225case ACPI_TYPE_PACKAGE:226227/* Recursive call to delete package elements */228229AcpiDbDeleteObjects (Objects[i].Package.Count,230Objects[i].Package.Elements);231232/* Free the elements array */233234ACPI_FREE (Objects[i].Package.Elements);235break;236237default:238239break;240}241}242}243244245/*******************************************************************************246*247* FUNCTION: AcpiDbExecuteMethod248*249* PARAMETERS: Info - Valid info segment250* ReturnObj - Where to put return object251*252* RETURN: Status253*254* DESCRIPTION: Execute a control method. Used to evaluate objects via the255* "EXECUTE" or "EVALUATE" commands.256*257******************************************************************************/258259static ACPI_STATUS260AcpiDbExecuteMethod (261ACPI_DB_METHOD_INFO *Info,262ACPI_BUFFER *ReturnObj)263{264ACPI_STATUS Status;265ACPI_OBJECT_LIST ParamObjects;266ACPI_OBJECT Params[ACPI_DEBUGGER_MAX_ARGS + 1];267UINT32 i;268269270ACPI_FUNCTION_TRACE (DbExecuteMethod);271272273if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel)274{275AcpiOsPrintf ("Warning: debug output is not enabled!\n");276}277278ParamObjects.Count = 0;279ParamObjects.Pointer = NULL;280281/* Pass through any command-line arguments */282283if (Info->Args && Info->Args[0])284{285/* Get arguments passed on the command line */286287for (i = 0; (Info->Args[i] && *(Info->Args[i])); i++)288{289/* Convert input string (token) to an actual ACPI_OBJECT */290291Status = AcpiDbConvertToObject (Info->Types[i],292Info->Args[i], &Params[i]);293if (ACPI_FAILURE (Status))294{295ACPI_EXCEPTION ((AE_INFO, Status,296"While parsing method arguments"));297goto Cleanup;298}299}300301ParamObjects.Count = i;302ParamObjects.Pointer = Params;303}304305/* Prepare for a return object of arbitrary size */306307ReturnObj->Pointer = AcpiGbl_DbBuffer;308ReturnObj->Length = ACPI_DEBUG_BUFFER_SIZE;309310/* Do the actual method execution */311312AcpiGbl_MethodExecuting = TRUE;313Status = AcpiEvaluateObject (NULL, Info->Pathname,314&ParamObjects, ReturnObj);315316AcpiGbl_CmSingleStep = FALSE;317AcpiGbl_MethodExecuting = FALSE;318319if (ACPI_FAILURE (Status))320{321if ((Status == AE_ABORT_METHOD) || AcpiGbl_AbortMethod)322{323/* Clear the abort and fall back to the debugger prompt */324325ACPI_EXCEPTION ((AE_INFO, Status,326"Aborting top-level method"));327328AcpiGbl_AbortMethod = FALSE;329Status = AE_OK;330goto Cleanup;331}332333ACPI_EXCEPTION ((AE_INFO, Status,334"while executing %s from AML Debugger", Info->Pathname));335336if (Status == AE_BUFFER_OVERFLOW)337{338ACPI_ERROR ((AE_INFO,339"Possible buffer overflow within AML Debugger "340"buffer (size 0x%X needed 0x%X)",341ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length));342}343}344345Cleanup:346AcpiDbDeleteObjects (ParamObjects.Count, Params);347return_ACPI_STATUS (Status);348}349350351/*******************************************************************************352*353* FUNCTION: AcpiDbExecuteSetup354*355* PARAMETERS: Info - Valid method info356*357* RETURN: None358*359* DESCRIPTION: Setup info segment prior to method execution360*361******************************************************************************/362363static ACPI_STATUS364AcpiDbExecuteSetup (365ACPI_DB_METHOD_INFO *Info)366{367ACPI_STATUS Status;368369370ACPI_FUNCTION_NAME (DbExecuteSetup);371372373/* Concatenate the current scope to the supplied name */374375Info->Pathname[0] = 0;376if ((Info->Name[0] != '\\') &&377(Info->Name[0] != '/'))378{379if (AcpiUtSafeStrcat (Info->Pathname, sizeof (Info->Pathname),380AcpiGbl_DbScopeBuf))381{382Status = AE_BUFFER_OVERFLOW;383goto ErrorExit;384}385}386387if (AcpiUtSafeStrcat (Info->Pathname, sizeof (Info->Pathname),388Info->Name))389{390Status = AE_BUFFER_OVERFLOW;391goto ErrorExit;392}393394AcpiDbPrepNamestring (Info->Pathname);395396AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);397AcpiOsPrintf ("Evaluating %s\n", Info->Pathname);398399if (Info->Flags & EX_SINGLE_STEP)400{401AcpiGbl_CmSingleStep = TRUE;402AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);403}404405else406{407/* No single step, allow redirection to a file */408409AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);410}411412return (AE_OK);413414ErrorExit:415416ACPI_EXCEPTION ((AE_INFO, Status, "During setup for method execution"));417return (Status);418}419420421#ifdef ACPI_DBG_TRACK_ALLOCATIONS422UINT32423AcpiDbGetCacheInfo (424ACPI_MEMORY_LIST *Cache)425{426427return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth);428}429#endif430431/*******************************************************************************432*433* FUNCTION: AcpiDbGetOutstandingAllocations434*435* PARAMETERS: None436*437* RETURN: Current global allocation count minus cache entries438*439* DESCRIPTION: Determine the current number of "outstanding" allocations --440* those allocations that have not been freed and also are not441* in one of the various object caches.442*443******************************************************************************/444445static UINT32446AcpiDbGetOutstandingAllocations (447void)448{449UINT32 Outstanding = 0;450451#ifdef ACPI_DBG_TRACK_ALLOCATIONS452453Outstanding += AcpiDbGetCacheInfo (AcpiGbl_StateCache);454Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeCache);455Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeExtCache);456Outstanding += AcpiDbGetCacheInfo (AcpiGbl_OperandCache);457#endif458459return (Outstanding);460}461462463/*******************************************************************************464*465* FUNCTION: AcpiDbExecutionWalk466*467* PARAMETERS: WALK_CALLBACK468*469* RETURN: Status470*471* DESCRIPTION: Execute a control method. Name is relative to the current472* scope.473*474******************************************************************************/475476static ACPI_STATUS477AcpiDbExecutionWalk (478ACPI_HANDLE ObjHandle,479UINT32 NestingLevel,480void *Context,481void **ReturnValue)482{483ACPI_OPERAND_OBJECT *ObjDesc;484ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;485ACPI_BUFFER ReturnObj;486ACPI_STATUS Status;487488489ObjDesc = AcpiNsGetAttachedObject (Node);490if (ObjDesc->Method.ParamCount)491{492return (AE_OK);493}494495ReturnObj.Pointer = NULL;496ReturnObj.Length = ACPI_ALLOCATE_BUFFER;497498AcpiNsPrintNodePathname (Node, "Evaluating");499500/* Do the actual method execution */501502AcpiOsPrintf ("\n");503AcpiGbl_MethodExecuting = TRUE;504505Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj);506507AcpiGbl_MethodExecuting = FALSE;508509AcpiOsPrintf ("Evaluation of [%4.4s] returned %s\n",510AcpiUtGetNodeName (Node),511AcpiFormatException (Status));512513return (AE_OK);514}515516517/*******************************************************************************518*519* FUNCTION: AcpiDbExecute520*521* PARAMETERS: Name - Name of method to execute522* Args - Parameters to the method523* Types -524* Flags - single step/no single step525*526* RETURN: None527*528* DESCRIPTION: Execute a control method. Name is relative to the current529* scope. Function used for the "EXECUTE", "EVALUATE", and530* "ALL" commands531*532******************************************************************************/533534void535AcpiDbExecute (536char *Name,537char **Args,538ACPI_OBJECT_TYPE *Types,539UINT32 Flags)540{541ACPI_STATUS Status;542ACPI_BUFFER ReturnObj;543char *NameString;544545#ifdef ACPI_DEBUG_OUTPUT546UINT32 PreviousAllocations;547UINT32 Allocations;548#endif549550551/*552* Allow one execution to be performed by debugger or single step553* execution will be dead locked by the interpreter mutexes.554*/555if (AcpiGbl_MethodExecuting)556{557AcpiOsPrintf ("Only one debugger execution is allowed.\n");558return;559}560561#ifdef ACPI_DEBUG_OUTPUT562/* Memory allocation tracking */563564PreviousAllocations = AcpiDbGetOutstandingAllocations ();565#endif566567if (*Name == '*')568{569(void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT,570ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL);571return;572}573574if ((Flags & EX_ALL) && (strlen (Name) > 4))575{576AcpiOsPrintf ("Input name (%s) must be a 4-char NameSeg\n", Name);577return;578}579580NameString = ACPI_ALLOCATE (strlen (Name) + 1);581if (!NameString)582{583return;584}585586memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO));587strcpy (NameString, Name);588AcpiUtStrupr (NameString);589590/* Subcommand to Execute all predefined names in the namespace */591592if (!strncmp (NameString, "PREDEF", 6))593{594AcpiDbEvaluatePredefinedNames ();595ACPI_FREE (NameString);596return;597}598599/* Command (ALL <nameseg>) to execute all methods of a particular name */600601else if (Flags & EX_ALL)602{603AcpiGbl_DbMethodInfo.Name = NameString;604ReturnObj.Pointer = NULL;605ReturnObj.Length = ACPI_ALLOCATE_BUFFER;606AcpiDbEvaluateAll (NameString);607ACPI_FREE (NameString);608return;609}610else611{612AcpiGbl_DbMethodInfo.Name = NameString;613AcpiGbl_DbMethodInfo.Args = Args;614AcpiGbl_DbMethodInfo.Types = Types;615AcpiGbl_DbMethodInfo.Flags = Flags;616617ReturnObj.Pointer = NULL;618ReturnObj.Length = ACPI_ALLOCATE_BUFFER;619}620621Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);622if (ACPI_FAILURE (Status))623{624ACPI_FREE (NameString);625return;626}627628/* Get the NS node, determines existence also */629630Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname,631&AcpiGbl_DbMethodInfo.Method);632if (ACPI_SUCCESS (Status))633{634Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo,635&ReturnObj);636}637ACPI_FREE (NameString);638639/*640* Allow any handlers in separate threads to complete.641* (Such as Notify handlers invoked from AML executed above).642*/643AcpiOsSleep ((UINT64) 10);644645#ifdef ACPI_DEBUG_OUTPUT646647/* Memory allocation tracking */648649Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations;650651AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);652653if (Allocations > 0)654{655AcpiOsPrintf (656"0x%X Outstanding allocations after evaluation of %s\n",657Allocations, AcpiGbl_DbMethodInfo.Pathname);658}659#endif660661if (ACPI_FAILURE (Status))662{663AcpiOsPrintf ("Evaluation of %s failed with status %s\n",664AcpiGbl_DbMethodInfo.Pathname,665AcpiFormatException (Status));666}667else668{669/* Display a return object, if any */670671if (ReturnObj.Length)672{673AcpiOsPrintf (674"Evaluation of %s returned object %p, "675"external buffer length %X\n",676AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer,677(UINT32) ReturnObj.Length);678679AcpiDbDumpExternalObject (ReturnObj.Pointer, 1);680AcpiOsPrintf ("\n");681682/* Dump a _PLD buffer if present */683684if (ACPI_COMPARE_NAMESEG ((ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,685AcpiGbl_DbMethodInfo.Method)->Name.Ascii),686METHOD_NAME__PLD))687{688AcpiDbDumpPldBuffer (ReturnObj.Pointer);689}690}691else692{693AcpiOsPrintf ("No object was returned from evaluation of %s\n",694AcpiGbl_DbMethodInfo.Pathname);695}696}697698AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);699}700701702/*******************************************************************************703*704* FUNCTION: AcpiDbMethodThread705*706* PARAMETERS: Context - Execution info segment707*708* RETURN: None709*710* DESCRIPTION: Debugger execute thread. Waits for a command line, then711* simply dispatches it.712*713******************************************************************************/714715static void ACPI_SYSTEM_XFACE716AcpiDbMethodThread (717void *Context)718{719ACPI_STATUS Status;720ACPI_DB_METHOD_INFO *Info = Context;721ACPI_DB_METHOD_INFO LocalInfo;722UINT32 i;723UINT8 Allow;724ACPI_BUFFER ReturnObj;725726727/*728* AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments.729* Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads730* concurrently.731*732* Note: The arguments we are passing are used by the ASL test suite733* (aslts). Do not change them without updating the tests.734*/735(void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER);736737if (Info->InitArgs)738{739AcpiDbUint32ToHexString (Info->NumCreated,740Info->IndexOfThreadStr);741AcpiDbUint32ToHexString ((UINT32) AcpiOsGetThreadId (),742Info->IdOfThreadStr);743}744745if (Info->Threads && (Info->NumCreated < Info->NumThreads))746{747Info->Threads[Info->NumCreated++] = AcpiOsGetThreadId();748}749750LocalInfo = *Info;751LocalInfo.Args = LocalInfo.Arguments;752LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr;753LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr;754LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr;755LocalInfo.Arguments[3] = NULL;756757LocalInfo.Types = LocalInfo.ArgTypes;758759(void) AcpiOsSignalSemaphore (Info->InfoGate, 1);760761for (i = 0; i < Info->NumLoops; i++)762{763Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj);764if (ACPI_FAILURE (Status))765{766AcpiOsPrintf ("%s During evaluation of %s at iteration %X\n",767AcpiFormatException (Status), Info->Pathname, i);768if (Status == AE_ABORT_METHOD)769{770break;771}772}773774#if 0775if ((i % 100) == 0)776{777AcpiOsPrintf ("%u loops, Thread 0x%x\n",778i, AcpiOsGetThreadId ());779}780781if (ReturnObj.Length)782{783AcpiOsPrintf ("Evaluation of %s returned object %p Buflen %X\n",784Info->Pathname, ReturnObj.Pointer,785(UINT32) ReturnObj.Length);786AcpiDbDumpExternalObject (ReturnObj.Pointer, 1);787}788#endif789}790791/* Signal our completion */792793Allow = 0;794(void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate,7951, ACPI_WAIT_FOREVER);796Info->NumCompleted++;797798if (Info->NumCompleted == Info->NumThreads)799{800/* Do signal for main thread once only */801Allow = 1;802}803804(void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1);805806if (Allow)807{808Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1);809if (ACPI_FAILURE (Status))810{811AcpiOsPrintf (812"Could not signal debugger thread sync semaphore, %s\n",813AcpiFormatException (Status));814}815}816}817818819/*******************************************************************************820*821* FUNCTION: AcpiDbSingleExecutionThread822*823* PARAMETERS: Context - Method info struct824*825* RETURN: None826*827* DESCRIPTION: Create one thread and execute a method828*829******************************************************************************/830831static void ACPI_SYSTEM_XFACE832AcpiDbSingleExecutionThread (833void *Context)834{835ACPI_DB_METHOD_INFO *Info = Context;836ACPI_STATUS Status;837ACPI_BUFFER ReturnObj;838839840AcpiOsPrintf ("\n");841842Status = AcpiDbExecuteMethod (Info, &ReturnObj);843if (ACPI_FAILURE (Status))844{845AcpiOsPrintf ("%s During evaluation of %s\n",846AcpiFormatException (Status), Info->Pathname);847return;848}849850/* Display a return object, if any */851852if (ReturnObj.Length)853{854AcpiOsPrintf ("Evaluation of %s returned object %p, "855"external buffer length %X\n",856AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer,857(UINT32) ReturnObj.Length);858859AcpiDbDumpExternalObject (ReturnObj.Pointer, 1);860}861862AcpiOsPrintf ("\nBackground thread completed\n%c ",863ACPI_DEBUGGER_COMMAND_PROMPT);864}865866867/*******************************************************************************868*869* FUNCTION: AcpiDbCreateExecutionThread870*871* PARAMETERS: MethodNameArg - Control method to execute872* Arguments - Array of arguments to the method873* Types - Corresponding array of object types874*875* RETURN: None876*877* DESCRIPTION: Create a single thread to evaluate a namespace object. Handles878* arguments passed on command line for control methods.879*880******************************************************************************/881882void883AcpiDbCreateExecutionThread (884char *MethodNameArg,885char **Arguments,886ACPI_OBJECT_TYPE *Types)887{888ACPI_STATUS Status;889UINT32 i;890891892memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO));893AcpiGbl_DbMethodInfo.Name = MethodNameArg;894AcpiGbl_DbMethodInfo.InitArgs = 1;895AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments;896AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes;897898/* Setup method arguments, up to 7 (0-6) */899900for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && *Arguments; i++)901{902AcpiGbl_DbMethodInfo.Arguments[i] = *Arguments;903Arguments++;904905AcpiGbl_DbMethodInfo.ArgTypes[i] = *Types;906Types++;907}908909Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);910if (ACPI_FAILURE (Status))911{912return;913}914915/* Get the NS node, determines existence also */916917Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname,918&AcpiGbl_DbMethodInfo.Method);919if (ACPI_FAILURE (Status))920{921AcpiOsPrintf ("%s Could not get handle for %s\n",922AcpiFormatException (Status), AcpiGbl_DbMethodInfo.Pathname);923return;924}925926Status = AcpiOsExecute (OSL_DEBUGGER_EXEC_THREAD,927AcpiDbSingleExecutionThread, &AcpiGbl_DbMethodInfo);928if (ACPI_FAILURE (Status))929{930return;931}932933AcpiOsPrintf ("\nBackground thread started\n");934}935936937/*******************************************************************************938*939* FUNCTION: AcpiDbCreateExecutionThreads940*941* PARAMETERS: NumThreadsArg - Number of threads to create942* NumLoopsArg - Loop count for the thread(s)943* MethodNameArg - Control method to execute944*945* RETURN: None946*947* DESCRIPTION: Create threads to execute method(s)948*949******************************************************************************/950951void952AcpiDbCreateExecutionThreads (953char *NumThreadsArg,954char *NumLoopsArg,955char *MethodNameArg)956{957ACPI_STATUS Status;958UINT32 NumThreads;959UINT32 NumLoops;960UINT32 i;961UINT32 Size;962ACPI_MUTEX MainThreadGate;963ACPI_MUTEX ThreadCompleteGate;964ACPI_MUTEX InfoGate;965966967/* Get the arguments */968969NumThreads = strtoul (NumThreadsArg, NULL, 0);970NumLoops = strtoul (NumLoopsArg, NULL, 0);971972if (!NumThreads || !NumLoops)973{974AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n",975NumThreads, NumLoops);976return;977}978979/*980* Create the semaphore for synchronization of981* the created threads with the main thread.982*/983Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate);984if (ACPI_FAILURE (Status))985{986AcpiOsPrintf ("Could not create semaphore for "987"synchronization with the main thread, %s\n",988AcpiFormatException (Status));989return;990}991992/*993* Create the semaphore for synchronization994* between the created threads.995*/996Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate);997if (ACPI_FAILURE (Status))998{999AcpiOsPrintf ("Could not create semaphore for "1000"synchronization between the created threads, %s\n",1001AcpiFormatException (Status));10021003(void) AcpiOsDeleteSemaphore (MainThreadGate);1004return;1005}10061007Status = AcpiOsCreateSemaphore (1, 1, &InfoGate);1008if (ACPI_FAILURE (Status))1009{1010AcpiOsPrintf ("Could not create semaphore for "1011"synchronization of AcpiGbl_DbMethodInfo, %s\n",1012AcpiFormatException (Status));10131014(void) AcpiOsDeleteSemaphore (ThreadCompleteGate);1015(void) AcpiOsDeleteSemaphore (MainThreadGate);1016return;1017}10181019memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO));10201021/* Array to store IDs of threads */10221023AcpiGbl_DbMethodInfo.NumThreads = NumThreads;1024Size = sizeof (ACPI_THREAD_ID) * AcpiGbl_DbMethodInfo.NumThreads;10251026AcpiGbl_DbMethodInfo.Threads = AcpiOsAllocate (Size);1027if (AcpiGbl_DbMethodInfo.Threads == NULL)1028{1029AcpiOsPrintf ("No memory for thread IDs array\n");1030(void) AcpiOsDeleteSemaphore (MainThreadGate);1031(void) AcpiOsDeleteSemaphore (ThreadCompleteGate);1032(void) AcpiOsDeleteSemaphore (InfoGate);1033return;1034}1035memset (AcpiGbl_DbMethodInfo.Threads, 0, Size);10361037/* Setup the context to be passed to each thread */10381039AcpiGbl_DbMethodInfo.Name = MethodNameArg;1040AcpiGbl_DbMethodInfo.Flags = 0;1041AcpiGbl_DbMethodInfo.NumLoops = NumLoops;1042AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate;1043AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate;1044AcpiGbl_DbMethodInfo.InfoGate = InfoGate;10451046/* Init arguments to be passed to method */10471048AcpiGbl_DbMethodInfo.InitArgs = 1;1049AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments;1050AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr;1051AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr;1052AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr;1053AcpiGbl_DbMethodInfo.Arguments[3] = NULL;10541055AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes;1056AcpiGbl_DbMethodInfo.ArgTypes[0] = ACPI_TYPE_INTEGER;1057AcpiGbl_DbMethodInfo.ArgTypes[1] = ACPI_TYPE_INTEGER;1058AcpiGbl_DbMethodInfo.ArgTypes[2] = ACPI_TYPE_INTEGER;10591060AcpiDbUint32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr);10611062Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);1063if (ACPI_FAILURE (Status))1064{1065goto CleanupAndExit;1066}10671068/* Get the NS node, determines existence also */10691070Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname,1071&AcpiGbl_DbMethodInfo.Method);1072if (ACPI_FAILURE (Status))1073{1074AcpiOsPrintf ("%s Could not get handle for %s\n",1075AcpiFormatException (Status), AcpiGbl_DbMethodInfo.Pathname);1076goto CleanupAndExit;1077}10781079/* Create the threads */10801081AcpiOsPrintf ("Creating %X threads to execute %X times each\n",1082NumThreads, NumLoops);10831084for (i = 0; i < (NumThreads); i++)1085{1086Status = AcpiOsExecute (OSL_DEBUGGER_EXEC_THREAD, AcpiDbMethodThread,1087&AcpiGbl_DbMethodInfo);1088if (ACPI_FAILURE (Status))1089{1090break;1091}1092}10931094/* Wait for all threads to complete */10951096(void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER);10971098AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);1099AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads);1100AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);11011102CleanupAndExit:11031104/* Cleanup and exit */11051106(void) AcpiOsDeleteSemaphore (MainThreadGate);1107(void) AcpiOsDeleteSemaphore (ThreadCompleteGate);1108(void) AcpiOsDeleteSemaphore (InfoGate);11091110AcpiOsFree (AcpiGbl_DbMethodInfo.Threads);1111AcpiGbl_DbMethodInfo.Threads = NULL;1112}111311141115