Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=c0d127b56937c3e72c2b1819161d2f6718eee877
Commit:     c0d127b56937c3e72c2b1819161d2f6718eee877
Parent:     724339d76d9407cd1a8ad32a9c1fdf64840cc51b
Author:     Alexey Starikovskiy <[EMAIL PROTECTED]>
AuthorDate: Thu Feb 15 16:12:23 2007 -0500
Committer:  Len Brown <[EMAIL PROTECTED]>
CommitDate: Thu Feb 15 16:13:16 2007 -0500

    ACPICA: fix AML mutex re-entrancy
    
    ACPI AML supports "serialized" methods which are protected
    by an implicit mutex.  The mutex is re-entrant for that AML thread
    to allow recursion.
    
    However, Linux implements notify() by creating a new AML thread.
    So for systems where notify() re-enters a serialized method,
    deadlock results.
    
    The fix is to use the Linux thread_id as the key to allowing
    re-entrancy, not the AML thread pointer.
    
    http://bugzilla.kernel.org/show_bug.cgi?id=5534
    
    Signed-off-by: Alexey Starikovskiy <[EMAIL PROTECTED]>
    Signed-off-by: Len Brown <[EMAIL PROTECTED]>
---
 drivers/acpi/dispatcher/dsmethod.c |   12 +++++-------
 drivers/acpi/executer/exdump.c     |    2 +-
 drivers/acpi/executer/exmutex.c    |   36 ++++++++++++++++--------------------
 drivers/acpi/utilities/utdelete.c  |    1 -
 include/acpi/acinterp.h            |    3 ++-
 include/acpi/acobject.h            |    2 +-
 6 files changed, 25 insertions(+), 31 deletions(-)

diff --git a/drivers/acpi/dispatcher/dsmethod.c 
b/drivers/acpi/dispatcher/dsmethod.c
index 1cbe619..1683e5c 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -231,10 +231,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node 
*method_node,
                 * Obtain the method mutex if necessary. Do not acquire mutex 
for a
                 * recursive call.
                 */
-               if (!walk_state ||
-                   !obj_desc->method.mutex->mutex.owner_thread ||
-                   (walk_state->thread !=
-                    obj_desc->method.mutex->mutex.owner_thread)) {
+               if (acpi_os_get_thread_id() !=
+                   obj_desc->method.mutex->mutex.owner_thread_id) {
                        /*
                         * Acquire the method mutex. This releases the 
interpreter if we
                         * block (and reacquires it before it returns)
@@ -248,14 +246,14 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node 
*method_node,
                        }
 
                        /* Update the mutex and walk info and save the original 
sync_level */
+                       obj_desc->method.mutex->mutex.owner_thread_id =
+                               acpi_os_get_thread_id();
 
                        if (walk_state) {
                                obj_desc->method.mutex->mutex.
                                    original_sync_level =
                                    walk_state->thread->current_sync_level;
 
-                               obj_desc->method.mutex->mutex.owner_thread =
-                                   walk_state->thread;
                                walk_state->thread->current_sync_level =
                                    obj_desc->method.sync_level;
                        } else {
@@ -569,7 +567,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object 
*method_desc,
 
                        acpi_os_release_mutex(method_desc->method.mutex->mutex.
                                              os_mutex);
-                       method_desc->method.mutex->mutex.owner_thread = NULL;
+                       method_desc->method.mutex->mutex.owner_thread_id = 
ACPI_MUTEX_NOT_ACQUIRED;
                }
        }
 
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index 68d283f..1a73c14 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -134,7 +134,7 @@ static struct acpi_exdump_info acpi_ex_dump_method[8] = {
 static struct acpi_exdump_info acpi_ex_dump_mutex[5] = {
        {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL},
        {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"},
-       {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"},
+       {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread_id), "Owner 
Thread"},
        {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth),
         "Acquire Depth"},
        {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"}
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index 5101bad..4eb883b 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -66,10 +66,9 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
  *
  
******************************************************************************/
 
-void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc,
+                         struct acpi_thread_state *thread)
 {
-       struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
-
        if (!thread) {
                return;
        }
@@ -174,16 +173,13 @@ acpi_ex_acquire_mutex(union acpi_operand_object 
*time_desc,
 
        /* Support for multiple acquires by the owning thread */
 
-       if (obj_desc->mutex.owner_thread) {
-               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
-                        */
-                       obj_desc->mutex.acquisition_depth++;
-                       return_ACPI_STATUS(AE_OK);
-               }
+       if (obj_desc->mutex.owner_thread_id == acpi_os_get_thread_id()) {
+               /*
+                * 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. Special case for Global Lock */
@@ -206,7 +202,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
 
        /* Have the mutex: update mutex and walk info and save the sync_level */
 
-       obj_desc->mutex.owner_thread = walk_state->thread;
+       obj_desc->mutex.owner_thread_id = acpi_os_get_thread_id();
        obj_desc->mutex.acquisition_depth = 1;
        obj_desc->mutex.original_sync_level =
            walk_state->thread->current_sync_level;
@@ -246,7 +242,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
 
        /* The mutex must have been previously acquired in order to release it 
*/
 
-       if (!obj_desc->mutex.owner_thread) {
+       if (!obj_desc->mutex.owner_thread_id) {
                ACPI_ERROR((AE_INFO,
                            "Cannot release Mutex [%4.4s], not acquired",
                            acpi_ut_get_node_name(obj_desc->mutex.node)));
@@ -266,14 +262,14 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
         * The Mutex is owned, but this thread must be the owner.
         * Special case for Global Lock, any thread can release
         */
-       if ((obj_desc->mutex.owner_thread->thread_id !=
+       if ((obj_desc->mutex.owner_thread_id !=
             walk_state->thread->thread_id)
            && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) {
                ACPI_ERROR((AE_INFO,
                            "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),
-                           (unsigned 
long)obj_desc->mutex.owner_thread->thread_id));
+                           (unsigned long)obj_desc->mutex.owner_thread_id));
                return_ACPI_STATUS(AE_AML_NOT_OWNER);
        }
 
@@ -300,7 +296,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
 
        /* Unlink the mutex from the owner's list */
 
-       acpi_ex_unlink_mutex(obj_desc);
+       acpi_ex_unlink_mutex(obj_desc, walk_state->thread);
 
        /* Release the mutex, special case for Global Lock */
 
@@ -312,7 +308,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
 
        /* Update the mutex and restore sync_level */
 
-       obj_desc->mutex.owner_thread = NULL;
+       obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
        walk_state->thread->current_sync_level =
            obj_desc->mutex.original_sync_level;
 
@@ -367,7 +363,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state 
*thread)
 
                /* Mark mutex unowned */
 
-               obj_desc->mutex.owner_thread = NULL;
+               obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
 
                /* Update Thread sync_level (Last mutex is the important one) */
 
diff --git a/drivers/acpi/utilities/utdelete.c 
b/drivers/acpi/utilities/utdelete.c
index f777ceb..673a0ca 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -170,7 +170,6 @@ static void acpi_ut_delete_internal_obj(union 
acpi_operand_object *object)
                        acpi_os_delete_mutex(object->mutex.os_mutex);
                        acpi_gbl_global_lock_mutex = NULL;
                } else {
-                       acpi_ex_unlink_mutex(object);
                        acpi_os_delete_mutex(object->mutex.os_mutex);
                }
                break;
diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h
index ce7c9d6..73967c8 100644
--- a/include/acpi/acinterp.h
+++ b/include/acpi/acinterp.h
@@ -253,7 +253,8 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
 
 void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread);
 
-void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc);
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc,
+                         struct acpi_thread_state *thread);
 
 /*
  * exprep - ACPI AML execution - prep utilities
diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h
index 04e9735..5206d61 100644
--- a/include/acpi/acobject.h
+++ b/include/acpi/acobject.h
@@ -155,7 +155,7 @@ struct acpi_object_event {
 struct acpi_object_mutex {
        ACPI_OBJECT_COMMON_HEADER u8 sync_level;        /* 0-15, specified in 
Mutex() call */
        u16 acquisition_depth;  /* Allow multiple Acquires, same thread */
-       struct acpi_thread_state *owner_thread; /* Current owner of the mutex */
+       acpi_thread_id owner_thread_id; /* Current owner of the mutex */
        acpi_mutex os_mutex;    /* Actual OS synchronization object */
        union acpi_operand_object *prev;        /* Link for list of acquired 
mutexes */
        union acpi_operand_object *next;        /* Link for list of acquired 
mutexes */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to