* [PATCH 0/3] acpi: semaphore removal -v2 @ 2008-08-07 14:59 Daniel Walker 2008-08-07 14:59 ` [PATCH 1/5] add mutex_lock_timeout() Daniel Walker 0 siblings, 1 reply; 18+ messages in thread From: Daniel Walker @ 2008-08-07 14:59 UTC (permalink / raw) To: linux-acpi Cc: Robert Moore, Andi Kleen, Matthew Wilcox, Peter Zijlstra, Zhao Yakui, Dave Chinner, Ingo Molnar I did a lot of cleanup .. I added the mutex_lock_timeout function which I didn't have in the last set of patches. I also trimmed down the semaphore to completions patch. So ACPI keeps the name "semaphore" internally, but it can only be initialized with "0" initial units. It means that ACPI developers can't randomly use the semaphore as a mutex (which I haven't seen anyway). Daniel ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1/5] add mutex_lock_timeout() 2008-08-07 14:59 [PATCH 0/3] acpi: semaphore removal -v2 Daniel Walker @ 2008-08-07 14:59 ` Daniel Walker 2008-08-07 14:59 ` [PATCH 2/5] acpi: add real mutex function calls Daniel Walker 0 siblings, 1 reply; 18+ messages in thread From: Daniel Walker @ 2008-08-07 14:59 UTC (permalink / raw) To: linux-acpi Cc: Robert Moore, Andi Kleen, Matthew Wilcox, Peter Zijlstra, Zhao Yakui, Dave Chinner, Ingo Molnar Adds mutex_lock_timeout() and mutex_lock_timeout_nested() used inside ACPI. Cc: linux-acpi@vger.kernel.org Signed-off-by: Daniel Walker <dwalker@mvista.com> --- include/asm-generic/mutex-dec.h | 23 ++++++++++++ include/asm-generic/mutex-null.h | 3 ++ include/asm-generic/mutex-xchg.h | 23 ++++++++++++ include/asm-x86/mutex_32.h | 21 +++++++++++ include/asm-x86/mutex_64.h | 21 +++++++++++ include/linux/mutex.h | 8 ++++ kernel/mutex.c | 71 +++++++++++++++++++++++++++++++++----- 7 files changed, 161 insertions(+), 9 deletions(-) diff --git a/include/asm-generic/mutex-dec.h b/include/asm-generic/mutex-dec.h index ed108be..eddc8c4 100644 --- a/include/asm-generic/mutex-dec.h +++ b/include/asm-generic/mutex-dec.h @@ -109,4 +109,27 @@ __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) #endif } +/** + * __mutex_fastpath_lock_timeout - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 1 + * This function will need to accept two arguments. + * @timeout: Timeout value as second argument to fail_fn. + * + * Change the count from 1 to a value lower than 1, and call <fail_fn> if + * it wasn't 1 originally. This function returns 0 if the fastpath succeeds, + * or anything the slow path function returns. + */ +static inline int +__mutex_fastpath_lock_timeout(atomic_t *count, long timeout, + int (*fail_fn)(atomic_t *, long)) +{ + if (unlikely(atomic_dec_return(count) < 0)) + return fail_fn(count, timeout); + else { + smp_mb(); + return 0; + } +} #endif diff --git a/include/asm-generic/mutex-null.h b/include/asm-generic/mutex-null.h index e1bbbc7..192a756 100644 --- a/include/asm-generic/mutex-null.h +++ b/include/asm-generic/mutex-null.h @@ -14,6 +14,9 @@ #define __mutex_fastpath_lock_retval(count, fail_fn) fail_fn(count) #define __mutex_fastpath_unlock(count, fail_fn) fail_fn(count) #define __mutex_fastpath_trylock(count, fail_fn) fail_fn(count) + +#define __mutex_fastpath_timeout(count, timeout, fail_fn) \ + fail_fn(count, timeout) #define __mutex_slowpath_needs_to_unlock() 1 #endif diff --git a/include/asm-generic/mutex-xchg.h b/include/asm-generic/mutex-xchg.h index 7b9cd2c..34ccdd3 100644 --- a/include/asm-generic/mutex-xchg.h +++ b/include/asm-generic/mutex-xchg.h @@ -115,4 +115,27 @@ __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) return prev; } +/** + * __mutex_fastpath_lock_timeout - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 1 + * This function will need to accept two arguments. + * @timeout: Timeout value as second argument to fail_fn. + * + * Change the count from 1 to a value lower than 1, and call <fail_fn> if it + * wasn't 1 originally. This function returns 0 if the fastpath succeeds, + * or anything the slow path function returns + */ +static inline int +__mutex_fastpath_lock_timeout(atomic_t *count, timeout, + int (*fail_fn)(atomic_t *, long)) +{ + if (unlikely(atomic_xchg(count, 0) != 1)) + return fail_fn(count, timeout); + else { + smp_mb(); + return 0; + } +} #endif diff --git a/include/asm-x86/mutex_32.h b/include/asm-x86/mutex_32.h index 73e928e..7d4696d 100644 --- a/include/asm-x86/mutex_32.h +++ b/include/asm-x86/mutex_32.h @@ -122,4 +122,25 @@ static inline int __mutex_fastpath_trylock(atomic_t *count, #endif } +/** + * __mutex_fastpath_lock_timeout - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 1 + * This function will need to accept two arguments. + * @timeout: Timeout value as second argument to fail_fn. + * + * Change the count from 1 to a value lower than 1, and call <fail_fn> if it + * wasn't 1 originally. This function returns 0 if the fastpath succeeds, + * or anything the slow path function returns + */ +static inline int +__mutex_fastpath_lock_timeout(atomic_t *count, long timeout, + int (*fail_fn)(atomic_t *, long)) +{ + if (unlikely(atomic_dec_return(count) < 0)) + return fail_fn(count, timeout); + else + return 0; +} #endif diff --git a/include/asm-x86/mutex_64.h b/include/asm-x86/mutex_64.h index f3fae9b..3e63b61 100644 --- a/include/asm-x86/mutex_64.h +++ b/include/asm-x86/mutex_64.h @@ -97,4 +97,25 @@ static inline int __mutex_fastpath_trylock(atomic_t *count, return 0; } +/** + * __mutex_fastpath_lock_timeout - try to take the lock by moving the count + * from 1 to a 0 value + * @count: pointer of type atomic_t + * @fail_fn: function to call if the original value was not 1 + * This function will need to accept two arguments. + * @timeout: Timeout value as second argument to fail_fn. + * + * Change the count from 1 to a value lower than 1, and call <fail_fn> if + * it wasn't 1 originally. This function returns 0 if the fastpath succeeds, + * or anything the slow path function returns + */ +static inline int +__mutex_fastpath_lock_timeout(atomic_t *count, long timeout, + int (*fail_fn)(atomic_t *, long)) +{ + if (unlikely(atomic_dec_return(count) < 0)) + return fail_fn(count, timeout); + else + return 0; +} #endif diff --git a/include/linux/mutex.h b/include/linux/mutex.h index bc6da10..bb84cd4 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -127,18 +127,26 @@ extern int __must_check mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass); extern int __must_check mutex_lock_killable_nested(struct mutex *lock, unsigned int subclass); +extern int __must_check +mutex_lock_timeout_nested(struct mutex *lock, long jiffies, + unsigned int subclass); #define mutex_lock(lock) mutex_lock_nested(lock, 0) #define mutex_lock_interruptible(lock) mutex_lock_interruptible_nested(lock, 0) #define mutex_lock_killable(lock) mutex_lock_killable_nested(lock, 0) +#define mutex_lock_timeout(lock, jiffies) \ + mutex_lock_timeout_nested(lock, jiffies, 0) #else extern void mutex_lock(struct mutex *lock); extern int __must_check mutex_lock_interruptible(struct mutex *lock); extern int __must_check mutex_lock_killable(struct mutex *lock); +extern int __must_check mutex_lock_timeout(struct mutex *lock, long jiffies); # define mutex_lock_nested(lock, subclass) mutex_lock(lock) # define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock) # define mutex_lock_killable_nested(lock, subclass) mutex_lock_killable(lock) +# define mutex_lock_timeout_nested(lock, jiffies, subclass) \ + mutex_lock_timeout(lock, jiffies) #endif /* diff --git a/kernel/mutex.c b/kernel/mutex.c index 12c779d..cf06f62 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -124,8 +124,8 @@ EXPORT_SYMBOL(mutex_unlock); * Lock a mutex (possibly interruptible), slowpath: */ static inline int __sched -__mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, - unsigned long ip) +__mutex_lock_common(struct mutex *lock, long state, long timeout, + unsigned int subclass, unsigned long ip) { struct task_struct *task = current; struct mutex_waiter waiter; @@ -179,7 +179,22 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, /* didnt get the lock, go to sleep: */ spin_unlock_mutex(&lock->wait_lock, flags); - schedule(); + if (timeout == MAX_SCHEDULE_TIMEOUT) + schedule(); + else { + timeout = schedule_timeout(timeout); + + if (timeout == 0) { + spin_lock_mutex(&lock->wait_lock, flags); + mutex_remove_waiter(lock, &waiter, + task_thread_info(task)); + mutex_release(&lock->dep_map, 1, ip); + spin_unlock_mutex(&lock->wait_lock, flags); + + debug_mutex_free_waiter(&waiter); + return -ETIME; + } + } spin_lock_mutex(&lock->wait_lock, flags); } @@ -205,7 +220,8 @@ void __sched mutex_lock_nested(struct mutex *lock, unsigned int subclass) { might_sleep(); - __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, subclass, _RET_IP_); + __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT, + subclass, _RET_IP_); } EXPORT_SYMBOL_GPL(mutex_lock_nested); @@ -214,7 +230,8 @@ int __sched mutex_lock_killable_nested(struct mutex *lock, unsigned int subclass) { might_sleep(); - return __mutex_lock_common(lock, TASK_KILLABLE, subclass, _RET_IP_); + return __mutex_lock_common(lock, TASK_KILLABLE, MAX_SCHEDULE_TIMEOUT, + subclass, _RET_IP_); } EXPORT_SYMBOL_GPL(mutex_lock_killable_nested); @@ -222,10 +239,23 @@ int __sched mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass) { might_sleep(); - return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, subclass, _RET_IP_); + return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT, + subclass, _RET_IP_); } EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested); + + +int __sched +mutex_lock_timeout_nested(struct mutex *lock, long timeout, + unsigned int subclass) +{ + might_sleep(); + return __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, timeout, + subclass, _RET_IP_); +} +EXPORT_SYMBOL_GPL(mutex_lock_timeout_nested); + #endif /* @@ -285,6 +315,9 @@ __mutex_lock_killable_slowpath(atomic_t *lock_count); static noinline int __sched __mutex_lock_interruptible_slowpath(atomic_t *lock_count); +static noinline int __sched +__mutex_lock_timeout_slowpath(atomic_t *lock_count, long timeout); + /*** * mutex_lock_interruptible - acquire the mutex, interruptable * @lock: the mutex to be acquired @@ -313,12 +346,21 @@ int __sched mutex_lock_killable(struct mutex *lock) } EXPORT_SYMBOL(mutex_lock_killable); +int __sched mutex_lock_timeout(struct mutex *lock, long timeout) +{ + might_sleep(); + return __mutex_fastpath_lock_timeout + (&lock->count, timeout, __mutex_lock_timeout_slowpath); +} +EXPORT_SYMBOL(mutex_lock_timeout); + static noinline void __sched __mutex_lock_slowpath(atomic_t *lock_count) { struct mutex *lock = container_of(lock_count, struct mutex, count); - __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0, _RET_IP_); + __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT, + _RET_IP_); } static noinline int __sched @@ -326,7 +368,8 @@ __mutex_lock_killable_slowpath(atomic_t *lock_count) { struct mutex *lock = container_of(lock_count, struct mutex, count); - return __mutex_lock_common(lock, TASK_KILLABLE, 0, _RET_IP_); + return __mutex_lock_common(lock, TASK_KILLABLE, MAX_SCHEDULE_TIMEOUT, + _RET_IP_); } static noinline int __sched @@ -334,7 +377,17 @@ __mutex_lock_interruptible_slowpath(atomic_t *lock_count) { struct mutex *lock = container_of(lock_count, struct mutex, count); - return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, 0, _RET_IP_); + return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, + MAX_SCHEDULE_TIMEOUT, _RET_IP_); +} + +static noinline int __sched +__mutex_lock_timeout_slowpath(atomic_t *lock_count, long timeout) +{ + struct mutex *lock = container_of(lock_count, struct mutex, count); + + return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, timeout, + _RET_IP_); } #endif -- 1.5.5.1.32.gba7d2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 2/5] acpi: add real mutex function calls 2008-08-07 14:59 ` [PATCH 1/5] add mutex_lock_timeout() Daniel Walker @ 2008-08-07 14:59 ` Daniel Walker 2008-08-07 14:59 ` [PATCH 3/5] acpi: add lockdep magic Daniel Walker 0 siblings, 1 reply; 18+ messages in thread From: Daniel Walker @ 2008-08-07 14:59 UTC (permalink / raw) To: linux-acpi Cc: Robert Moore, Andi Kleen, Matthew Wilcox, Peter Zijlstra, Zhao Yakui, Dave Chinner, Ingo Molnar Instead of re-using semaphores for the mutex operation, I've add usage of the kernel mutex for the acpi os mutex implementation. Cc: linux-acpi@vger.kernel.org Signed-off-by: Daniel Walker <dwalker@mvista.com> --- drivers/acpi/osl.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++ include/acpi/acpiosxf.h | 11 +----- 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 235a138..c0184f4 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -871,6 +871,92 @@ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) return AE_OK; } +acpi_status +acpi_os_create_mutex(acpi_mutex *handle) +{ + struct mutex *mutex = NULL; + + mutex = acpi_os_allocate(sizeof(struct mutex)); + if (!mutex) + return AE_NO_MEMORY; + memset(mutex, 0, sizeof(struct mutex)); + + mutex_init(mutex); + + *handle = (acpi_handle *) mutex; + + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating mutex[%p].\n", + *handle)); + + return AE_OK; +} + +acpi_status acpi_os_delete_mutex(acpi_mutex handle) +{ + struct mutex *mutex = (struct mutex *)handle; + + if (!mutex) + return AE_BAD_PARAMETER; + + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting mutex[%p].\n", handle)); + + BUG_ON(mutex_is_locked(mutex)); + kfree(mutex); + mutex = NULL; + + return AE_OK; +} + +acpi_status acpi_os_acquire_mutex(acpi_mutex handle, u16 timeout) +{ + acpi_status status = AE_OK; + struct mutex *mutex = (struct mutex *)handle; + long jiffies; + int ret = 0; + + if (!mutex) + return AE_BAD_PARAMETER; + + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for mutex[%p|%d]\n", + handle, timeout)); + + if (timeout == ACPI_WAIT_FOREVER) + jiffies = MAX_SCHEDULE_TIMEOUT; + else + jiffies = msecs_to_jiffies(timeout); + + ret = mutex_lock_timeout(mutex, jiffies); + if (ret == -ETIME) + status = AE_TIME; + + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "Failed to acquire mutex[%p|%d], %s", + handle, timeout, + acpi_format_exception(status))); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "Acquired mutex[%p|%d]", handle, + timeout)); + } + + return status; +} + +acpi_status acpi_os_release_mutex(acpi_mutex handle) +{ + struct mutex *mutex = (struct mutex *)handle; + + if (!mutex) + return AE_BAD_PARAMETER; + + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling mutex[%p]\n", handle)); + + mutex_unlock(mutex); + + return AE_OK; +} + #ifdef ACPI_FUTURE_USAGE u32 acpi_os_get_line(char *buffer) { diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 3f93a6b..9032ec3 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -125,18 +125,11 @@ acpi_status acpi_os_signal_semaphore(acpi_semaphore handle, u32 units); */ acpi_status acpi_os_create_mutex(acpi_mutex * out_handle); -void acpi_os_delete_mutex(acpi_mutex handle); +acpi_status acpi_os_delete_mutex(acpi_mutex handle); acpi_status acpi_os_acquire_mutex(acpi_mutex handle, u16 timeout); -void acpi_os_release_mutex(acpi_mutex handle); - -/* Temporary macros for Mutex* interfaces, map to existing semaphore xfaces */ - -#define acpi_os_create_mutex(out_handle) acpi_os_create_semaphore (1, 1, out_handle) -#define acpi_os_delete_mutex(handle) (void) acpi_os_delete_semaphore (handle) -#define acpi_os_acquire_mutex(handle,time) acpi_os_wait_semaphore (handle, 1, time) -#define acpi_os_release_mutex(handle) (void) acpi_os_signal_semaphore (handle, 1) +acpi_status acpi_os_release_mutex(acpi_mutex handle); /* * Memory allocation and mapping -- 1.5.5.1.32.gba7d2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 3/5] acpi: add lockdep magic 2008-08-07 14:59 ` [PATCH 2/5] acpi: add real mutex function calls Daniel Walker @ 2008-08-07 14:59 ` Daniel Walker 2008-08-07 14:59 ` [PATCH 4/5] acpi: remove interpreter lock Daniel Walker 0 siblings, 1 reply; 18+ messages in thread From: Daniel Walker @ 2008-08-07 14:59 UTC (permalink / raw) To: linux-acpi Cc: Robert Moore, Andi Kleen, Matthew Wilcox, Peter Zijlstra, Zhao Yakui, Dave Chinner, Ingo Molnar Add lockdep integration for the ACPI mutex usage. Cc: linux-acpi@vger.kernel.org Signed-off-by: Daniel Walker <dwalker@mvista.com> --- drivers/acpi/dispatcher/dsmethod.c | 4 ++++ drivers/acpi/executer/excreate.c | 7 ++++++- drivers/acpi/executer/exmutex.c | 5 +++-- drivers/acpi/executer/exsystem.c | 3 ++- drivers/acpi/namespace/nsaccess.c | 5 +++++ drivers/acpi/osl.c | 3 ++- drivers/acpi/utilities/utmutex.c | 6 ++++++ include/acpi/acpiosxf.h | 6 ++++-- 8 files changed, 32 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 4613b9c..a3cf3d4 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -130,6 +130,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) static acpi_status acpi_ds_create_method_mutex(union acpi_operand_object *method_desc) { + static struct lock_class_key method_mutex; union acpi_operand_object *mutex_desc; acpi_status status; @@ -149,6 +150,9 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc) return_ACPI_STATUS(status); } + lockdep_set_class((struct mutex *)&mutex_desc->mutex.os_mutex, + &method_mutex); + mutex_desc->mutex.sync_level = method_desc->method.sync_level; method_desc->method.mutex = mutex_desc; return_ACPI_STATUS(AE_OK); diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index ad09696..4397015 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -222,6 +222,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state) { acpi_status status = AE_OK; union acpi_operand_object *obj_desc; + static struct lock_class_key interpreter_class; ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS); @@ -235,11 +236,15 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state) /* Create the actual OS Mutex */ - status = acpi_os_create_mutex(&obj_desc->mutex.os_mutex); + status = + acpi_os_create_mutex(&obj_desc->mutex.os_mutex); if (ACPI_FAILURE(status)) { goto cleanup; } + lockdep_set_class((struct mutex *)obj_desc->mutex.os_mutex, + &interpreter_class); + /* Init object and attach to NS node */ obj_desc->mutex.sync_level = diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index a8bf3d7..6472a24 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -176,8 +176,9 @@ acpi_ex_acquire_mutex_object(u16 timeout, if (obj_desc == acpi_gbl_global_lock_mutex) { status = acpi_ev_acquire_global_lock(timeout); } else { - status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, - timeout); + status = + acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, + timeout); } if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index 68990f1..1a4aa5e 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -108,7 +108,8 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) * ******************************************************************************/ -acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) +acpi_status +acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) { acpi_status status; diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index c39a7f6..293c0ba 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -64,6 +64,7 @@ ACPI_MODULE_NAME("nsaccess") ******************************************************************************/ acpi_status acpi_ns_root_initialize(void) { + static struct lock_class_key ns_root_mutex; acpi_status status; const struct acpi_predefined_names *init_val = NULL; struct acpi_namespace_node *new_node; @@ -205,6 +206,10 @@ acpi_status acpi_ns_root_initialize(void) goto unlock_and_exit; } + lockdep_set_class((struct mutex *) + obj_desc->mutex.os_mutex, + &ns_root_mutex); + /* Special case for ACPI Global Lock */ if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c0184f4..7340baf 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -907,7 +907,8 @@ acpi_status acpi_os_delete_mutex(acpi_mutex handle) return AE_OK; } -acpi_status acpi_os_acquire_mutex(acpi_mutex handle, u16 timeout) +acpi_status +acpi_os_acquire_mutex(acpi_mutex handle, u16 timeout) { acpi_status status = AE_OK; struct mutex *mutex = (struct mutex *)handle; diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c index 7331dde..3f7f16c 100644 --- a/drivers/acpi/utilities/utmutex.c +++ b/drivers/acpi/utilities/utmutex.c @@ -134,6 +134,7 @@ void acpi_ut_mutex_terminate(void) static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id) { + static struct lock_class_key utility_class_keys[ACPI_MAX_MUTEX]; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id); @@ -145,6 +146,11 @@ static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id) if (!acpi_gbl_mutex_info[mutex_id].mutex) { status = acpi_os_create_mutex(&acpi_gbl_mutex_info[mutex_id].mutex); + + lockdep_set_class( + (struct mutex *)acpi_gbl_mutex_info[mutex_id].mutex, + &utility_class_keys[mutex_id]); + acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; acpi_gbl_mutex_info[mutex_id].use_count = 0; diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 9032ec3..0f4247b 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -123,11 +123,13 @@ acpi_status acpi_os_signal_semaphore(acpi_semaphore handle, u32 units); /* * Mutex primitives */ -acpi_status acpi_os_create_mutex(acpi_mutex * out_handle); +acpi_status +acpi_os_create_mutex(acpi_mutex * handle); acpi_status acpi_os_delete_mutex(acpi_mutex handle); -acpi_status acpi_os_acquire_mutex(acpi_mutex handle, u16 timeout); +acpi_status +acpi_os_acquire_mutex(acpi_mutex handle, u16 timeout); acpi_status acpi_os_release_mutex(acpi_mutex handle); -- 1.5.5.1.32.gba7d2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 4/5] acpi: remove interpreter lock 2008-08-07 14:59 ` [PATCH 3/5] acpi: add lockdep magic Daniel Walker @ 2008-08-07 14:59 ` Daniel Walker 2008-08-07 14:59 ` [PATCH 5/5] acpi: semaphore removal Daniel Walker ` (2 more replies) 0 siblings, 3 replies; 18+ messages in thread From: Daniel Walker @ 2008-08-07 14:59 UTC (permalink / raw) To: linux-acpi Cc: Robert Moore, Andi Kleen, Matthew Wilcox, Peter Zijlstra, Zhao Yakui, Dave Chinner, Ingo Molnar Lockdep has identified this lock as a source of potential deadlock in acpi. After reviewing the lock it's not clear what it's protecting. I invite anyone who might know what the point of the lock is to describe it. In the mean time I removed the lock completely which, so far, hasn't had any ill effects on my test machines. Cc: linux-acpi@vger.kernel.org Signed-off-by: Daniel Walker <dwalker@mvista.com> --- drivers/acpi/dispatcher/dsmethod.c | 5 -- drivers/acpi/events/evregion.c | 30 --------- drivers/acpi/events/evxface.c | 5 -- drivers/acpi/executer/exsystem.c | 21 ------ drivers/acpi/executer/exutils.c | 127 ------------------------------------ drivers/acpi/namespace/nseval.c | 6 -- drivers/acpi/namespace/nsinit.c | 6 -- drivers/acpi/namespace/nsxfeval.c | 5 +- 8 files changed, 1 insertions(+), 204 deletions(-) diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index a3cf3d4..0b8af17 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -86,10 +86,6 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) if (acpi_gbl_exception_handler) { - /* Exit the interpreter, allow handler to execute methods */ - - acpi_ex_exit_interpreter(); - /* * Handler can map the exception code to anything it wants, including * AE_OK, in which case the executing method will not be aborted. @@ -101,7 +97,6 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) walk_state->opcode, walk_state->aml_offset, NULL); - acpi_ex_enter_interpreter(); } #ifdef ACPI_DISASSEMBLER if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index 236fbd1..4eb4c30 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -338,21 +338,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, return_ACPI_STATUS(AE_NOT_EXIST); } - /* - * We must exit the interpreter because the region - * setup will potentially execute control methods - * (e.g., _REG method for this region) - */ - acpi_ex_exit_interpreter(); - status = region_setup(region_obj, ACPI_REGION_ACTIVATE, handler_desc->address_space.context, ®ion_context); - /* Re-enter the interpreter */ - - acpi_ex_enter_interpreter(); - /* Check for failure of the Region Setup */ if (ACPI_FAILURE(status)) { @@ -397,16 +386,6 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, acpi_ut_get_region_name(region_obj->region. space_id))); - if (!(handler_desc->address_space.handler_flags & - ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { - /* - * For handlers other than the default (supplied) handlers, we must - * exit the interpreter because the handler *might* block -- we don't - * know what it will do, so we can't hold the lock on the intepreter. - */ - acpi_ex_exit_interpreter(); - } - /* Call the handler */ status = handler(function, address, bit_width, value, @@ -419,15 +398,6 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, space_id))); } - if (!(handler_desc->address_space.handler_flags & - ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { - /* - * We just returned from a non-default handler, we must re-enter the - * interpreter - */ - acpi_ex_enter_interpreter(); - } - return_ACPI_STATUS(status); } diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index 94a6efe..4e4bd7a 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -773,10 +773,6 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) return (AE_BAD_PARAMETER); } - /* Must lock interpreter to prevent race conditions */ - - acpi_ex_enter_interpreter(); - status = acpi_ex_acquire_mutex_object(timeout, acpi_gbl_global_lock_mutex, acpi_os_get_thread_id()); @@ -788,7 +784,6 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) *handle = acpi_gbl_global_lock_handle; } - acpi_ex_exit_interpreter(); return (status); } diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index 1a4aa5e..6c82143 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -75,19 +75,12 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) if (status == AE_TIME) { - /* We must wait, so unlock the interpreter */ - - acpi_ex_relinquish_interpreter(); - status = acpi_os_wait_semaphore(semaphore, 1, timeout); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*** Thread awake after blocking, %s\n", acpi_format_exception(status))); - /* Reacquire the interpreter */ - - acpi_ex_reacquire_interpreter(); } return_ACPI_STATUS(status); @@ -122,19 +115,12 @@ acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) if (status == AE_TIME) { - /* We must wait, so unlock the interpreter */ - - acpi_ex_relinquish_interpreter(); - status = acpi_os_acquire_mutex(mutex, timeout); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*** Thread awake after blocking, %s\n", acpi_format_exception(status))); - /* Reacquire the interpreter */ - - acpi_ex_reacquire_interpreter(); } return_ACPI_STATUS(status); @@ -197,15 +183,8 @@ acpi_status acpi_ex_system_do_suspend(acpi_integer how_long) { ACPI_FUNCTION_ENTRY(); - /* Since this thread will sleep, we must release the interpreter */ - - acpi_ex_relinquish_interpreter(); - acpi_os_sleep(how_long); - /* And now we must get the interpreter again */ - - acpi_ex_reacquire_interpreter(); return (AE_OK); } diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 86c0388..815defd 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -71,133 +71,6 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base); #ifndef ACPI_NO_METHOD_EXECUTION /******************************************************************************* * - * FUNCTION: acpi_ex_enter_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Enter the interpreter execution region. Failure to enter - * the interpreter region is a fatal system error. Used in - * conjunction with exit_interpreter. - * - ******************************************************************************/ - -void acpi_ex_enter_interpreter(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ex_enter_interpreter); - - status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not acquire AML Interpreter mutex")); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_reacquire_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Reacquire the interpreter execution region from within the - * interpreter code. Failure to enter the interpreter region is a - * fatal system error. Used in conjuction with - * relinquish_interpreter - * - ******************************************************************************/ - -void acpi_ex_reacquire_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_reacquire_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter, - * since it was not actually released by acpi_ex_relinquish_interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_enter_interpreter(); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_exit_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Exit the interpreter execution region. This is the top level - * routine used to exit the interpreter when all processing has - * been completed. - * - ******************************************************************************/ - -void acpi_ex_exit_interpreter(void) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE(ex_exit_interpreter); - - status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not release AML Interpreter mutex")); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_relinquish_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Exit the interpreter execution region, from within the - * interpreter - before attempting an operation that will possibly - * block the running thread. - * - * Cases where the interpreter is unlocked internally - * 1) Method to be blocked on a Sleep() AML opcode - * 2) Method to be blocked on an Acquire() AML opcode - * 3) Method to be blocked on a Wait() AML opcode - * 4) Method to be blocked to acquire the global lock - * 5) Method to be blocked waiting to execute a serialized control method - * that is currently executing - * 6) About to invoke a user-installed opregion handler - * - ******************************************************************************/ - -void acpi_ex_relinquish_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_relinquish_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_exit_interpreter(); - } - - return_VOID; -} - -/******************************************************************************* - * * FUNCTION: acpi_ex_truncate_for32bit_table * * PARAMETERS: obj_desc - Object to be truncated diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index d369164..2a98cc7 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -72,8 +72,6 @@ ACPI_MODULE_NAME("nseval") * DESCRIPTION: Execute a control method or return the current value of an * ACPI namespace object. * - * MUTEX: Locks interpreter - * ******************************************************************************/ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) { @@ -189,9 +187,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) * Execute the method via the interpreter. The interpreter is locked * here before calling into the AML parser */ - acpi_ex_enter_interpreter(); status = acpi_ps_execute_method(info); - acpi_ex_exit_interpreter(); } else { /* * 2) Object is not a method, return its current value @@ -213,13 +209,11 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) * resolution, we must lock it because we could access an opregion. * The opregion access code assumes that the interpreter is locked. */ - acpi_ex_enter_interpreter(); /* Function has a strange interface */ status = acpi_ex_resolve_node_to_value(&info->resolved_node, NULL); - acpi_ex_exit_interpreter(); /* * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index e4c5751..e6c93d4 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -270,11 +270,6 @@ acpi_ns_init_one_object(acpi_handle obj_handle, } /* - * Must lock the interpreter before executing AML code - */ - acpi_ex_enter_interpreter(); - - /* * Each of these types can contain executable AML code within the * declaration. */ @@ -333,7 +328,6 @@ acpi_ns_init_one_object(acpi_handle obj_handle, * We ignore errors from above, and always return OK, since we don't want * to abort the walk on any single error. */ - acpi_ex_exit_interpreter(); return (AE_OK); } diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index 38be586..64c63f0 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -322,15 +322,12 @@ acpi_evaluate_object(acpi_handle handle, if (info->return_object) { /* - * Delete the internal return object. NOTE: Interpreter must be - * locked to avoid race condition. + * Delete the internal return object. */ - acpi_ex_enter_interpreter(); /* Remove one reference on the return object (should delete it) */ acpi_ut_remove_reference(info->return_object); - acpi_ex_exit_interpreter(); } cleanup: -- 1.5.5.1.32.gba7d2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 5/5] acpi: semaphore removal 2008-08-07 14:59 ` [PATCH 4/5] acpi: remove interpreter lock Daniel Walker @ 2008-08-07 14:59 ` Daniel Walker 2008-08-08 0:34 ` Matthew Wilcox 2008-08-08 2:44 ` Andi Kleen 2008-08-07 20:32 ` [PATCH 4/5] acpi: remove interpreter lock Moore, Robert 2008-08-08 2:40 ` Andi Kleen 2 siblings, 2 replies; 18+ messages in thread From: Daniel Walker @ 2008-08-07 14:59 UTC (permalink / raw) To: linux-acpi Cc: Robert Moore, Andi Kleen, Matthew Wilcox, Peter Zijlstra, Zhao Yakui, Dave Chinner, Ingo Molnar The semaphore usage in ACPI is more like completions. The ASL functions getting implemented here are signals which follow a "wait for", signaled, or reset format. This implements the ACPI signaling methods with the Linux completion API, instead of using semaphores. completion_done() taken from Dave Chinner. Cc: linux-acpi@vger.kernel.org Cc: Dave Chinner <david@fromorbit.com> Signed-off-by: Daniel Walker <dwalker@mvista.com> --- drivers/acpi/osl.c | 54 ++++++++++++++++++++++--------------------- include/linux/completion.h | 19 +++++++++++++++ 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 7340baf..2e4ae01 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -43,7 +43,7 @@ #include <linux/ioport.h> #include <linux/list.h> #include <linux/jiffies.h> -#include <linux/semaphore.h> +#include <linux/completion.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -768,42 +768,44 @@ void acpi_os_delete_lock(acpi_spinlock handle) acpi_status acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) { - struct semaphore *sem = NULL; + struct completion *comp = NULL; - sem = acpi_os_allocate(sizeof(struct semaphore)); - if (!sem) + BUG_ON(initial_units); + + comp = acpi_os_allocate(sizeof(struct completion)); + if (!comp) return AE_NO_MEMORY; - memset(sem, 0, sizeof(struct semaphore)); + memset(comp, 0, sizeof(struct completion)); - sema_init(sem, initial_units); + init_completion(comp); - *handle = (acpi_handle *) sem; + *handle = (acpi_handle *) comp; - ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n", + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating completion[%p|%d].\n", *handle, initial_units)); return AE_OK; } /* - * TODO: A better way to delete semaphores? Linux doesn't have a - * 'delete_semaphore()' function -- may result in an invalid + * TODO: A better way to delete completions? Linux doesn't have a + * 'delete_completions()' function -- may result in an invalid * pointer dereference for non-synchronized consumers. Should * we at least check for blocked threads and signal/cancel them? */ acpi_status acpi_os_delete_semaphore(acpi_handle handle) { - struct semaphore *sem = (struct semaphore *)handle; + struct completion *comp = (struct completion *)handle; - if (!sem) + if (!comp) return AE_BAD_PARAMETER; - ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle)); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting completion[%p].\n", handle)); - BUG_ON(!list_empty(&sem->wait_list)); - kfree(sem); - sem = NULL; + BUG_ON(!completion_done(comp)); + kfree(comp); + comp = NULL; return AE_OK; } @@ -814,17 +816,17 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle) acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) { acpi_status status = AE_OK; - struct semaphore *sem = (struct semaphore *)handle; + struct completion *comp = (struct completion *)handle; long jiffies; int ret = 0; - if (!sem || (units < 1)) + if (!comp || (units < 1)) return AE_BAD_PARAMETER; if (units > 1) return AE_SUPPORT; - ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for completion[%p|%d|%d]\n", handle, units, timeout)); if (timeout == ACPI_WAIT_FOREVER) @@ -832,18 +834,18 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) else jiffies = msecs_to_jiffies(timeout); - ret = down_timeout(sem, jiffies); + ret = wait_for_completion_timeout(comp, jiffies); if (ret) status = AE_TIME; if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, - "Failed to acquire semaphore[%p|%d|%d], %s", + "Failed to acquire completion[%p|%d|%d], %s", handle, units, timeout, acpi_format_exception(status))); } else { ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, - "Acquired semaphore[%p|%d|%d]", handle, + "Acquired completion[%p|%d|%d]", handle, units, timeout)); } @@ -855,18 +857,18 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) */ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) { - struct semaphore *sem = (struct semaphore *)handle; + struct completion *comp = (struct completion *)handle; - if (!sem || (units < 1)) + if (!comp || (units < 1)) return AE_BAD_PARAMETER; if (units > 1) return AE_SUPPORT; - ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle, + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling completion[%p|%d]\n", handle, units)); - up(sem); + complete(comp); return AE_OK; } diff --git a/include/linux/completion.h b/include/linux/completion.h index d2961b6..00b1288 100644 --- a/include/linux/completion.h +++ b/include/linux/completion.h @@ -36,6 +36,25 @@ struct completion { # define DECLARE_COMPLETION_ONSTACK(work) DECLARE_COMPLETION(work) #endif +/** + * completion_done - Test to see if a completion has any waiters + * @x: completion structure + * + * Returns: 0 if there are waiters (wait_for_completion() in progress) + * 1 if there are no waiters. + * + */ +static inline bool completion_done(struct completion *x) +{ + int ret = 1; + + spin_lock_irq(&x->wait.lock); + if (!x->done) + ret = 0; + spin_unlock_irq(&x->wait.lock); + return ret; +} + static inline void init_completion(struct completion *x) { x->done = 0; -- 1.5.5.1.32.gba7d2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 5/5] acpi: semaphore removal 2008-08-07 14:59 ` [PATCH 5/5] acpi: semaphore removal Daniel Walker @ 2008-08-08 0:34 ` Matthew Wilcox 2008-08-08 1:00 ` Daniel Walker 2008-08-08 1:28 ` Dave Chinner 2008-08-08 2:44 ` Andi Kleen 1 sibling, 2 replies; 18+ messages in thread From: Matthew Wilcox @ 2008-08-08 0:34 UTC (permalink / raw) To: Daniel Walker Cc: linux-acpi, Robert Moore, Andi Kleen, Peter Zijlstra, Zhao Yakui, Dave Chinner, Ingo Molnar On Thu, Aug 07, 2008 at 07:59:43AM -0700, Daniel Walker wrote: > The semaphore usage in ACPI is more like completions. The ASL > functions getting implemented here are signals which follow a > "wait for", signaled, or reset format. > > This implements the ACPI signaling methods with the Linux > completion API, instead of using semaphores. > > completion_done() taken from Dave Chinner. completion_done is an abomination. Stop this. -- Intel are signing my paycheques ... these opinions are still mine "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step." ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 5/5] acpi: semaphore removal 2008-08-08 0:34 ` Matthew Wilcox @ 2008-08-08 1:00 ` Daniel Walker 2008-08-08 1:28 ` Dave Chinner 1 sibling, 0 replies; 18+ messages in thread From: Daniel Walker @ 2008-08-08 1:00 UTC (permalink / raw) To: Matthew Wilcox Cc: linux-acpi, Robert Moore, Andi Kleen, Peter Zijlstra, Zhao Yakui, Dave Chinner, Ingo Molnar On Thu, 2008-08-07 at 18:34 -0600, Matthew Wilcox wrote: > On Thu, Aug 07, 2008 at 07:59:43AM -0700, Daniel Walker wrote: > > The semaphore usage in ACPI is more like completions. The ASL > > functions getting implemented here are signals which follow a > > "wait for", signaled, or reset format. > > > > This implements the ACPI signaling methods with the Linux > > completion API, instead of using semaphores. > > > > completion_done() taken from Dave Chinner. > > completion_done is an abomination. Stop this. > In my ACPI changes it's just used for a BUG_ON to trigger if there is something waiting on the completion before the memory gets free'd .. You don't like how it's used, or you don't like the code itself? Daniel ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 5/5] acpi: semaphore removal 2008-08-08 0:34 ` Matthew Wilcox 2008-08-08 1:00 ` Daniel Walker @ 2008-08-08 1:28 ` Dave Chinner 2008-08-08 2:53 ` Matthew Wilcox 1 sibling, 1 reply; 18+ messages in thread From: Dave Chinner @ 2008-08-08 1:28 UTC (permalink / raw) To: Matthew Wilcox Cc: Daniel Walker, linux-acpi, Robert Moore, Andi Kleen, Peter Zijlstra, Zhao Yakui, Ingo Molnar On Thu, Aug 07, 2008 at 06:34:08PM -0600, Matthew Wilcox wrote: > On Thu, Aug 07, 2008 at 07:59:43AM -0700, Daniel Walker wrote: > > The semaphore usage in ACPI is more like completions. The ASL > > functions getting implemented here are signals which follow a > > "wait for", signaled, or reset format. > > > > This implements the ACPI signaling methods with the Linux > > completion API, instead of using semaphores. > > > > completion_done() taken from Dave Chinner. > > completion_done is an abomination. Stop this. Say what? You've had several opportunities to comment on that *you suggested* [1]. You did not respond to any of them when it was being discussed 6 weeks ago and subsequent resends [2] and now you're saying what you suggested is an abortion? What's the problem? The implementation, the interface, or something else? [1] http://oss.sgi.com/archives/xfs/2008-06/msg00380.html [2] http://oss.sgi.com/archives/xfs/2008-06/msg00382.html http://oss.sgi.com/archives/xfs/2008-06/msg00400.html http://oss.sgi.com/archives/xfs/2008-07/msg00173.html Cheers, Dave. -- Dave Chinner david@fromorbit.com ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 5/5] acpi: semaphore removal 2008-08-08 1:28 ` Dave Chinner @ 2008-08-08 2:53 ` Matthew Wilcox 2008-08-08 3:47 ` Daniel Walker 0 siblings, 1 reply; 18+ messages in thread From: Matthew Wilcox @ 2008-08-08 2:53 UTC (permalink / raw) To: Dave Chinner Cc: Daniel Walker, linux-acpi, Robert Moore, Andi Kleen, Peter Zijlstra, Zhao Yakui, Ingo Molnar On Fri, Aug 08, 2008 at 11:28:49AM +1000, Dave Chinner wrote: > > completion_done is an abomination. Stop this. > > Say what? > > You've had several opportunities to comment on that *you suggested* > [1]. You did not respond to any of them when it was being discussed > 6 weeks ago and subsequent resends [2] and now you're saying what > you suggested is an abortion? Sorry, I had it confused with these: http://oss.sgi.com/archives/xfs/2008-06/msg00372.html -- Intel are signing my paycheques ... these opinions are still mine "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step." ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 5/5] acpi: semaphore removal 2008-08-08 2:53 ` Matthew Wilcox @ 2008-08-08 3:47 ` Daniel Walker 0 siblings, 0 replies; 18+ messages in thread From: Daniel Walker @ 2008-08-08 3:47 UTC (permalink / raw) To: Matthew Wilcox Cc: Dave Chinner, linux-acpi, Robert Moore, Andi Kleen, Peter Zijlstra, Zhao Yakui, Ingo Molnar On Thu, 2008-08-07 at 20:53 -0600, Matthew Wilcox wrote: > On Fri, Aug 08, 2008 at 11:28:49AM +1000, Dave Chinner wrote: > > > completion_done is an abomination. Stop this. > > > > Say what? > > > > You've had several opportunities to comment on that *you suggested* > > [1]. You did not respond to any of them when it was being discussed > > 6 weeks ago and subsequent resends [2] and now you're saying what > > you suggested is an abortion? > > Sorry, I had it confused with these: > > http://oss.sgi.com/archives/xfs/2008-06/msg00372.html I was just saying that completions should be used for resource counting. Like the usage in drivers/usb/usb-skeleton.c, sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); This writes in flight usage happens 5-10 times in Linux, and completion can fit that usage model .. It's not really locking, it's just counting. Daniel ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 5/5] acpi: semaphore removal 2008-08-07 14:59 ` [PATCH 5/5] acpi: semaphore removal Daniel Walker 2008-08-08 0:34 ` Matthew Wilcox @ 2008-08-08 2:44 ` Andi Kleen 2008-08-08 3:35 ` Daniel Walker 1 sibling, 1 reply; 18+ messages in thread From: Andi Kleen @ 2008-08-08 2:44 UTC (permalink / raw) To: Daniel Walker Cc: linux-acpi, Robert Moore, Matthew Wilcox, Peter Zijlstra, Zhao Yakui, Dave Chinner, Ingo Molnar Daniel Walker wrote: > The semaphore usage in ACPI is more like completions. The ASL > functions getting implemented here are signals which follow a > "wait for", signaled, or reset format. > > This implements the ACPI signaling methods with the Linux > completion API, instead of using semaphores. > > completion_done() taken from Dave Chinner. I agree with Matthew's earlier criticism. It doesn't make sense to reinvent semaphores using completions when we really need semaphores here for several cases (e.g. the AML locks by themselves) So I'm not going to apply this patch. What I'm open for is to convert specific non AML instances of the ACPICA semaphores to mutexes. Such changes would need to be coordinated with Bob of course though because it would affect his codebase. In fact that has been already done for some. -Andi ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 5/5] acpi: semaphore removal 2008-08-08 2:44 ` Andi Kleen @ 2008-08-08 3:35 ` Daniel Walker 0 siblings, 0 replies; 18+ messages in thread From: Daniel Walker @ 2008-08-08 3:35 UTC (permalink / raw) To: Andi Kleen Cc: linux-acpi, Robert Moore, Matthew Wilcox, Peter Zijlstra, Zhao Yakui, Dave Chinner, Ingo Molnar On Fri, 2008-08-08 at 04:44 +0200, Andi Kleen wrote: > Daniel Walker wrote: > > The semaphore usage in ACPI is more like completions. The ASL > > functions getting implemented here are signals which follow a > > "wait for", signaled, or reset format. > > > > This implements the ACPI signaling methods with the Linux > > completion API, instead of using semaphores. > > > > completion_done() taken from Dave Chinner. > > I agree with Matthew's earlier criticism. It doesn't make sense to > reinvent semaphores using completions when we really need semaphores > here for several cases (e.g. the AML locks by themselves) Not following you .. The AML locks are strict mutexes (I was happily surprised to find out how strict).. The AML signals are just strict completions .. I didn't have to mod the completion API to make this work, the one API addition could be removed without any ill effects (except less debug checking). It's really a clean replacement .. ACPI has it's own mutex API which now just calls the Linux mutex, and that change leaves AML signals as the only semaphore user which are completions .. Everything should be fine if Bob just uses two types of locking either he uses a mutex, or he uses a semaphore with an initial unit of 0.. Which appears to be what he's been doing for a while anyway.. > So I'm not going to apply this patch. Ok .. I think the interpreter locking needs to get straightened out before it's even considered to be applied .. > What I'm open for is to convert specific non AML instances > of the ACPICA semaphores to mutexes. Such changes would need > to be coordinated with Bob of course though because it would affect > his codebase. In fact that has been already done for some. You don't want lockdep checking the AML mutexes? Daniel ^ permalink raw reply [flat|nested] 18+ messages in thread
* RE: [PATCH 4/5] acpi: remove interpreter lock 2008-08-07 14:59 ` [PATCH 4/5] acpi: remove interpreter lock Daniel Walker 2008-08-07 14:59 ` [PATCH 5/5] acpi: semaphore removal Daniel Walker @ 2008-08-07 20:32 ` Moore, Robert 2008-08-07 21:09 ` Daniel Walker 2008-08-08 2:40 ` Andi Kleen 2 siblings, 1 reply; 18+ messages in thread From: Moore, Robert @ 2008-08-07 20:32 UTC (permalink / raw) To: Daniel Walker, linux-acpi Cc: Andi Kleen, Matthew Wilcox, Peter Zijlstra, Zhao, Yakui, Dave Chinner, Ingo Molnar I believe the point was to allow the handler to execute methods, even from other threads and to not block the interpreter for an unknown amount of time. >-----Original Message----- >From: Daniel Walker [mailto:dwalker@mvista.com] >Sent: Thursday, August 07, 2008 8:00 AM >To: linux-acpi@vger.kernel.org >Cc: Moore, Robert; Andi Kleen; Matthew Wilcox; Peter Zijlstra; Zhao, Yakui; >Dave Chinner; Ingo Molnar >Subject: [PATCH 4/5] acpi: remove interpreter lock > >Lockdep has identified this lock as a source of potential deadlock in >acpi. After reviewing the lock it's not clear what it's protecting. I >invite anyone who might know what the point of the lock is to describe it. > >In the mean time I removed the lock completely which, so far, hasn't had >any ill effects on my test machines. > >Cc: linux-acpi@vger.kernel.org >Signed-off-by: Daniel Walker <dwalker@mvista.com> >--- > drivers/acpi/dispatcher/dsmethod.c | 5 -- > drivers/acpi/events/evregion.c | 30 --------- > drivers/acpi/events/evxface.c | 5 -- > drivers/acpi/executer/exsystem.c | 21 ------ > drivers/acpi/executer/exutils.c | 127 -------------------------------- >---- > drivers/acpi/namespace/nseval.c | 6 -- > drivers/acpi/namespace/nsinit.c | 6 -- > drivers/acpi/namespace/nsxfeval.c | 5 +- > 8 files changed, 1 insertions(+), 204 deletions(-) > >diff --git a/drivers/acpi/dispatcher/dsmethod.c >b/drivers/acpi/dispatcher/dsmethod.c >index a3cf3d4..0b8af17 100644 >--- a/drivers/acpi/dispatcher/dsmethod.c >+++ b/drivers/acpi/dispatcher/dsmethod.c >@@ -86,10 +86,6 @@ acpi_ds_method_error(acpi_status status, struct >acpi_walk_state *walk_state) > > if (acpi_gbl_exception_handler) { > >- /* Exit the interpreter, allow handler to execute methods */ >- >- acpi_ex_exit_interpreter(); >- > /* > * Handler can map the exception code to anything it wants, >including > * AE_OK, in which case the executing method will not be >aborted. >@@ -101,7 +97,6 @@ acpi_ds_method_error(acpi_status status, struct >acpi_walk_state *walk_state) > walk_state->opcode, > walk_state->aml_offset, > NULL); >- acpi_ex_enter_interpreter(); > } > #ifdef ACPI_DISASSEMBLER > if (ACPI_FAILURE(status)) { >diff --git a/drivers/acpi/events/evregion.c >b/drivers/acpi/events/evregion.c >index 236fbd1..4eb4c30 100644 >--- a/drivers/acpi/events/evregion.c >+++ b/drivers/acpi/events/evregion.c >@@ -338,21 +338,10 @@ acpi_ev_address_space_dispatch(union >acpi_operand_object *region_obj, > return_ACPI_STATUS(AE_NOT_EXIST); > } > >- /* >- * We must exit the interpreter because the region >- * setup will potentially execute control methods >- * (e.g., _REG method for this region) >- */ >- acpi_ex_exit_interpreter(); >- > status = region_setup(region_obj, ACPI_REGION_ACTIVATE, > handler_desc->address_space.context, > ®ion_context); > >- /* Re-enter the interpreter */ >- >- acpi_ex_enter_interpreter(); >- > /* Check for failure of the Region Setup */ > > if (ACPI_FAILURE(status)) { >@@ -397,16 +386,6 @@ acpi_ev_address_space_dispatch(union >acpi_operand_object *region_obj, > acpi_ut_get_region_name(region_obj->region. > space_id))); > >- if (!(handler_desc->address_space.handler_flags & >- ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { >- /* >- * For handlers other than the default (supplied) handlers, we >must >- * exit the interpreter because the handler *might* block -- we >don't >- * know what it will do, so we can't hold the lock on the >intepreter. >- */ >- acpi_ex_exit_interpreter(); >- } >- > /* Call the handler */ > > status = handler(function, address, bit_width, value, >@@ -419,15 +398,6 @@ acpi_ev_address_space_dispatch(union >acpi_operand_object *region_obj, > space_id))); > } > >- if (!(handler_desc->address_space.handler_flags & >- ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { >- /* >- * We just returned from a non-default handler, we must re- >enter the >- * interpreter >- */ >- acpi_ex_enter_interpreter(); >- } >- > return_ACPI_STATUS(status); > } > >diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c >index 94a6efe..4e4bd7a 100644 >--- a/drivers/acpi/events/evxface.c >+++ b/drivers/acpi/events/evxface.c >@@ -773,10 +773,6 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 >* handle) > return (AE_BAD_PARAMETER); > } > >- /* Must lock interpreter to prevent race conditions */ >- >- acpi_ex_enter_interpreter(); >- > status = acpi_ex_acquire_mutex_object(timeout, > acpi_gbl_global_lock_mutex, > acpi_os_get_thread_id()); >@@ -788,7 +784,6 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * >handle) > *handle = acpi_gbl_global_lock_handle; > } > >- acpi_ex_exit_interpreter(); > return (status); > } > >diff --git a/drivers/acpi/executer/exsystem.c >b/drivers/acpi/executer/exsystem.c >index 1a4aa5e..6c82143 100644 >--- a/drivers/acpi/executer/exsystem.c >+++ b/drivers/acpi/executer/exsystem.c >@@ -75,19 +75,12 @@ acpi_status >acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) > > if (status == AE_TIME) { > >- /* We must wait, so unlock the interpreter */ >- >- acpi_ex_relinquish_interpreter(); >- > status = acpi_os_wait_semaphore(semaphore, 1, timeout); > > ACPI_DEBUG_PRINT((ACPI_DB_EXEC, > "*** Thread awake after blocking, %s\n", > acpi_format_exception(status))); > >- /* Reacquire the interpreter */ >- >- acpi_ex_reacquire_interpreter(); > } > > return_ACPI_STATUS(status); >@@ -122,19 +115,12 @@ acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 >timeout) > > if (status == AE_TIME) { > >- /* We must wait, so unlock the interpreter */ >- >- acpi_ex_relinquish_interpreter(); >- > status = acpi_os_acquire_mutex(mutex, timeout); > > ACPI_DEBUG_PRINT((ACPI_DB_EXEC, > "*** Thread awake after blocking, %s\n", > acpi_format_exception(status))); > >- /* Reacquire the interpreter */ >- >- acpi_ex_reacquire_interpreter(); > } > > return_ACPI_STATUS(status); >@@ -197,15 +183,8 @@ acpi_status acpi_ex_system_do_suspend(acpi_integer >how_long) > { > ACPI_FUNCTION_ENTRY(); > >- /* Since this thread will sleep, we must release the interpreter */ >- >- acpi_ex_relinquish_interpreter(); >- > acpi_os_sleep(how_long); > >- /* And now we must get the interpreter again */ >- >- acpi_ex_reacquire_interpreter(); > return (AE_OK); > } > >diff --git a/drivers/acpi/executer/exutils.c >b/drivers/acpi/executer/exutils.c >index 86c0388..815defd 100644 >--- a/drivers/acpi/executer/exutils.c >+++ b/drivers/acpi/executer/exutils.c >@@ -71,133 +71,6 @@ static u32 acpi_ex_digits_needed(acpi_integer value, >u32 base); > #ifndef ACPI_NO_METHOD_EXECUTION > >/********************************************************************** **** >***** > * >- * FUNCTION: acpi_ex_enter_interpreter >- * >- * PARAMETERS: None >- * >- * RETURN: None >- * >- * DESCRIPTION: Enter the interpreter execution region. Failure to enter >- * the interpreter region is a fatal system error. Used in >- * conjunction with exit_interpreter. >- * >- >*********************************************************************** **** >***/ >- >-void acpi_ex_enter_interpreter(void) >-{ >- acpi_status status; >- >- ACPI_FUNCTION_TRACE(ex_enter_interpreter); >- >- status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); >- if (ACPI_FAILURE(status)) { >- ACPI_ERROR((AE_INFO, >- "Could not acquire AML Interpreter mutex")); >- } >- >- return_VOID; >-} >- >- >/********************************************************************** **** >***** >- * >- * FUNCTION: acpi_ex_reacquire_interpreter >- * >- * PARAMETERS: None >- * >- * RETURN: None >- * >- * DESCRIPTION: Reacquire the interpreter execution region from within the >- * interpreter code. Failure to enter the interpreter region >is a >- * fatal system error. Used in conjuction with >- * relinquish_interpreter >- * >- >*********************************************************************** **** >***/ >- >-void acpi_ex_reacquire_interpreter(void) >-{ >- ACPI_FUNCTION_TRACE(ex_reacquire_interpreter); >- >- /* >- * If the global serialized flag is set, do not release the >interpreter, >- * since it was not actually released by >acpi_ex_relinquish_interpreter. >- * This forces the interpreter to be single threaded. >- */ >- if (!acpi_gbl_all_methods_serialized) { >- acpi_ex_enter_interpreter(); >- } >- >- return_VOID; >-} >- >- >/********************************************************************** **** >***** >- * >- * FUNCTION: acpi_ex_exit_interpreter >- * >- * PARAMETERS: None >- * >- * RETURN: None >- * >- * DESCRIPTION: Exit the interpreter execution region. This is the top >level >- * routine used to exit the interpreter when all processing >has >- * been completed. >- * >- >*********************************************************************** **** >***/ >- >-void acpi_ex_exit_interpreter(void) >-{ >- acpi_status status; >- >- ACPI_FUNCTION_TRACE(ex_exit_interpreter); >- >- status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); >- if (ACPI_FAILURE(status)) { >- ACPI_ERROR((AE_INFO, >- "Could not release AML Interpreter mutex")); >- } >- >- return_VOID; >-} >- >- >/********************************************************************** **** >***** >- * >- * FUNCTION: acpi_ex_relinquish_interpreter >- * >- * PARAMETERS: None >- * >- * RETURN: None >- * >- * DESCRIPTION: Exit the interpreter execution region, from within the >- * interpreter - before attempting an operation that will >possibly >- * block the running thread. >- * >- * Cases where the interpreter is unlocked internally >- * 1) Method to be blocked on a Sleep() AML opcode >- * 2) Method to be blocked on an Acquire() AML opcode >- * 3) Method to be blocked on a Wait() AML opcode >- * 4) Method to be blocked to acquire the global lock >- * 5) Method to be blocked waiting to execute a serialized control >method >- * that is currently executing >- * 6) About to invoke a user-installed opregion handler >- * >- >*********************************************************************** **** >***/ >- >-void acpi_ex_relinquish_interpreter(void) >-{ >- ACPI_FUNCTION_TRACE(ex_relinquish_interpreter); >- >- /* >- * If the global serialized flag is set, do not release the >interpreter. >- * This forces the interpreter to be single threaded. >- */ >- if (!acpi_gbl_all_methods_serialized) { >- acpi_ex_exit_interpreter(); >- } >- >- return_VOID; >-} >- >- >/********************************************************************** **** >***** >- * > * FUNCTION: acpi_ex_truncate_for32bit_table > * > * PARAMETERS: obj_desc - Object to be truncated >diff --git a/drivers/acpi/namespace/nseval.c >b/drivers/acpi/namespace/nseval.c >index d369164..2a98cc7 100644 >--- a/drivers/acpi/namespace/nseval.c >+++ b/drivers/acpi/namespace/nseval.c >@@ -72,8 +72,6 @@ ACPI_MODULE_NAME("nseval") > * DESCRIPTION: Execute a control method or return the current value of an > * ACPI namespace object. > * >- * MUTEX: Locks interpreter >- * > >*********************************************************************** **** >***/ > acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) > { >@@ -189,9 +187,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info >* info) > * Execute the method via the interpreter. The interpreter is >locked > * here before calling into the AML parser > */ >- acpi_ex_enter_interpreter(); > status = acpi_ps_execute_method(info); >- acpi_ex_exit_interpreter(); > } else { > /* > * 2) Object is not a method, return its current value >@@ -213,13 +209,11 @@ acpi_status acpi_ns_evaluate(struct >acpi_evaluate_info * info) > * resolution, we must lock it because we could access an >opregion. > * The opregion access code assumes that the interpreter is >locked. > */ >- acpi_ex_enter_interpreter(); > > /* Function has a strange interface */ > > status = > acpi_ex_resolve_node_to_value(&info->resolved_node, NULL); >- acpi_ex_exit_interpreter(); > > /* > * If acpi_ex_resolve_node_to_value() succeeded, the return >value was placed >diff --git a/drivers/acpi/namespace/nsinit.c >b/drivers/acpi/namespace/nsinit.c >index e4c5751..e6c93d4 100644 >--- a/drivers/acpi/namespace/nsinit.c >+++ b/drivers/acpi/namespace/nsinit.c >@@ -270,11 +270,6 @@ acpi_ns_init_one_object(acpi_handle obj_handle, > } > > /* >- * Must lock the interpreter before executing AML code >- */ >- acpi_ex_enter_interpreter(); >- >- /* > * Each of these types can contain executable AML code within the > * declaration. > */ >@@ -333,7 +328,6 @@ acpi_ns_init_one_object(acpi_handle obj_handle, > * We ignore errors from above, and always return OK, since we don't >want > * to abort the walk on any single error. > */ >- acpi_ex_exit_interpreter(); > return (AE_OK); > } > >diff --git a/drivers/acpi/namespace/nsxfeval.c >b/drivers/acpi/namespace/nsxfeval.c >index 38be586..64c63f0 100644 >--- a/drivers/acpi/namespace/nsxfeval.c >+++ b/drivers/acpi/namespace/nsxfeval.c >@@ -322,15 +322,12 @@ acpi_evaluate_object(acpi_handle handle, > > if (info->return_object) { > /* >- * Delete the internal return object. NOTE: Interpreter must be >- * locked to avoid race condition. >+ * Delete the internal return object. > */ >- acpi_ex_enter_interpreter(); > > /* Remove one reference on the return object (should delete it) >*/ > > acpi_ut_remove_reference(info->return_object); >- acpi_ex_exit_interpreter(); > } > > cleanup: >-- >1.5.5.1.32.gba7d2 > ^ permalink raw reply [flat|nested] 18+ messages in thread
* RE: [PATCH 4/5] acpi: remove interpreter lock 2008-08-07 20:32 ` [PATCH 4/5] acpi: remove interpreter lock Moore, Robert @ 2008-08-07 21:09 ` Daniel Walker 2008-08-07 21:30 ` Moore, Robert 0 siblings, 1 reply; 18+ messages in thread From: Daniel Walker @ 2008-08-07 21:09 UTC (permalink / raw) To: Moore, Robert Cc: linux-acpi, Andi Kleen, Matthew Wilcox, Peter Zijlstra, Zhao, Yakui, Dave Chinner, Ingo Molnar On Thu, 2008-08-07 at 13:32 -0700, Moore, Robert wrote: > I believe the point was to allow the handler to execute methods, even > from other threads and to not block the interpreter for an unknown > amount of time. > Could you elaborate on this more, I'm not following you.. What do you mean by "handler"? The name "interpreter lock" to me sort of indicates that it's protecting the interpreter. So I'm guessing the point was to stop multiple threads from being inside the interpreter at once. If that's the case it doesn't make sense to release the mutex while your inside the interpreter. That means another thread could then enter and the protection doesn't hold. It looked like most if the interpreter functions allocate their own memory, then use that memory without sharing it with other instances of the interpreter. So it's all contained into the one thread. You also have the mutexes embedded in the AML , which seem to indicate the AML is thread safe (might be a big assumption tho). Daniel ^ permalink raw reply [flat|nested] 18+ messages in thread
* RE: [PATCH 4/5] acpi: remove interpreter lock 2008-08-07 21:09 ` Daniel Walker @ 2008-08-07 21:30 ` Moore, Robert 2008-08-08 0:01 ` Daniel Walker 0 siblings, 1 reply; 18+ messages in thread From: Moore, Robert @ 2008-08-07 21:30 UTC (permalink / raw) To: Daniel Walker Cc: linux-acpi, Andi Kleen, Matthew Wilcox, Peter Zijlstra, Zhao, Yakui, Dave Chinner, Ingo Molnar Yes, we lock the interpreter for major parts of control method execution in order to implement the multithreading model of the ACPI specification. Here are a couple of sections from the ACPICA programmer reference that explain the ACPICA multithreading, control method execution, reentrancy, etc. -------------------- 2.2.5 Multitasking and Reentrancy All components of the ACPI subsystem are intended to be fully reentrant and support multiple threads of execution. To achieve this, there are several mutual exclusion OSL interfaces that must be properly implemented with the native host OS primitives to ensure that mutual exclusion and synchronization can be performed correctly. Although dependent on the correct implementation of these interfaces, the ACPI Core Subsystem is otherwise fully reentrant and supports multiple threads throughout the component, with the exception of the AML interpreter, as explained below. Because of the constraints of the ACPI specification, there is a major limitation on the concurrency that can be achieved within the AML interpreter portion of the subsystem. The specification states that at most one control method can be actually executing AML code at any given time. If a control method blocks (an event that can occur only under a few limited conditions), another method may begin execution. However, it can be said that the specification precludes the concurrent execution of control methods. Therefore, the AML interpreter itself is essentially a single-threaded component of the ACPI subsystem. Serialization of both internal and external requests for execution of control methods is performed and managed by the front-end of the interpreter. And section 3.3.2 3.3.2 Control Method Execution Most of the multithread support within the ACPI subsystem is implemented using traditional locks and mutexes around critical (shared) data areas. However, the AML interpreter design is different in that the ACPI specification defines a special threading behavior for the execution of control methods. The design implements the following portion of the ACPI specification that defines a partially multithreaded AML interpreter in four sentences: A control method can use other internal, or well-defined, control methods to accomplish the task at hand, which can include defined control methods provided by the operating software. Interpretation of a Control Method is not preemptive, but can block. When a control method does block, the operating software can initiate or continue the execution of a different control method. A control method can only assume that access to global objects is exclusive for any period the control method does not block. 3.3.2.1 Control Method Blocking First of all, how can a control method block? This is a fairly exhaustive list of the possibilities: 1. Executes the Sleep() ASL opcode 2. Executes the Acquire() ASL opcode and the request cannot be immediately satisfied 3. Executes the Wait() ASL opcode and the request cannot be immediately satisfied 4. Attempts to acquire the Global Lock (via Operation Region access, etc), but must wait 5. Attempts to execute a control method that is serialized and already executing (or is blocked), or has reached its concurrency limit 6. Invokes the host debugger via a write to the debug object or executes the BreakPoint() ASL opcode 7. Accesses an Operation Region which results in a dispatch to a user-installed handler that blocks on I/O or other long-term operation 8. A Notify AML opcode results in a dispatch to a user-installed handler that blocks in a similar way --------------------- The "handler" in question is the code that implements #7 above. A good example of this is the EC operation region, which can be very slow. Essentially, the implementation of 1-8 above is to unlock the interpreter for the duration of the event. There's more information about this in the ACPICA document, which is available at http://www.acpica.org/documentation/ >-----Original Message----- >From: Daniel Walker [mailto:dwalker@mvista.com] >Sent: Thursday, August 07, 2008 2:09 PM >To: Moore, Robert >Cc: linux-acpi@vger.kernel.org; Andi Kleen; Matthew Wilcox; Peter Zijlstra; >Zhao, Yakui; Dave Chinner; Ingo Molnar >Subject: RE: [PATCH 4/5] acpi: remove interpreter lock > >On Thu, 2008-08-07 at 13:32 -0700, Moore, Robert wrote: >> I believe the point was to allow the handler to execute methods, even >> from other threads and to not block the interpreter for an unknown >> amount of time. >> > >Could you elaborate on this more, I'm not following you.. What do you >mean by "handler"? The name "interpreter lock" to me sort of indicates >that it's protecting the interpreter. So I'm guessing the point was to >stop multiple threads from being inside the interpreter at once. > >If that's the case it doesn't make sense to release the mutex while your >inside the interpreter. That means another thread could then enter and >the protection doesn't hold. > >It looked like most if the interpreter functions allocate their own >memory, then use that memory without sharing it with other instances of >the interpreter. So it's all contained into the one thread. > >You also have the mutexes embedded in the AML , which seem to indicate >the AML is thread safe (might be a big assumption tho). > >Daniel ^ permalink raw reply [flat|nested] 18+ messages in thread
* RE: [PATCH 4/5] acpi: remove interpreter lock 2008-08-07 21:30 ` Moore, Robert @ 2008-08-08 0:01 ` Daniel Walker 0 siblings, 0 replies; 18+ messages in thread From: Daniel Walker @ 2008-08-08 0:01 UTC (permalink / raw) To: Moore, Robert Cc: linux-acpi, Andi Kleen, Matthew Wilcox, Peter Zijlstra, Zhao, Yakui, Dave Chinner, Ingo Molnar On Thu, 2008-08-07 at 14:30 -0700, Moore, Robert wrote: > Yes, we lock the interpreter for major parts of control method execution > in order to implement the multithreading model of the ACPI > specification. > > Here are a couple of sections from the ACPICA programmer reference that > explain the ACPICA multithreading, control method execution, reentrancy, > etc. Thanks for the lengthy response. > 3.3.2.1 Control Method Blocking > First of all, how can a control method block? This is a fairly > exhaustive list of the possibilities: > 1. Executes the Sleep() ASL opcode > 2. Executes the Acquire() ASL opcode and the request cannot be > immediately satisfied > 3. Executes the Wait() ASL opcode and the request cannot be > immediately satisfied > 4. Attempts to acquire the Global Lock (via Operation Region > access, etc), but must wait > 5. Attempts to execute a control method that is serialized and > already executing (or is blocked), or has reached its concurrency limit > 6. Invokes the host debugger via a write to the debug object or > executes the BreakPoint() ASL opcode > 7. Accesses an Operation Region which results in a dispatch to a > user-installed handler that blocks on I/O or other long-term operation > 8. A Notify AML opcode results in a dispatch to a user-installed > handler that blocks in a similar way Ok .. Well it looks like the deadlock that lockdep is warning on is fixed with #2 or #3 .. If you release the interpreter before sleeping on an Acquire() ASL opcode then you "fix" the deadlock that could happen by having different locking orders of the interpreter lock with other mutexes. I'm not sure how to train lockdep to understand this tho , Ingo? Peter? you guys have any thoughts? I assume it's not safe to remove the interpreter lock given the text that you quoted? Daniel ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/5] acpi: remove interpreter lock 2008-08-07 14:59 ` [PATCH 4/5] acpi: remove interpreter lock Daniel Walker 2008-08-07 14:59 ` [PATCH 5/5] acpi: semaphore removal Daniel Walker 2008-08-07 20:32 ` [PATCH 4/5] acpi: remove interpreter lock Moore, Robert @ 2008-08-08 2:40 ` Andi Kleen 2 siblings, 0 replies; 18+ messages in thread From: Andi Kleen @ 2008-08-08 2:40 UTC (permalink / raw) To: Daniel Walker Cc: linux-acpi, Robert Moore, Matthew Wilcox, Peter Zijlstra, Zhao Yakui, Dave Chinner, Ingo Molnar Daniel Walker wrote: > Lockdep has identified this lock as a source of potential deadlock in > acpi. After reviewing the lock it's not clear what it's protecting. I > invite anyone who might know what the point of the lock is to describe it. > > In the mean time I removed the lock completely which, so far, hasn't had > any ill effects on my test machines. As Bob pointed out this lock is required by the ACPI specification. So I'm not going to apply this patch. However of course we still have to do something about the lockdep warnings when the lock is dropped/reaquired. The big question is if deadlocks can happen really or not. AFAIK we didn't have a clear answer on that yet. -Andi ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2008-08-08 3:48 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-08-07 14:59 [PATCH 0/3] acpi: semaphore removal -v2 Daniel Walker 2008-08-07 14:59 ` [PATCH 1/5] add mutex_lock_timeout() Daniel Walker 2008-08-07 14:59 ` [PATCH 2/5] acpi: add real mutex function calls Daniel Walker 2008-08-07 14:59 ` [PATCH 3/5] acpi: add lockdep magic Daniel Walker 2008-08-07 14:59 ` [PATCH 4/5] acpi: remove interpreter lock Daniel Walker 2008-08-07 14:59 ` [PATCH 5/5] acpi: semaphore removal Daniel Walker 2008-08-08 0:34 ` Matthew Wilcox 2008-08-08 1:00 ` Daniel Walker 2008-08-08 1:28 ` Dave Chinner 2008-08-08 2:53 ` Matthew Wilcox 2008-08-08 3:47 ` Daniel Walker 2008-08-08 2:44 ` Andi Kleen 2008-08-08 3:35 ` Daniel Walker 2008-08-07 20:32 ` [PATCH 4/5] acpi: remove interpreter lock Moore, Robert 2008-08-07 21:09 ` Daniel Walker 2008-08-07 21:30 ` Moore, Robert 2008-08-08 0:01 ` Daniel Walker 2008-08-08 2:40 ` Andi Kleen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).