From 95b36bc38b6581661ab9bf36da09dd71c9890f34 Mon Sep 17 00:00:00 2001 From: Robert Moore Date: Fri, 1 May 2009 12:54:20 -0700 Subject: [PATCH] Mutex support: Fix release ordering issue and current sync level. Fixes a problem where if multiple mutexes of the same sync level are acquired but then not released in strict opposite order, the current sync level becomes confused and can cause errors. ACPICA BZ 471. --- source/components/executer/exmutex.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/source/components/executer/exmutex.c b/source/components/executer/exmutex.c index 99e768d3c..9a23a97c7 100644 --- a/source/components/executer/exmutex.c +++ b/source/components/executer/exmutex.c @@ -166,6 +166,15 @@ AcpiExUnlinkMutex ( if (ObjDesc->Mutex.Prev) { (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. + */ + (ObjDesc->Mutex.Prev)->Mutex.OriginalSyncLevel = + ObjDesc->Mutex.OriginalSyncLevel; } else { @@ -461,6 +470,7 @@ AcpiExReleaseMutex ( ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; + UINT8 PreviousSyncLevel; ACPI_FUNCTION_TRACE (ExReleaseMutex); @@ -517,13 +527,21 @@ AcpiExReleaseMutex ( 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 = + WalkState->Thread->AcquiredMutexList->Mutex.OriginalSyncLevel; + Status = AcpiExReleaseMutexObject (ObjDesc); if (ObjDesc->Mutex.AcquisitionDepth == 0) { /* Restore the original SyncLevel */ - WalkState->Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel; + WalkState->Thread->CurrentSyncLevel = PreviousSyncLevel; } return_ACPI_STATUS (Status); }