ACPI_STATUS AcpiReleaseGlobalLock ( UINT32 Handle) { ACPI_STATUS Status; if (!Handle || (Handle != AcpiGbl_GlobalLockHandle)) { return (AE_NOT_ACQUIRED); } Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex); return (Status); }
ACPI_STATUS AcpiExReleaseMutex ( ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; UINT8 PreviousSyncLevel; ACPI_THREAD_STATE *OwnerThread; ACPI_FUNCTION_TRACE (ExReleaseMutex); if (!ObjDesc) { return_ACPI_STATUS (AE_BAD_PARAMETER); } OwnerThread = ObjDesc->Mutex.OwnerThread; /* The mutex must have been previously acquired in order to release it */ if (!OwnerThread) { 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 ((OwnerThread->ThreadId != WalkState->Thread->ThreadId) && (ObjDesc != AcpiGbl_GlobalLockMutex)) { ACPI_ERROR ((AE_INFO, "Thread %u cannot release Mutex [%4.4s] acquired by thread %u", (UINT32) WalkState->Thread->ThreadId, AcpiUtGetNodeName (ObjDesc->Mutex.Node), (UINT32) OwnerThread->ThreadId)); return_ACPI_STATUS (AE_AML_NOT_OWNER); } /* * 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 * level is currently being held. Attempting to release a mutex of a * 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 != OwnerThread->CurrentSyncLevel) { ACPI_ERROR ((AE_INFO, "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); } /* * Get the previous SyncLevel from the head of the acquired mutex list. * This handles the case where several mutexes at the same level have been * acquired, but are not released in reverse order. */ PreviousSyncLevel = OwnerThread->AcquiredMutexList->Mutex.OriginalSyncLevel; Status = AcpiExReleaseMutexObject (ObjDesc); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (ObjDesc->Mutex.AcquisitionDepth == 0) { /* Restore the previous SyncLevel */ OwnerThread->CurrentSyncLevel = PreviousSyncLevel; } return_ACPI_STATUS (Status); }