Bug #1846 ยป exmutex.c.patch
sys/contrib/dev/acpica-unix/executer/exmutex.c | ||
---|---|---|
*
|
||
* 1. Copyright Notice
|
||
*
|
||
* Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
|
||
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
|
||
* All rights reserved.
|
||
*
|
||
* 2. License
|
||
... | ... | |
(ObjDesc->Mutex.Prev)->Mutex.Next = ObjDesc->Mutex.Next;
|
||
/*
|
||
* Migrate the previous sync level associated with this mutex to the
|
||
* previous mutex on the list so that it may be preserved. This handles
|
||
* the case where several mutexes have been acquired at the same level,
|
||
* but are not released in opposite order.
|
||
* Migrate the previous sync level associated with this mutex to
|
||
* the previous mutex on the list so that it may be preserved.
|
||
* This handles the case where several mutexes have been acquired
|
||
* at the same level, but are not released in opposite order.
|
||
*/
|
||
(ObjDesc->Mutex.Prev)->Mutex.OriginalSyncLevel =
|
||
ObjDesc->Mutex.OriginalSyncLevel;
|
||
... | ... | |
*
|
||
* FUNCTION: AcpiExLinkMutex
|
||
*
|
||
* PARAMETERS: ObjDesc - The mutex to be linked
|
||
* Thread - Current executing thread object
|
||
* PARAMETERS: ObjDesc - The mutex to be linked
|
||
* Thread - Current executing thread object
|
||
*
|
||
* RETURN: None
|
||
*
|
||
... | ... | |
*
|
||
* FUNCTION: AcpiExAcquireMutexObject
|
||
*
|
||
* PARAMETERS: TimeDesc - Timeout in milliseconds
|
||
* PARAMETERS: Timeout - Timeout in milliseconds
|
||
* ObjDesc - Mutex object
|
||
* Thread - Current thread state
|
||
* ThreadId - Current thread state
|
||
*
|
||
* RETURN: Status
|
||
*
|
||
... | ... | |
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||
}
|
||
/* Must have a valid thread ID */
|
||
/* Must have a valid thread state struct */
|
||
if (!WalkState->Thread)
|
||
{
|
||
ACPI_ERROR ((AE_INFO, "Cannot acquire Mutex [%4.4s], null thread info",
|
||
ACPI_ERROR ((AE_INFO,
|
||
"Cannot acquire Mutex [%4.4s], null thread info",
|
||
AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
|
||
return_ACPI_STATUS (AE_AML_INTERNAL);
|
||
}
|
||
... | ... | |
if (WalkState->Thread->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel)
|
||
{
|
||
ACPI_ERROR ((AE_INFO,
|
||
"Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%d)",
|
||
"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);
|
||
... | ... | |
{
|
||
ACPI_STATUS Status = AE_OK;
|
||
UINT8 PreviousSyncLevel;
|
||
ACPI_THREAD_STATE *OwnerThread;
|
||
ACPI_FUNCTION_TRACE (ExReleaseMutex);
|
||
... | ... | |
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||
}
|
||
OwnerThread = ObjDesc->Mutex.OwnerThread;
|
||
/* The mutex must have been previously acquired in order to release it */
|
||
if (!ObjDesc->Mutex.OwnerThread)
|
||
if (!OwnerThread)
|
||
{
|
||
ACPI_ERROR ((AE_INFO, "Cannot release Mutex [%4.4s], not acquired",
|
||
ACPI_ERROR ((AE_INFO,
|
||
"Cannot release Mutex [%4.4s], not acquired",
|
||
AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
|
||
return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED);
|
||
}
|
||
/* Must have a valid thread ID */
|
||
if (!WalkState->Thread)
|
||
{
|
||
ACPI_ERROR ((AE_INFO,
|
||
"Cannot release Mutex [%4.4s], null thread info",
|
||
AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
|
||
return_ACPI_STATUS (AE_AML_INTERNAL);
|
||
}
|
||
/*
|
||
* The Mutex is owned, but this thread must be the owner.
|
||
* Special case for Global Lock, any thread can release
|
||
*/
|
||
if ((ObjDesc->Mutex.OwnerThread->ThreadId != WalkState->Thread->ThreadId) &&
|
||
if ((OwnerThread->ThreadId != WalkState->Thread->ThreadId) &&
|
||
(ObjDesc != AcpiGbl_GlobalLockMutex))
|
||
{
|
||
ACPI_ERROR ((AE_INFO,
|
||
"Thread %p cannot release Mutex [%4.4s] acquired by thread %p",
|
||
ACPI_CAST_PTR (void, WalkState->Thread->ThreadId),
|
||
AcpiUtGetNodeName (ObjDesc->Mutex.Node),
|
||
ACPI_CAST_PTR (void, ObjDesc->Mutex.OwnerThread->ThreadId)));
|
||
ACPI_CAST_PTR (void, OwnerThread->ThreadId)));
|
||
return_ACPI_STATUS (AE_AML_NOT_OWNER);
|
||
}
|
||
/* Must have a valid thread ID */
|
||
if (!WalkState->Thread)
|
||
{
|
||
ACPI_ERROR ((AE_INFO, "Cannot release Mutex [%4.4s], null thread info",
|
||
AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
|
||
return_ACPI_STATUS (AE_AML_INTERNAL);
|
||
}
|
||
/*
|
||
* The sync level of the mutex must be equal to the current sync level. In
|
||
* other words, the current level means that at least one mutex at that
|
||
... | ... | |
* different level can only mean that the mutex ordering rule is being
|
||
* violated. This behavior is clarified in ACPI 4.0 specification.
|
||
*/
|
||
if (ObjDesc->Mutex.SyncLevel != WalkState->Thread->CurrentSyncLevel)
|
||
if (ObjDesc->Mutex.SyncLevel != OwnerThread->CurrentSyncLevel)
|
||
{
|
||
ACPI_ERROR ((AE_INFO,
|
||
"Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %d current %d",
|
||
"Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u",
|
||
AcpiUtGetNodeName (ObjDesc->Mutex.Node),
|
||
ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel));
|
||
return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
|
||
... | ... | |
* acquired, but are not released in reverse order.
|
||
*/
|
||
PreviousSyncLevel =
|
||
WalkState->Thread->AcquiredMutexList->Mutex.OriginalSyncLevel;
|
||
OwnerThread->AcquiredMutexList->Mutex.OriginalSyncLevel;
|
||
Status = AcpiExReleaseMutexObject (ObjDesc);
|
||
if (ACPI_FAILURE (Status))
|
||
... | ... | |
{
|
||
/* Restore the previous SyncLevel */
|
||
WalkState->Thread->CurrentSyncLevel = PreviousSyncLevel;
|
||
OwnerThread->CurrentSyncLevel = PreviousSyncLevel;
|
||
}
|
||
return_ACPI_STATUS (Status);
|
||
}
|
||
... | ... | |
*
|
||
* FUNCTION: AcpiExReleaseAllMutexes
|
||
*
|
||
* PARAMETERS: Thread - Current executing thread object
|
||
* PARAMETERS: Thread - Current executing thread object
|
||
*
|
||
* RETURN: Status
|
||
*
|
||
... | ... | |
Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel;
|
||
}
|
||
}
|
||