diff options
author | Bob Moore <robert.moore@intel.com> | 2009-03-09 04:31:04 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-03-27 12:11:02 -0400 |
commit | 8a335a2331c72e60c6b3ef09b2dedd3ba00da1b1 (patch) | |
tree | f538a4f68499dab0d59e253bc55a5cf4aff66ec1 /drivers/acpi/acpica/tbinstal.c | |
parent | aab61b676a024d3527f6201e2b31285a96f7a1d2 (diff) |
ACPICA: Fix AcpiWalkNamespace race condition with table unload
Added a reader/writer locking mechanism to allow multiple
concurrent namespace walks (readers), but a dynamic table unload
will have exclusive access to the namespace. This fixes a problem
where a table unload could delete the portion of the namespace that
is currently being examined by a walk. Adds a new file, utlock.c
that implements the reader/writer lock mechanism. ACPICA BZ 749.
http://www.acpica.org/bugzilla/show_bug.cgi?id=749
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/tbinstal.c')
-rw-r--r-- | drivers/acpi/acpica/tbinstal.c | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index c37993003f2c..f865d5a096de 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c | |||
@@ -434,27 +434,56 @@ void acpi_tb_terminate(void) | |||
434 | * | 434 | * |
435 | * PARAMETERS: table_index - Table index | 435 | * PARAMETERS: table_index - Table index |
436 | * | 436 | * |
437 | * RETURN: None | 437 | * RETURN: Status |
438 | * | 438 | * |
439 | * DESCRIPTION: Delete all namespace objects created when this table was loaded. | 439 | * DESCRIPTION: Delete all namespace objects created when this table was loaded. |
440 | * | 440 | * |
441 | ******************************************************************************/ | 441 | ******************************************************************************/ |
442 | 442 | ||
443 | void acpi_tb_delete_namespace_by_owner(u32 table_index) | 443 | acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index) |
444 | { | 444 | { |
445 | acpi_owner_id owner_id; | 445 | acpi_owner_id owner_id; |
446 | acpi_status status; | ||
447 | |||
448 | ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner); | ||
449 | |||
450 | status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
451 | if (ACPI_FAILURE(status)) { | ||
452 | return_ACPI_STATUS(status); | ||
453 | } | ||
454 | |||
455 | if (table_index >= acpi_gbl_root_table_list.count) { | ||
456 | |||
457 | /* The table index does not exist */ | ||
446 | 458 | ||
447 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
448 | if (table_index < acpi_gbl_root_table_list.count) { | ||
449 | owner_id = | ||
450 | acpi_gbl_root_table_list.tables[table_index].owner_id; | ||
451 | } else { | ||
452 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 459 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
453 | return; | 460 | return_ACPI_STATUS(AE_NOT_EXIST); |
454 | } | 461 | } |
455 | 462 | ||
463 | /* Get the owner ID for this table, used to delete namespace nodes */ | ||
464 | |||
465 | owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id; | ||
456 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 466 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
467 | |||
468 | /* | ||
469 | * Need to acquire the namespace writer lock to prevent interference | ||
470 | * with any concurrent namespace walks. The interpreter must be | ||
471 | * released during the deletion since the acquisition of the deletion | ||
472 | * lock may block, and also since the execution of a namespace walk | ||
473 | * must be allowed to use the interpreter. | ||
474 | */ | ||
475 | acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); | ||
476 | status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); | ||
477 | |||
457 | acpi_ns_delete_namespace_by_owner(owner_id); | 478 | acpi_ns_delete_namespace_by_owner(owner_id); |
479 | if (ACPI_FAILURE(status)) { | ||
480 | return_ACPI_STATUS(status); | ||
481 | } | ||
482 | |||
483 | acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); | ||
484 | |||
485 | status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); | ||
486 | return_ACPI_STATUS(status); | ||
458 | } | 487 | } |
459 | 488 | ||
460 | /******************************************************************************* | 489 | /******************************************************************************* |