Skip to content

Commit

Permalink
ACPICA: Fix for possible fault in acpi_ex_release_mutex
Browse files Browse the repository at this point in the history
Fixed a problem with the AML Mutex handling function
acpi_ex_release_mutex where the function could fault under the very
rare condition when the interpreter has blocked, the interpreter
lock is released, the interpreter is then reentered via the
same thread, and attempts to acquire a mutex that was previously
acquired. FreeBSD report 140979.

http://www.freebsd.org/cgi/query-pr.cgi?pr=140979

Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
Lin Ming authored and Len Brown committed Apr 20, 2010
1 parent f6a22b0 commit e0f4028
Showing 1 changed file with 10 additions and 11 deletions.
21 changes: 10 additions & 11 deletions drivers/acpi/acpica/exmutex.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,16 +359,19 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
{
acpi_status status = AE_OK;
u8 previous_sync_level;
struct acpi_thread_state *owner_thread;

ACPI_FUNCTION_TRACE(ex_release_mutex);

if (!obj_desc) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}

owner_thread = obj_desc->mutex.owner_thread;

/* The mutex must have been previously acquired in order to release it */

if (!obj_desc->mutex.owner_thread) {
if (!owner_thread) {
ACPI_ERROR((AE_INFO,
"Cannot release Mutex [%4.4s], not acquired",
acpi_ut_get_node_name(obj_desc->mutex.node)));
Expand All @@ -387,16 +390,13 @@ 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 !=
walk_state->thread->thread_id)
&& (obj_desc != acpi_gbl_global_lock_mutex)) {
if ((owner_thread->thread_id != walk_state->thread->thread_id) &&
(obj_desc != acpi_gbl_global_lock_mutex)) {
ACPI_ERROR((AE_INFO,
"Thread %p cannot release Mutex [%4.4s] acquired by thread %p",
ACPI_CAST_PTR(void, walk_state->thread->thread_id),
acpi_ut_get_node_name(obj_desc->mutex.node),
ACPI_CAST_PTR(void,
obj_desc->mutex.owner_thread->
thread_id)));
ACPI_CAST_PTR(void, owner_thread->thread_id)));
return_ACPI_STATUS(AE_AML_NOT_OWNER);
}

Expand All @@ -407,8 +407,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
* different level can only mean that the mutex ordering rule is being
* violated. This behavior is clarified in ACPI 4.0 specification.
*/
if (obj_desc->mutex.sync_level !=
walk_state->thread->current_sync_level) {
if (obj_desc->mutex.sync_level != owner_thread->current_sync_level) {
ACPI_ERROR((AE_INFO,
"Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u",
acpi_ut_get_node_name(obj_desc->mutex.node),
Expand All @@ -423,7 +422,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
* acquired, but are not released in reverse order.
*/
previous_sync_level =
walk_state->thread->acquired_mutex_list->mutex.original_sync_level;
owner_thread->acquired_mutex_list->mutex.original_sync_level;

status = acpi_ex_release_mutex_object(obj_desc);
if (ACPI_FAILURE(status)) {
Expand All @@ -434,7 +433,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,

/* Restore the previous sync_level */

walk_state->thread->current_sync_level = previous_sync_level;
owner_thread->current_sync_level = previous_sync_level;
}
return_ACPI_STATUS(status);
}
Expand Down

0 comments on commit e0f4028

Please sign in to comment.