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