diff options
Diffstat (limited to 'drivers/acpi/executer/exmutex.c')
-rw-r--r-- | drivers/acpi/executer/exmutex.c | 92 |
1 files changed, 55 insertions, 37 deletions
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index 3a39c2e8e10..5101bad5baf 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2006, R. Byron Moore + * Copyright (C) 2000 - 2007, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +44,7 @@ #include <acpi/acpi.h> #include <acpi/acinterp.h> +#include <acpi/acevents.h> #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exmutex") @@ -150,7 +151,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Sanity check -- we must have a valid thread ID */ + /* Sanity check: we must have a valid thread ID */ if (!walk_state->thread) { ACPI_ERROR((AE_INFO, @@ -174,24 +175,28 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, /* Support for multiple acquires by the owning thread */ if (obj_desc->mutex.owner_thread) { - - /* Special case for Global Lock, allow all threads */ - - if ((obj_desc->mutex.owner_thread->thread_id == - walk_state->thread->thread_id) || - (obj_desc->mutex.os_mutex == ACPI_GLOBAL_LOCK)) { + if (obj_desc->mutex.owner_thread->thread_id == + walk_state->thread->thread_id) { /* - * The mutex is already owned by this thread, - * just increment the acquisition depth + * The mutex is already owned by this thread, just increment the + * acquisition depth */ obj_desc->mutex.acquisition_depth++; return_ACPI_STATUS(AE_OK); } } - /* Acquire the mutex, wait if necessary */ + /* Acquire the mutex, wait if necessary. Special case for Global Lock */ + + if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { + status = + acpi_ev_acquire_global_lock((u16) time_desc->integer.value); + } else { + status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, + (u16) time_desc->integer. + value); + } - status = acpi_ex_system_acquire_mutex(time_desc, obj_desc); if (ACPI_FAILURE(status)) { /* Includes failure from a timeout on time_desc */ @@ -211,7 +216,6 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, /* Link the mutex to the current thread for force-unlock at method exit */ acpi_ex_link_mutex(obj_desc, walk_state->thread); - return_ACPI_STATUS(AE_OK); } @@ -232,7 +236,7 @@ acpi_status acpi_ex_release_mutex(union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state) { - acpi_status status; + acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(ex_release_mutex); @@ -249,7 +253,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } - /* Sanity check -- we must have a valid thread ID */ + /* Sanity check: we must have a valid thread ID */ if (!walk_state->thread) { ACPI_ERROR((AE_INFO, @@ -264,18 +268,18 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, */ if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) - && (obj_desc->mutex.os_mutex != ACPI_GLOBAL_LOCK)) { + && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { ACPI_ERROR((AE_INFO, - "Thread %X cannot release Mutex [%4.4s] acquired by thread %X", - (u32) walk_state->thread->thread_id, + "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", + (unsigned long)walk_state->thread->thread_id, acpi_ut_get_node_name(obj_desc->mutex.node), - (u32) obj_desc->mutex.owner_thread->thread_id)); + (unsigned long)obj_desc->mutex.owner_thread->thread_id)); return_ACPI_STATUS(AE_AML_NOT_OWNER); } /* - * The sync level of the mutex must be less than or - * equal to the current sync level + * The sync level of the mutex must be less than or equal to the current + * sync level */ if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { ACPI_ERROR((AE_INFO, @@ -298,11 +302,15 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, acpi_ex_unlink_mutex(obj_desc); - /* Release the mutex */ + /* Release the mutex, special case for Global Lock */ - status = acpi_ex_system_release_mutex(obj_desc); + if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { + status = acpi_ev_release_global_lock(); + } else { + acpi_os_release_mutex(obj_desc->mutex.os_mutex); + } - /* Update the mutex and walk state, restore sync_level before acquire */ + /* Update the mutex and restore sync_level */ obj_desc->mutex.owner_thread = NULL; walk_state->thread->current_sync_level = @@ -321,39 +329,49 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, * * DESCRIPTION: Release all mutexes held by this thread * + * NOTE: This function is called as the thread is exiting the interpreter. + * Mutexes are not released when an individual control method is exited, but + * only when the parent thread actually exits the interpreter. This allows one + * method to acquire a mutex, and a different method to release it, as long as + * this is performed underneath a single parent control method. + * ******************************************************************************/ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) { union acpi_operand_object *next = thread->acquired_mutex_list; - union acpi_operand_object *this; - acpi_status status; + union acpi_operand_object *obj_desc; ACPI_FUNCTION_ENTRY(); /* Traverse the list of owned mutexes, releasing each one */ while (next) { - this = next; - next = this->mutex.next; + obj_desc = next; + next = obj_desc->mutex.next; + + obj_desc->mutex.prev = NULL; + obj_desc->mutex.next = NULL; + obj_desc->mutex.acquisition_depth = 0; + + /* Release the mutex, special case for Global Lock */ - this->mutex.acquisition_depth = 1; - this->mutex.prev = NULL; - this->mutex.next = NULL; + if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { - /* Release the mutex */ + /* Ignore errors */ - status = acpi_ex_system_release_mutex(this); - if (ACPI_FAILURE(status)) { - continue; + (void)acpi_ev_release_global_lock(); + } else { + acpi_os_release_mutex(obj_desc->mutex.os_mutex); } /* Mark mutex unowned */ - this->mutex.owner_thread = NULL; + obj_desc->mutex.owner_thread = NULL; /* Update Thread sync_level (Last mutex is the important one) */ - thread->current_sync_level = this->mutex.original_sync_level; + thread->current_sync_level = + obj_desc->mutex.original_sync_level; } } |