⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dsmethod.c

📁 acpi tools for linux include acpiexec and acpixtract
💻 C
📖 第 1 页 / 共 2 页
字号:
        if (ACPI_FAILURE (Status))        {            goto Cleanup;        }    }    /*     * Increment the method parse tree thread count since it has been     * reentered one more time (even if it is the same thread)     */    ObjDesc->Method.ThreadCount++;    AcpiMethodCount++;    return_ACPI_STATUS (Status);Cleanup:    /* On error, must release the method mutex (if present) */    if (ObjDesc->Method.Mutex)    {        AcpiOsReleaseMutex (ObjDesc->Method.Mutex->Mutex.OsMutex);    }    return_ACPI_STATUS (Status);}/******************************************************************************* * * FUNCTION:    AcpiDsCallControlMethod * * PARAMETERS:  Thread              - Info for this thread *              ThisWalkState       - Current walk state *              Op                  - Current Op to be walked * * RETURN:      Status * * DESCRIPTION: Transfer execution to a called control method * ******************************************************************************/ACPI_STATUSAcpiDsCallControlMethod (    ACPI_THREAD_STATE       *Thread,    ACPI_WALK_STATE         *ThisWalkState,    ACPI_PARSE_OBJECT       *Op){    ACPI_STATUS             Status;    ACPI_NAMESPACE_NODE     *MethodNode;    ACPI_WALK_STATE         *NextWalkState = NULL;    ACPI_OPERAND_OBJECT     *ObjDesc;    ACPI_EVALUATE_INFO      *Info;    UINT32                  i;    ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState);    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Calling method %p, currentstate=%p\n",        ThisWalkState->PrevOp, ThisWalkState));    /*     * Get the namespace entry for the control method we are about to call     */    MethodNode = ThisWalkState->MethodCallNode;    if (!MethodNode)    {        return_ACPI_STATUS (AE_NULL_ENTRY);    }    ObjDesc = AcpiNsGetAttachedObject (MethodNode);    if (!ObjDesc)    {        return_ACPI_STATUS (AE_NULL_OBJECT);    }    /* Init for new method, possibly wait on method mutex */    Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc,                ThisWalkState);    if (ACPI_FAILURE (Status))    {        return_ACPI_STATUS (Status);    }    /* Begin method parse/execution. Create a new walk state */    NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwnerId,                        NULL, ObjDesc, Thread);    if (!NextWalkState)    {        Status = AE_NO_MEMORY;        goto Cleanup;    }    /*     * The resolved arguments were put on the previous walk state's operand     * stack. Operands on the previous walk state stack always     * start at index 0. Also, null terminate the list of arguments     */    ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL;    /*     * Allocate and initialize the evaluation information block     * TBD: this is somewhat inefficient, should change interface to     * DsInitAmlWalk. For now, keeps this struct off the CPU stack     */    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));    if (!Info)    {        return_ACPI_STATUS (AE_NO_MEMORY);    }    Info->Parameters = &ThisWalkState->Operands[0];    Info->ParameterType = ACPI_PARAM_ARGS;    Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode,                ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength,                Info, ACPI_IMODE_EXECUTE);    ACPI_FREE (Info);    if (ACPI_FAILURE (Status))    {        goto Cleanup;    }    /*     * Delete the operands on the previous walkstate operand stack     * (they were copied to new objects)     */    for (i = 0; i < ObjDesc->Method.ParamCount; i++)    {        AcpiUtRemoveReference (ThisWalkState->Operands [i]);        ThisWalkState->Operands [i] = NULL;    }    /* Clear the operand stack */    ThisWalkState->NumOperands = 0;    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,        "**** Begin nested execution of [%4.4s] **** WalkState=%p\n",        MethodNode->Name.Ascii, NextWalkState));    /* Invoke an internal method if necessary */    if (ObjDesc->Method.MethodFlags & AML_METHOD_INTERNAL_ONLY)    {        Status = ObjDesc->Method.Implementation (NextWalkState);    }    return_ACPI_STATUS (Status);Cleanup:    /* On error, we must terminate the method properly */    AcpiDsTerminateControlMethod (ObjDesc, NextWalkState);    if (NextWalkState)    {        AcpiDsDeleteWalkState (NextWalkState);    }    return_ACPI_STATUS (Status);}/******************************************************************************* * * FUNCTION:    AcpiDsRestartControlMethod * * PARAMETERS:  WalkState           - State for preempted method (caller) *              ReturnDesc          - Return value from the called method * * RETURN:      Status * * DESCRIPTION: Restart a method that was preempted by another (nested) method *              invocation.  Handle the return value (if any) from the callee. * ******************************************************************************/ACPI_STATUSAcpiDsRestartControlMethod (    ACPI_WALK_STATE         *WalkState,    ACPI_OPERAND_OBJECT     *ReturnDesc){    ACPI_STATUS             Status;    int                     SameAsImplicitReturn;    ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState);    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,        "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",        AcpiUtGetNodeName (WalkState->MethodNode),        WalkState->MethodCallOp, ReturnDesc));    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,        "    ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",        WalkState->ReturnUsed,        WalkState->Results, WalkState));    /* Did the called method return a value? */    if (ReturnDesc)    {        /* Is the implicit return object the same as the return desc? */        SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc);        /* Are we actually going to use the return value? */        if (WalkState->ReturnUsed)        {            /* Save the return value from the previous method */            Status = AcpiDsResultPush (ReturnDesc, WalkState);            if (ACPI_FAILURE (Status))            {                AcpiUtRemoveReference (ReturnDesc);                return_ACPI_STATUS (Status);            }            /*             * Save as THIS method's return value in case it is returned             * immediately to yet another method             */            WalkState->ReturnDesc = ReturnDesc;        }        /*         * The following code is the optional support for the so-called         * "implicit return". Some AML code assumes that the last value of the         * method is "implicitly" returned to the caller, in the absence of an         * explicit return value.         *         * Just save the last result of the method as the return value.         *         * NOTE: this is optional because the ASL language does not actually         * support this behavior.         */        else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) ||                 SameAsImplicitReturn)        {            /*             * Delete the return value if it will not be used by the             * calling method or remove one reference if the explicit return             * is the same as the implicit return value.             */            AcpiUtRemoveReference (ReturnDesc);        }    }    return_ACPI_STATUS (AE_OK);}/******************************************************************************* * * FUNCTION:    AcpiDsTerminateControlMethod * * PARAMETERS:  MethodDesc          - Method object *              WalkState           - State associated with the method * * RETURN:      None * * DESCRIPTION: Terminate a control method.  Delete everything that the method *              created, delete all locals and arguments, and delete the parse *              tree if requested. * * MUTEX:       Interpreter is locked * ******************************************************************************/voidAcpiDsTerminateControlMethod (    ACPI_OPERAND_OBJECT     *MethodDesc,    ACPI_WALK_STATE         *WalkState){    ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState);    /* MethodDesc is required, WalkState is optional */    if (!MethodDesc)    {        return_VOID;    }    if (WalkState)    {        /* Delete all arguments and locals */        AcpiDsMethodDataDeleteAll (WalkState);        /*         * If method is serialized, release the mutex and restore the         * current sync level for this thread         */        if (MethodDesc->Method.Mutex)        {            /* Acquisition Depth handles recursive calls */            MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--;            if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth)            {                WalkState->Thread->CurrentSyncLevel =                    MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel;                AcpiOsReleaseMutex (MethodDesc->Method.Mutex->Mutex.OsMutex);                MethodDesc->Method.Mutex->Mutex.ThreadId = 0;            }        }        /*         * Delete any namespace objects created anywhere within         * the namespace by the execution of this method         */        AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId);    }    /* Decrement the thread count on the method */    if (MethodDesc->Method.ThreadCount)    {        MethodDesc->Method.ThreadCount--;    }    else    {        ACPI_ERROR ((AE_INFO,            "Invalid zero thread count in method"));    }    /* Are there any other threads currently executing this method? */    if (MethodDesc->Method.ThreadCount)    {        /*         * Additional threads. Do not release the OwnerId in this case,         * we immediately reuse it for the next thread executing this method         */        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,            "*** Completed execution of one thread, %d threads remaining\n",            MethodDesc->Method.ThreadCount));    }    else    {        /* This is the only executing thread for this method */        /*         * Support to dynamically change a method from NotSerialized to         * Serialized if it appears that the method is incorrectly written and         * does not support multiple thread execution. The best example of this         * is if such a method creates namespace objects and blocks. A second         * thread will fail with an AE_ALREADY_EXISTS exception         *         * This code is here because we must wait until the last thread exits         * before creating the synchronization semaphore.         */        if ((MethodDesc->Method.MethodFlags & AML_METHOD_SERIALIZED) &&            (!MethodDesc->Method.Mutex))        {            (void) AcpiDsCreateMethodMutex (MethodDesc);        }        /* No more threads, we can free the OwnerId */        AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId);    }    return_VOID;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -