Exemplo n.º 1
0
ACPI_TABLE_DESC *
AcpiTbUninstallTable (
    ACPI_TABLE_DESC         *TableDesc)
{
    ACPI_TABLE_DESC         *NextDesc;


    ACPI_FUNCTION_TRACE_PTR (TbUninstallTable, TableDesc);


    if (!TableDesc)
    {
        return_PTR (NULL);
    }

    /* Unlink the descriptor from the doubly linked list */

    if (TableDesc->Prev)
    {
        TableDesc->Prev->Next = TableDesc->Next;
    }
    else
    {
        /* Is first on list, update list head */

        AcpiGbl_TableLists[TableDesc->Type].Next = TableDesc->Next;
    }

    if (TableDesc->Next)
    {
        TableDesc->Next->Prev = TableDesc->Prev;
    }

    /* Free the memory allocated for the table itself */

    AcpiTbDeleteSingleTable (TableDesc);

    /* Free the owner ID associated with this table */

    AcpiUtReleaseOwnerId (&TableDesc->OwnerId);

    /* Free the table descriptor */

    NextDesc = TableDesc->Next;
    ACPI_FREE (TableDesc);

    /* Return pointer to the next descriptor */

    return_PTR (NextDesc);
}
Exemplo n.º 2
0
ACPI_STATUS
AcpiTbReleaseOwnerId (
    UINT32                  TableIndex)
{
    ACPI_STATUS             Status = AE_BAD_PARAMETER;


    ACPI_FUNCTION_TRACE (TbReleaseOwnerId);


    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
    {
        AcpiUtReleaseOwnerId (
            &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
        Status = AE_OK;
    }

    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
    return_ACPI_STATUS (Status);
}
Exemplo n.º 3
0
ACPI_STATUS
AcpiDbDisassembleMethod (
    char                    *Name)
{
    ACPI_STATUS             Status;
    ACPI_PARSE_OBJECT       *Op;
    ACPI_WALK_STATE         *WalkState;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_NAMESPACE_NODE     *Method;


    Method = AcpiDbConvertToNode (Name);
    if (!Method)
    {
        return (AE_BAD_PARAMETER);
    }

    if (Method->Type != ACPI_TYPE_METHOD)
    {
        ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method",
            Name, AcpiUtGetTypeName (Method->Type)));
        return (AE_BAD_PARAMETER);
    }

    ObjDesc = Method->Object;

    Op = AcpiPsCreateScopeOp ();
    if (!Op)
    {
        return (AE_NO_MEMORY);
    }

    /* Create and initialize a new walk state */

    WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
    if (!WalkState)
    {
        return (AE_NO_MEMORY);
    }

    Status = AcpiDsInitAmlWalk (WalkState, Op, NULL,
        ObjDesc->Method.AmlStart,
        ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
    WalkState->OwnerId = ObjDesc->Method.OwnerId;

    /* Push start scope on scope stack and make it current */

    Status = AcpiDsScopeStackPush (Method,
        Method->Type, WalkState);
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    /* Parse the entire method AML including deferred operators */

    WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
    WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;

    Status = AcpiPsParseAml (WalkState);
    (void) AcpiDmParseDeferredOps (Op);

    /* Now we can disassemble the method */

    AcpiGbl_DbOpt_verbose = FALSE;
    AcpiDmDisassemble (NULL, Op, 0);
    AcpiGbl_DbOpt_verbose = TRUE;

    AcpiPsDeleteParseTree (Op);

    /* Method cleanup */

    AcpiNsDeleteNamespaceSubtree (Method);
    AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId);
    AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId);
    return (AE_OK);
}
Exemplo n.º 4
0
void
AcpiDsTerminateControlMethod (
    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. Unless:
         * 1) This method is a module-level executable code method, in which
         *    case we want make the objects permanent.
         * 2) There are other threads executing the method, in which case we
         *    will wait until the last thread has completed.
         */
        if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) &&
             (MethodDesc->Method.ThreadCount == 1))
        {
            /* Delete any direct children of (created by) this method */

            AcpiNsDeleteNamespaceSubtree (WalkState->MethodNode);

            /*
             * Delete any objects that were created by this method
             * elsewhere in the namespace (if any were created).
             * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the
             * deletion such that we don't have to perform an entire
             * namespace walk for every control method execution.
             */
            if (MethodDesc->Method.InfoFlags & ACPI_METHOD_MODIFIED_NAMESPACE)
            {
                AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId);
                MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_MODIFIED_NAMESPACE;
            }
        }
    }

    /* 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, %u 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 marking the method as serialized.
         */
        if (MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED_PENDING)
        {
            if (WalkState)
            {
                ACPI_INFO ((AE_INFO,
                    "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
                    WalkState->MethodNode->Name.Ascii));
            }

            /*
             * Method tried to create an object twice and was marked as
             * "pending serialized". The probable cause is that the method
             * cannot handle reentrancy.
             *
             * The method was created as NotSerialized, but it tried to create
             * a named object and then blocked, causing the second thread
             * entrance to begin and then fail. Workaround this problem by
             * marking the method permanently as Serialized when the last
             * thread exits here.
             */
            MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_SERIALIZED_PENDING;
            MethodDesc->Method.InfoFlags |= ACPI_METHOD_SERIALIZED;
            MethodDesc->Method.SyncLevel = 0;
        }

        /* No more threads, we can free the OwnerId */

        if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL))
        {
            AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId);
        }
    }

    return_VOID;
}
Exemplo n.º 5
0
ACPI_STATUS
AcpiTbInitTableDescriptor (
    ACPI_TABLE_TYPE         TableType,
    ACPI_TABLE_DESC         *TableInfo)
{
    ACPI_TABLE_LIST         *ListHead;
    ACPI_TABLE_DESC         *TableDesc;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE_U32 (TbInitTableDescriptor, TableType);


    /* Allocate a descriptor for this table */

    TableDesc = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_TABLE_DESC));
    if (!TableDesc)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Get a new owner ID for the table */

    Status = AcpiUtAllocateOwnerId (&TableDesc->OwnerId);
    if (ACPI_FAILURE (Status))
    {
        goto ErrorExit1;
    }

    /* Install the table into the global data structure */

    ListHead = &AcpiGbl_TableLists[TableType];

    /*
     * Two major types of tables:  1) Only one instance is allowed.  This
     * includes most ACPI tables such as the DSDT.  2) Multiple instances of
     * the table are allowed.  This includes SSDT and PSDTs.
     */
    if (ACPI_IS_SINGLE_TABLE (AcpiGbl_TableData[TableType].Flags))
    {
        /*
         * Only one table allowed, and a table has alread been installed
         * at this location, so return an error.
         */
        if (ListHead->Next)
        {
            Status = AE_ALREADY_EXISTS;
            goto ErrorExit2;
        }

        TableDesc->Next = ListHead->Next;
        ListHead->Next = TableDesc;

        if (TableDesc->Next)
        {
            TableDesc->Next->Prev = TableDesc;
        }

        ListHead->Count++;
    }
    else
    {
        /*
         * Link the new table in to the list of tables of this type.
         * Insert at the end of the list, order IS IMPORTANT.
         *
         * TableDesc->Prev & Next are already NULL from calloc()
         */
        ListHead->Count++;

        if (!ListHead->Next)
        {
            ListHead->Next = TableDesc;
        }
        else
        {
            TableDesc->Next = ListHead->Next;

            while (TableDesc->Next->Next)
            {
                TableDesc->Next = TableDesc->Next->Next;
            }

            TableDesc->Next->Next = TableDesc;
            TableDesc->Prev = TableDesc->Next;
            TableDesc->Next = NULL;
        }
    }

    /* Finish initialization of the table descriptor */

    TableDesc->LoadedIntoNamespace = FALSE;
    TableDesc->Type = (UINT8) TableType;
    TableDesc->Pointer = TableInfo->Pointer;
    TableDesc->Length = TableInfo->Length;
    TableDesc->Allocation = TableInfo->Allocation;
    TableDesc->AmlStart = (UINT8 *) (TableDesc->Pointer + 1),
    TableDesc->AmlLength = (UINT32)
        (TableDesc->Length - (UINT32) sizeof (ACPI_TABLE_HEADER));

    /*
     * Set the appropriate global pointer (if there is one) to point to the
     * newly installed table
     */
    if (AcpiGbl_TableData[TableType].GlobalPtr)
    {
        *(AcpiGbl_TableData[TableType].GlobalPtr) = TableInfo->Pointer;
    }

    /* Return Data */

    TableInfo->OwnerId = TableDesc->OwnerId;
    TableInfo->InstalledDesc = TableDesc;
    return_ACPI_STATUS (AE_OK);


    /* Error exit with cleanup */

ErrorExit2:

    AcpiUtReleaseOwnerId (&TableDesc->OwnerId);

ErrorExit1:

    ACPI_FREE (TableDesc);
    return_ACPI_STATUS (Status);
}