From 610a3d069665ba2b27e42c90129ce640c4d6e515 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 7 Mar 2007 00:57:30 -0500 Subject: ACPICA: Fix ACPI Global Lock re-entrancy patch "Delete recursive feature of ACPI Global Lock" broke re-entrancy of the Global Lock. The common routine to acquire GL is acpi_ev_acquire_global_lock, so check for re-entrancy _must_ be there, and not anywhere else. http://bugzilla.kernel.org/show_bug.cgi?id=8066#c9 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/events/evmisc.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index d572700197f3..8dcade63b04b 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -423,6 +423,8 @@ static acpi_status acpi_ev_remove_global_lock_handler(void) * the global lock appear as a standard mutex on the OS side. * *****************************************************************************/ +static acpi_thread_id acpi_ev_global_lock_thread_id; +static int acpi_ev_global_lock_acquired; acpi_status acpi_ev_acquire_global_lock(u16 timeout) { @@ -435,11 +437,24 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) * Only one thread can acquire the GL at a time, the global_lock_mutex * enforces this. This interface releases the interpreter if we must wait. */ - status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout); + status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0); + if (status == AE_TIME) { + if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) { + acpi_ev_global_lock_acquired++; + return AE_OK; + } + } + + if (ACPI_FAILURE(status)) { + status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout); + } if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + acpi_ev_global_lock_thread_id = acpi_os_get_thread_id(); + acpi_ev_global_lock_acquired++; + /* * Make sure that a global lock actually exists. If not, just treat * the lock as a standard mutex. @@ -506,6 +521,11 @@ acpi_status acpi_ev_release_global_lock(void) return_ACPI_STATUS(AE_NOT_ACQUIRED); } + acpi_ev_global_lock_acquired--; + if (acpi_ev_global_lock_acquired > 0) { + return AE_OK; + } + if (acpi_gbl_global_lock_present) { /* Allow any thread to release the lock */ @@ -529,7 +549,8 @@ acpi_status acpi_ev_release_global_lock(void) acpi_gbl_global_lock_acquired = FALSE; /* Release the local GL mutex */ - + acpi_ev_global_lock_thread_id = 0; + acpi_ev_global_lock_acquired = 0; acpi_os_release_mutex(acpi_gbl_global_lock_mutex); return_ACPI_STATUS(status); } -- cgit v1.2.2