diff options
author | Lin Ming <ming.m.lin@intel.com> | 2010-03-05 04:59:54 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-04-20 10:42:53 -0400 |
commit | e0f40281d52161dddeb1bc12879425266a53f26f (patch) | |
tree | 163241e07e71a32fa56b6433d70630dc86af1ca3 /drivers/acpi/acpica | |
parent | f6a22b0bc417042e83117f52ab1a03696af185ab (diff) |
ACPICA: Fix for possible fault in acpi_ex_release_mutex
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>
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r-- | drivers/acpi/acpica/exmutex.c | 21 |
1 files changed, 10 insertions, 11 deletions
diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index 2b0d722c984f..bb2efcfb81e2 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c | |||
@@ -359,6 +359,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
359 | { | 359 | { |
360 | acpi_status status = AE_OK; | 360 | acpi_status status = AE_OK; |
361 | u8 previous_sync_level; | 361 | u8 previous_sync_level; |
362 | struct acpi_thread_state *owner_thread; | ||
362 | 363 | ||
363 | ACPI_FUNCTION_TRACE(ex_release_mutex); | 364 | ACPI_FUNCTION_TRACE(ex_release_mutex); |
364 | 365 | ||
@@ -366,9 +367,11 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
366 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 367 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
367 | } | 368 | } |
368 | 369 | ||
370 | owner_thread = obj_desc->mutex.owner_thread; | ||
371 | |||
369 | /* The mutex must have been previously acquired in order to release it */ | 372 | /* The mutex must have been previously acquired in order to release it */ |
370 | 373 | ||
371 | if (!obj_desc->mutex.owner_thread) { | 374 | if (!owner_thread) { |
372 | ACPI_ERROR((AE_INFO, | 375 | ACPI_ERROR((AE_INFO, |
373 | "Cannot release Mutex [%4.4s], not acquired", | 376 | "Cannot release Mutex [%4.4s], not acquired", |
374 | acpi_ut_get_node_name(obj_desc->mutex.node))); | 377 | acpi_ut_get_node_name(obj_desc->mutex.node))); |
@@ -387,16 +390,13 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
387 | * The Mutex is owned, but this thread must be the owner. | 390 | * The Mutex is owned, but this thread must be the owner. |
388 | * Special case for Global Lock, any thread can release | 391 | * Special case for Global Lock, any thread can release |
389 | */ | 392 | */ |
390 | if ((obj_desc->mutex.owner_thread->thread_id != | 393 | if ((owner_thread->thread_id != walk_state->thread->thread_id) && |
391 | walk_state->thread->thread_id) | 394 | (obj_desc != acpi_gbl_global_lock_mutex)) { |
392 | && (obj_desc != acpi_gbl_global_lock_mutex)) { | ||
393 | ACPI_ERROR((AE_INFO, | 395 | ACPI_ERROR((AE_INFO, |
394 | "Thread %p cannot release Mutex [%4.4s] acquired by thread %p", | 396 | "Thread %p cannot release Mutex [%4.4s] acquired by thread %p", |
395 | ACPI_CAST_PTR(void, walk_state->thread->thread_id), | 397 | ACPI_CAST_PTR(void, walk_state->thread->thread_id), |
396 | acpi_ut_get_node_name(obj_desc->mutex.node), | 398 | acpi_ut_get_node_name(obj_desc->mutex.node), |
397 | ACPI_CAST_PTR(void, | 399 | ACPI_CAST_PTR(void, owner_thread->thread_id))); |
398 | obj_desc->mutex.owner_thread-> | ||
399 | thread_id))); | ||
400 | return_ACPI_STATUS(AE_AML_NOT_OWNER); | 400 | return_ACPI_STATUS(AE_AML_NOT_OWNER); |
401 | } | 401 | } |
402 | 402 | ||
@@ -407,8 +407,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
407 | * different level can only mean that the mutex ordering rule is being | 407 | * different level can only mean that the mutex ordering rule is being |
408 | * violated. This behavior is clarified in ACPI 4.0 specification. | 408 | * violated. This behavior is clarified in ACPI 4.0 specification. |
409 | */ | 409 | */ |
410 | if (obj_desc->mutex.sync_level != | 410 | if (obj_desc->mutex.sync_level != owner_thread->current_sync_level) { |
411 | walk_state->thread->current_sync_level) { | ||
412 | ACPI_ERROR((AE_INFO, | 411 | ACPI_ERROR((AE_INFO, |
413 | "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u", | 412 | "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u", |
414 | acpi_ut_get_node_name(obj_desc->mutex.node), | 413 | acpi_ut_get_node_name(obj_desc->mutex.node), |
@@ -423,7 +422,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
423 | * acquired, but are not released in reverse order. | 422 | * acquired, but are not released in reverse order. |
424 | */ | 423 | */ |
425 | previous_sync_level = | 424 | previous_sync_level = |
426 | walk_state->thread->acquired_mutex_list->mutex.original_sync_level; | 425 | owner_thread->acquired_mutex_list->mutex.original_sync_level; |
427 | 426 | ||
428 | status = acpi_ex_release_mutex_object(obj_desc); | 427 | status = acpi_ex_release_mutex_object(obj_desc); |
429 | if (ACPI_FAILURE(status)) { | 428 | if (ACPI_FAILURE(status)) { |
@@ -434,7 +433,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
434 | 433 | ||
435 | /* Restore the previous sync_level */ | 434 | /* Restore the previous sync_level */ |
436 | 435 | ||
437 | walk_state->thread->current_sync_level = previous_sync_level; | 436 | owner_thread->current_sync_level = previous_sync_level; |
438 | } | 437 | } |
439 | return_ACPI_STATUS(status); | 438 | return_ACPI_STATUS(status); |
440 | } | 439 | } |