Beispiel #1
0
ACPI_STATUS
AcpiExAcquireMutex (
    ACPI_OPERAND_OBJECT     *TimeDesc,
    ACPI_OPERAND_OBJECT     *ObjDesc,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE_PTR (ExAcquireMutex, ObjDesc);


    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /* Must have a valid thread state struct */

    if (!WalkState->Thread)
    {
        ACPI_ERROR ((AE_INFO,
            "Cannot acquire Mutex [%4.4s], null thread info",
            AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
        return_ACPI_STATUS (AE_AML_INTERNAL);
    }

    /*
     * Current sync level must be less than or equal to the sync level of the
     * mutex. This mechanism provides some deadlock prevention
     */
    if (WalkState->Thread->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel)
    {
        ACPI_ERROR ((AE_INFO,
            "Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%u)",
            AcpiUtGetNodeName (ObjDesc->Mutex.Node),
            WalkState->Thread->CurrentSyncLevel));
        return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
    }

    Status = AcpiExAcquireMutexObject ((UINT16) TimeDesc->Integer.Value,
                ObjDesc, WalkState->Thread->ThreadId);
    if (ACPI_SUCCESS (Status) && ObjDesc->Mutex.AcquisitionDepth == 1)
    {
        /* Save Thread object, original/current sync levels */

        ObjDesc->Mutex.OwnerThread = WalkState->Thread;
        ObjDesc->Mutex.OriginalSyncLevel = WalkState->Thread->CurrentSyncLevel;
        WalkState->Thread->CurrentSyncLevel = ObjDesc->Mutex.SyncLevel;

        /* Link the mutex to the current thread for force-unlock at method exit */

        AcpiExLinkMutex (ObjDesc, WalkState->Thread);
    }

    return_ACPI_STATUS (Status);
}
Beispiel #2
0
ACPI_STATUS
AcpiExAcquireMutex (
    ACPI_OPERAND_OBJECT     *TimeDesc,
    ACPI_OPERAND_OBJECT     *ObjDesc,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE_PTR (ExAcquireMutex, ObjDesc);


    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /* Sanity check: we must have a valid thread ID */

    if (!WalkState->Thread)
    {
        ACPI_ERROR ((AE_INFO, "Cannot acquire Mutex [%4.4s], null thread info",
            AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
        return_ACPI_STATUS (AE_AML_INTERNAL);
    }

    /*
     * Current Sync must be less than or equal to the sync level of the
     * mutex. This mechanism provides some deadlock prevention
     */
    if (WalkState->Thread->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel)
    {
        ACPI_ERROR ((AE_INFO,
            "Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%d)",
            AcpiUtGetNodeName (ObjDesc->Mutex.Node),
            WalkState->Thread->CurrentSyncLevel));
        return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
    }

    /* Support for multiple acquires by the owning thread */

    if (ObjDesc->Mutex.OwnerThread)
    {
        if (ObjDesc->Mutex.OwnerThread->ThreadId ==
            WalkState->Thread->ThreadId)
        {
            /*
             * The mutex is already owned by this thread, just increment the
             * acquisition depth
             */
            ObjDesc->Mutex.AcquisitionDepth++;
            return_ACPI_STATUS (AE_OK);
        }
    }

    /* Acquire the mutex, wait if necessary. Special case for Global Lock */

    if (ObjDesc->Mutex.OsMutex == AcpiGbl_GlobalLockMutex)
    {
        Status = AcpiEvAcquireGlobalLock ((UINT16) TimeDesc->Integer.Value);
    }
    else
    {
        Status = AcpiExSystemWaitMutex (ObjDesc->Mutex.OsMutex,
                    (UINT16) TimeDesc->Integer.Value);
    }

    if (ACPI_FAILURE (Status))
    {
        /* Includes failure from a timeout on TimeDesc */

        return_ACPI_STATUS (Status);
    }

    /* Have the mutex: update mutex and walk info and save the SyncLevel */

    ObjDesc->Mutex.OwnerThread = WalkState->Thread;
    ObjDesc->Mutex.AcquisitionDepth = 1;
    ObjDesc->Mutex.OriginalSyncLevel = WalkState->Thread->CurrentSyncLevel;

    WalkState->Thread->CurrentSyncLevel = ObjDesc->Mutex.SyncLevel;

    /* Link the mutex to the current thread for force-unlock at method exit */

    AcpiExLinkMutex (ObjDesc, WalkState->Thread);
    return_ACPI_STATUS (AE_OK);
}