aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLin Ming <ming.m.lin@intel.com>2010-03-05 04:59:54 -0500
committerLen Brown <len.brown@intel.com>2010-04-20 10:42:53 -0400
commite0f40281d52161dddeb1bc12879425266a53f26f (patch)
tree163241e07e71a32fa56b6433d70630dc86af1ca3 /drivers/acpi
parentf6a22b0bc417042e83117f52ab1a03696af185ab (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')
-rw-r--r--drivers/acpi/acpica/exmutex.c21
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}