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>
This commit is contained in:
parent
aab61b676a
commit
8a335a2331
11 changed files with 304 additions and 34 deletions
|
@ -41,4 +41,4 @@ obj-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
|
||||||
|
|
||||||
obj-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
|
obj-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
|
||||||
utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
|
utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
|
||||||
utstate.o utmutex.o utobject.o utresrc.o
|
utstate.o utmutex.o utobject.o utresrc.o utlock.o
|
||||||
|
|
|
@ -165,6 +165,10 @@ ACPI_EXTERN u8 acpi_gbl_integer_bit_width;
|
||||||
ACPI_EXTERN u8 acpi_gbl_integer_byte_width;
|
ACPI_EXTERN u8 acpi_gbl_integer_byte_width;
|
||||||
ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
|
ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
|
||||||
|
|
||||||
|
/* Reader/Writer lock is used for namespace walk and dynamic table unload */
|
||||||
|
|
||||||
|
ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock;
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* Mutual exlusion within ACPICA subsystem
|
* Mutual exlusion within ACPICA subsystem
|
||||||
|
|
|
@ -108,6 +108,14 @@ static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Lock structure for reader/writer interfaces */
|
||||||
|
|
||||||
|
struct acpi_rw_lock {
|
||||||
|
acpi_mutex writer_mutex;
|
||||||
|
acpi_mutex reader_mutex;
|
||||||
|
u32 num_readers;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Predefined handles for spinlocks used within the subsystem.
|
* Predefined handles for spinlocks used within the subsystem.
|
||||||
* These spinlocks are created by acpi_ut_mutex_initialize
|
* These spinlocks are created by acpi_ut_mutex_initialize
|
||||||
|
|
|
@ -79,7 +79,7 @@ void acpi_tb_delete_table(struct acpi_table_desc *table_desc);
|
||||||
|
|
||||||
void acpi_tb_terminate(void);
|
void acpi_tb_terminate(void);
|
||||||
|
|
||||||
void acpi_tb_delete_namespace_by_owner(u32 table_index);
|
acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index);
|
||||||
|
|
||||||
acpi_status acpi_tb_allocate_owner_id(u32 table_index);
|
acpi_status acpi_tb_allocate_owner_id(u32 table_index);
|
||||||
|
|
||||||
|
|
|
@ -345,6 +345,21 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
|
||||||
acpi_status
|
acpi_status
|
||||||
acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest);
|
acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* utlock - reader/writer locks
|
||||||
|
*/
|
||||||
|
acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock);
|
||||||
|
|
||||||
|
void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock);
|
||||||
|
|
||||||
|
acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock);
|
||||||
|
|
||||||
|
acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock);
|
||||||
|
|
||||||
|
acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock);
|
||||||
|
|
||||||
|
void acpi_ut_release_write_lock(struct acpi_rw_lock *lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* utobject - internal object create/delete/cache routines
|
* utobject - internal object create/delete/cache routines
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -180,11 +180,23 @@ acpi_ds_initialize_objects(u32 table_index,
|
||||||
|
|
||||||
/* Walk entire namespace from the supplied root */
|
/* Walk entire namespace from the supplied root */
|
||||||
|
|
||||||
status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
|
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||||
acpi_ds_init_one_object, &info, NULL);
|
if (ACPI_FAILURE(status)) {
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't use acpi_walk_namespace since we do not want to acquire
|
||||||
|
* the namespace reader lock.
|
||||||
|
*/
|
||||||
|
status =
|
||||||
|
acpi_ns_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
|
||||||
|
ACPI_NS_WALK_UNLOCK, acpi_ds_init_one_object,
|
||||||
|
&info, NULL);
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
|
ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
|
||||||
}
|
}
|
||||||
|
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||||
|
|
||||||
status = acpi_get_table_by_index(table_index, &table);
|
status = acpi_get_table_by_index(table_index, &table);
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
|
|
|
@ -520,13 +520,14 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Delete the portion of the namespace owned by this table */
|
||||||
* Delete the entire namespace under this table Node
|
|
||||||
* (Offset contains the table_id)
|
|
||||||
*/
|
|
||||||
acpi_tb_delete_namespace_by_owner(table_index);
|
|
||||||
(void)acpi_tb_release_owner_id(table_index);
|
|
||||||
|
|
||||||
|
status = acpi_tb_delete_namespace_by_owner(table_index);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)acpi_tb_release_owner_id(table_index);
|
||||||
acpi_tb_set_table_loaded_flag(table_index, FALSE);
|
acpi_tb_set_table_loaded_flag(table_index, FALSE);
|
||||||
|
|
||||||
/* Table unloaded, remove a reference to the ddb_handle object */
|
/* Table unloaded, remove a reference to the ddb_handle object */
|
||||||
|
|
|
@ -475,21 +475,40 @@ acpi_walk_namespace(acpi_object_type type,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lock the namespace around the walk.
|
* Need to acquire the namespace reader lock to prevent interference
|
||||||
* The namespace will be unlocked/locked around each call
|
* with any concurrent table unloads (which causes the deletion of
|
||||||
* to the user function - since this function
|
* namespace objects). We cannot allow the deletion of a namespace node
|
||||||
* must be allowed to make Acpi calls itself.
|
* while the user function is using it. The exception to this are the
|
||||||
|
* nodes created and deleted during control method execution -- these
|
||||||
|
* nodes are marked as temporary nodes and are ignored by the namespace
|
||||||
|
* walk. Thus, control methods can be executed while holding the
|
||||||
|
* namespace deletion lock (and the user function can execute control
|
||||||
|
* methods.)
|
||||||
|
*/
|
||||||
|
status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lock the namespace around the walk. The namespace will be
|
||||||
|
* unlocked/locked around each call to the user function - since the user
|
||||||
|
* function must be allowed to make ACPICA calls itself (for example, it
|
||||||
|
* will typically execute control methods during device enumeration.)
|
||||||
*/
|
*/
|
||||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
return_ACPI_STATUS(status);
|
goto unlock_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = acpi_ns_walk_namespace(type, start_object, max_depth,
|
status = acpi_ns_walk_namespace(type, start_object, max_depth,
|
||||||
ACPI_NS_WALK_UNLOCK,
|
ACPI_NS_WALK_UNLOCK, user_function,
|
||||||
user_function, context, return_value);
|
context, return_value);
|
||||||
|
|
||||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||||
|
|
||||||
|
unlock_and_exit:
|
||||||
|
(void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock);
|
||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -434,27 +434,56 @@ void acpi_tb_terminate(void)
|
||||||
*
|
*
|
||||||
* PARAMETERS: table_index - Table index
|
* PARAMETERS: table_index - Table index
|
||||||
*
|
*
|
||||||
* RETURN: None
|
* RETURN: Status
|
||||||
*
|
*
|
||||||
* DESCRIPTION: Delete all namespace objects created when this table was loaded.
|
* DESCRIPTION: Delete all namespace objects created when this table was loaded.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
void acpi_tb_delete_namespace_by_owner(u32 table_index)
|
acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
|
||||||
{
|
{
|
||||||
acpi_owner_id owner_id;
|
acpi_owner_id owner_id;
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner);
|
||||||
if (table_index < acpi_gbl_root_table_list.count) {
|
|
||||||
owner_id =
|
status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||||
acpi_gbl_root_table_list.tables[table_index].owner_id;
|
if (ACPI_FAILURE(status)) {
|
||||||
} else {
|
return_ACPI_STATUS(status);
|
||||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (table_index >= acpi_gbl_root_table_list.count) {
|
||||||
|
|
||||||
|
/* The table index does not exist */
|
||||||
|
|
||||||
|
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||||
|
return_ACPI_STATUS(AE_NOT_EXIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the owner ID for this table, used to delete namespace nodes */
|
||||||
|
|
||||||
|
owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id;
|
||||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to acquire the namespace writer lock to prevent interference
|
||||||
|
* with any concurrent namespace walks. The interpreter must be
|
||||||
|
* released during the deletion since the acquisition of the deletion
|
||||||
|
* lock may block, and also since the execution of a namespace walk
|
||||||
|
* must be allowed to use the interpreter.
|
||||||
|
*/
|
||||||
|
acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
|
||||||
|
status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
|
||||||
|
|
||||||
acpi_ns_delete_namespace_by_owner(owner_id);
|
acpi_ns_delete_namespace_by_owner(owner_id);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
|
||||||
|
|
||||||
|
status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
175
drivers/acpi/acpica/utlock.c
Normal file
175
drivers/acpi/acpica/utlock.c
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Module Name: utlock - Reader/Writer lock interfaces
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2000 - 2009, Intel Corp.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions, and the following disclaimer,
|
||||||
|
* without modification.
|
||||||
|
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||||
|
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||||
|
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||||
|
* including a substantially similar Disclaimer requirement for further
|
||||||
|
* binary redistribution.
|
||||||
|
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||||
|
* of any contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* Alternatively, this software may be distributed under the terms of the
|
||||||
|
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||||
|
* Software Foundation.
|
||||||
|
*
|
||||||
|
* NO WARRANTY
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <acpi/acpi.h>
|
||||||
|
#include "accommon.h"
|
||||||
|
|
||||||
|
#define _COMPONENT ACPI_UTILITIES
|
||||||
|
ACPI_MODULE_NAME("utlock")
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_ut_create_rw_lock
|
||||||
|
* acpi_ut_delete_rw_lock
|
||||||
|
*
|
||||||
|
* PARAMETERS: Lock - Pointer to a valid RW lock
|
||||||
|
*
|
||||||
|
* RETURN: Status
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Reader/writer lock creation and deletion interfaces.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock)
|
||||||
|
{
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
lock->num_readers = 0;
|
||||||
|
status = acpi_os_create_mutex(&lock->reader_mutex);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = acpi_os_create_mutex(&lock->writer_mutex);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock)
|
||||||
|
{
|
||||||
|
|
||||||
|
acpi_os_delete_mutex(lock->reader_mutex);
|
||||||
|
acpi_os_delete_mutex(lock->writer_mutex);
|
||||||
|
|
||||||
|
lock->num_readers = 0;
|
||||||
|
lock->reader_mutex = NULL;
|
||||||
|
lock->writer_mutex = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_ut_acquire_read_lock
|
||||||
|
* acpi_ut_release_read_lock
|
||||||
|
*
|
||||||
|
* PARAMETERS: Lock - Pointer to a valid RW lock
|
||||||
|
*
|
||||||
|
* RETURN: Status
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Reader interfaces for reader/writer locks. On acquisition,
|
||||||
|
* only the first reader acquires the write mutex. On release,
|
||||||
|
* only the last reader releases the write mutex. Although this
|
||||||
|
* algorithm can in theory starve writers, this should not be a
|
||||||
|
* problem with ACPICA since the subsystem is infrequently used
|
||||||
|
* in comparison to (for example) an I/O system.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock)
|
||||||
|
{
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Acquire the write lock only for the first reader */
|
||||||
|
|
||||||
|
lock->num_readers++;
|
||||||
|
if (lock->num_readers == 1) {
|
||||||
|
status =
|
||||||
|
acpi_os_acquire_mutex(lock->writer_mutex,
|
||||||
|
ACPI_WAIT_FOREVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
acpi_os_release_mutex(lock->reader_mutex);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock)
|
||||||
|
{
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the write lock only for the very last reader */
|
||||||
|
|
||||||
|
lock->num_readers--;
|
||||||
|
if (lock->num_readers == 0) {
|
||||||
|
acpi_os_release_mutex(lock->writer_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
acpi_os_release_mutex(lock->reader_mutex);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_ut_acquire_write_lock
|
||||||
|
* acpi_ut_release_write_lock
|
||||||
|
*
|
||||||
|
* PARAMETERS: Lock - Pointer to a valid RW lock
|
||||||
|
*
|
||||||
|
* RETURN: Status
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Writer interfaces for reader/writer locks. Simply acquire or
|
||||||
|
* release the writer mutex associated with the lock. Acquisition
|
||||||
|
* of the lock is fully exclusive and will block all readers and
|
||||||
|
* writers until it is released.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock)
|
||||||
|
{
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
status = acpi_os_acquire_mutex(lock->writer_mutex, ACPI_WAIT_FOREVER);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void acpi_ut_release_write_lock(struct acpi_rw_lock *lock)
|
||||||
|
{
|
||||||
|
|
||||||
|
acpi_os_release_mutex(lock->writer_mutex);
|
||||||
|
}
|
|
@ -60,7 +60,8 @@ static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id);
|
||||||
*
|
*
|
||||||
* RETURN: Status
|
* RETURN: Status
|
||||||
*
|
*
|
||||||
* DESCRIPTION: Create the system mutex objects.
|
* DESCRIPTION: Create the system mutex objects. This includes mutexes,
|
||||||
|
* spin locks, and reader/writer locks.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
@ -71,9 +72,8 @@ acpi_status acpi_ut_mutex_initialize(void)
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE(ut_mutex_initialize);
|
ACPI_FUNCTION_TRACE(ut_mutex_initialize);
|
||||||
|
|
||||||
/*
|
/* Create each of the predefined mutex objects */
|
||||||
* Create each of the predefined mutex objects
|
|
||||||
*/
|
|
||||||
for (i = 0; i < ACPI_NUM_MUTEX; i++) {
|
for (i = 0; i < ACPI_NUM_MUTEX; i++) {
|
||||||
status = acpi_ut_create_mutex(i);
|
status = acpi_ut_create_mutex(i);
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
|
@ -86,6 +86,9 @@ acpi_status acpi_ut_mutex_initialize(void)
|
||||||
spin_lock_init(acpi_gbl_gpe_lock);
|
spin_lock_init(acpi_gbl_gpe_lock);
|
||||||
spin_lock_init(acpi_gbl_hardware_lock);
|
spin_lock_init(acpi_gbl_hardware_lock);
|
||||||
|
|
||||||
|
/* Create the reader/writer lock for namespace access */
|
||||||
|
|
||||||
|
status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock);
|
||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +100,8 @@ acpi_status acpi_ut_mutex_initialize(void)
|
||||||
*
|
*
|
||||||
* RETURN: None.
|
* RETURN: None.
|
||||||
*
|
*
|
||||||
* DESCRIPTION: Delete all of the system mutex objects.
|
* DESCRIPTION: Delete all of the system mutex objects. This includes mutexes,
|
||||||
|
* spin locks, and reader/writer locks.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
@ -107,9 +111,8 @@ void acpi_ut_mutex_terminate(void)
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE(ut_mutex_terminate);
|
ACPI_FUNCTION_TRACE(ut_mutex_terminate);
|
||||||
|
|
||||||
/*
|
/* Delete each predefined mutex object */
|
||||||
* Delete each predefined mutex object
|
|
||||||
*/
|
|
||||||
for (i = 0; i < ACPI_NUM_MUTEX; i++) {
|
for (i = 0; i < ACPI_NUM_MUTEX; i++) {
|
||||||
(void)acpi_ut_delete_mutex(i);
|
(void)acpi_ut_delete_mutex(i);
|
||||||
}
|
}
|
||||||
|
@ -118,6 +121,10 @@ void acpi_ut_mutex_terminate(void)
|
||||||
|
|
||||||
acpi_os_delete_lock(acpi_gbl_gpe_lock);
|
acpi_os_delete_lock(acpi_gbl_gpe_lock);
|
||||||
acpi_os_delete_lock(acpi_gbl_hardware_lock);
|
acpi_os_delete_lock(acpi_gbl_hardware_lock);
|
||||||
|
|
||||||
|
/* Delete the reader/writer lock */
|
||||||
|
|
||||||
|
acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock);
|
||||||
return_VOID;
|
return_VOID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue