aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2009-03-09 04:31:04 -0400
committerLen Brown <len.brown@intel.com>2009-03-27 12:11:02 -0400
commit8a335a2331c72e60c6b3ef09b2dedd3ba00da1b1 (patch)
treef538a4f68499dab0d59e253bc55a5cf4aff66ec1 /drivers/acpi/acpica
parentaab61b676a024d3527f6201e2b31285a96f7a1d2 (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')
-rw-r--r--drivers/acpi/acpica/Makefile2
-rw-r--r--drivers/acpi/acpica/acglobal.h4
-rw-r--r--drivers/acpi/acpica/aclocal.h8
-rw-r--r--drivers/acpi/acpica/actables.h2
-rw-r--r--drivers/acpi/acpica/acutils.h15
-rw-r--r--drivers/acpi/acpica/dsinit.c16
-rw-r--r--drivers/acpi/acpica/exconfig.c13
-rw-r--r--drivers/acpi/acpica/nsxfeval.c33
-rw-r--r--drivers/acpi/acpica/tbinstal.c45
-rw-r--r--drivers/acpi/acpica/utlock.c175
-rw-r--r--drivers/acpi/acpica/utmutex.c23
11 files changed, 303 insertions, 33 deletions
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index 3f23298ee3fd..290be74b774d 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -41,4 +41,4 @@ obj-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
41 41
42obj-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ 42obj-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
43 utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ 43 utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
44 utstate.o utmutex.o utobject.o utresrc.o 44 utstate.o utmutex.o utobject.o utresrc.o utlock.o
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index f3e87ba43dbe..f431b997d2f8 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -165,6 +165,10 @@ ACPI_EXTERN u8 acpi_gbl_integer_bit_width;
165ACPI_EXTERN u8 acpi_gbl_integer_byte_width; 165ACPI_EXTERN u8 acpi_gbl_integer_byte_width;
166ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; 166ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
167 167
168/* Reader/Writer lock is used for namespace walk and dynamic table unload */
169
170ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock;
171
168/***************************************************************************** 172/*****************************************************************************
169 * 173 *
170 * Mutual exlusion within ACPICA subsystem 174 * Mutual exlusion within ACPICA subsystem
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 6feebc8f789a..18a8d96eaa49 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -108,6 +108,14 @@ static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
108#endif 108#endif
109#endif 109#endif
110 110
111/* Lock structure for reader/writer interfaces */
112
113struct acpi_rw_lock {
114 acpi_mutex writer_mutex;
115 acpi_mutex reader_mutex;
116 u32 num_readers;
117};
118
111/* 119/*
112 * Predefined handles for spinlocks used within the subsystem. 120 * Predefined handles for spinlocks used within the subsystem.
113 * These spinlocks are created by acpi_ut_mutex_initialize 121 * These spinlocks are created by acpi_ut_mutex_initialize
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h
index d8f8c5df4fbc..01c76b8ea7ba 100644
--- a/drivers/acpi/acpica/actables.h
+++ b/drivers/acpi/acpica/actables.h
@@ -79,7 +79,7 @@ void acpi_tb_delete_table(struct acpi_table_desc *table_desc);
79 79
80void acpi_tb_terminate(void); 80void acpi_tb_terminate(void);
81 81
82void acpi_tb_delete_namespace_by_owner(u32 table_index); 82acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index);
83 83
84acpi_status acpi_tb_allocate_owner_id(u32 table_index); 84acpi_status acpi_tb_allocate_owner_id(u32 table_index);
85 85
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 80d8813484fe..897810ba0ccc 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -346,6 +346,21 @@ acpi_status
346acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest); 346acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest);
347 347
348/* 348/*
349 * utlock - reader/writer locks
350 */
351acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock);
352
353void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock);
354
355acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock);
356
357acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock);
358
359acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock);
360
361void acpi_ut_release_write_lock(struct acpi_rw_lock *lock);
362
363/*
349 * utobject - internal object create/delete/cache routines 364 * utobject - internal object create/delete/cache routines
350 */ 365 */
351union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char 366union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char
diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c
index eb144b13d8fa..3aae13f30c5e 100644
--- a/drivers/acpi/acpica/dsinit.c
+++ b/drivers/acpi/acpica/dsinit.c
@@ -180,11 +180,23 @@ acpi_ds_initialize_objects(u32 table_index,
180 180
181 /* Walk entire namespace from the supplied root */ 181 /* Walk entire namespace from the supplied root */
182 182
183 status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, 183 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
184 acpi_ds_init_one_object, &info, NULL); 184 if (ACPI_FAILURE(status)) {
185 return_ACPI_STATUS(status);
186 }
187
188 /*
189 * We don't use acpi_walk_namespace since we do not want to acquire
190 * the namespace reader lock.
191 */
192 status =
193 acpi_ns_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
194 ACPI_NS_WALK_UNLOCK, acpi_ds_init_one_object,
195 &info, NULL);
185 if (ACPI_FAILURE(status)) { 196 if (ACPI_FAILURE(status)) {
186 ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); 197 ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
187 } 198 }
199 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
188 200
189 status = acpi_get_table_by_index(table_index, &table); 201 status = acpi_get_table_by_index(table_index, &table);
190 if (ACPI_FAILURE(status)) { 202 if (ACPI_FAILURE(status)) {
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c
index 70b39c7daeab..3deb20a126b2 100644
--- a/drivers/acpi/acpica/exconfig.c
+++ b/drivers/acpi/acpica/exconfig.c
@@ -520,13 +520,14 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
520 } 520 }
521 } 521 }
522 522
523 /* 523 /* Delete the portion of the namespace owned by this table */
524 * Delete the entire namespace under this table Node 524
525 * (Offset contains the table_id) 525 status = acpi_tb_delete_namespace_by_owner(table_index);
526 */ 526 if (ACPI_FAILURE(status)) {
527 acpi_tb_delete_namespace_by_owner(table_index); 527 return_ACPI_STATUS(status);
528 (void)acpi_tb_release_owner_id(table_index); 528 }
529 529
530 (void)acpi_tb_release_owner_id(table_index);
530 acpi_tb_set_table_loaded_flag(table_index, FALSE); 531 acpi_tb_set_table_loaded_flag(table_index, FALSE);
531 532
532 /* Table unloaded, remove a reference to the ddb_handle object */ 533 /* Table unloaded, remove a reference to the ddb_handle object */
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c
index 2583a66a60a7..045054037c2d 100644
--- a/drivers/acpi/acpica/nsxfeval.c
+++ b/drivers/acpi/acpica/nsxfeval.c
@@ -475,21 +475,40 @@ acpi_walk_namespace(acpi_object_type type,
475 } 475 }
476 476
477 /* 477 /*
478 * Lock the namespace around the walk. 478 * Need to acquire the namespace reader lock to prevent interference
479 * The namespace will be unlocked/locked around each call 479 * with any concurrent table unloads (which causes the deletion of
480 * to the user function - since this function 480 * namespace objects). We cannot allow the deletion of a namespace node
481 * must be allowed to make Acpi calls itself. 481 * while the user function is using it. The exception to this are the
482 * nodes created and deleted during control method execution -- these
483 * nodes are marked as temporary nodes and are ignored by the namespace
484 * walk. Thus, control methods can be executed while holding the
485 * namespace deletion lock (and the user function can execute control
486 * methods.)
487 */
488 status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock);
489 if (ACPI_FAILURE(status)) {
490 return status;
491 }
492
493 /*
494 * Lock the namespace around the walk. The namespace will be
495 * unlocked/locked around each call to the user function - since the user
496 * function must be allowed to make ACPICA calls itself (for example, it
497 * will typically execute control methods during device enumeration.)
482 */ 498 */
483 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 499 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
484 if (ACPI_FAILURE(status)) { 500 if (ACPI_FAILURE(status)) {
485 return_ACPI_STATUS(status); 501 goto unlock_and_exit;
486 } 502 }
487 503
488 status = acpi_ns_walk_namespace(type, start_object, max_depth, 504 status = acpi_ns_walk_namespace(type, start_object, max_depth,
489 ACPI_NS_WALK_UNLOCK, 505 ACPI_NS_WALK_UNLOCK, user_function,
490 user_function, context, return_value); 506 context, return_value);
491 507
492 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 508 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
509
510 unlock_and_exit:
511 (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock);
493 return_ACPI_STATUS(status); 512 return_ACPI_STATUS(status);
494} 513}
495 514
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
443void acpi_tb_delete_namespace_by_owner(u32 table_index) 443acpi_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/*******************************************************************************
diff --git a/drivers/acpi/acpica/utlock.c b/drivers/acpi/acpica/utlock.c
new file mode 100644
index 000000000000..25e03120686d
--- /dev/null
+++ b/drivers/acpi/acpica/utlock.c
@@ -0,0 +1,175 @@
1/******************************************************************************
2 *
3 * Module Name: utlock - Reader/Writer lock interfaces
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2009, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <acpi/acpi.h>
45#include "accommon.h"
46
47#define _COMPONENT ACPI_UTILITIES
48ACPI_MODULE_NAME("utlock")
49
50/*******************************************************************************
51 *
52 * FUNCTION: acpi_ut_create_rw_lock
53 * acpi_ut_delete_rw_lock
54 *
55 * PARAMETERS: Lock - Pointer to a valid RW lock
56 *
57 * RETURN: Status
58 *
59 * DESCRIPTION: Reader/writer lock creation and deletion interfaces.
60 *
61 ******************************************************************************/
62acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock)
63{
64 acpi_status status;
65
66 lock->num_readers = 0;
67 status = acpi_os_create_mutex(&lock->reader_mutex);
68 if (ACPI_FAILURE(status)) {
69 return status;
70 }
71
72 status = acpi_os_create_mutex(&lock->writer_mutex);
73 return status;
74}
75
76void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock)
77{
78
79 acpi_os_delete_mutex(lock->reader_mutex);
80 acpi_os_delete_mutex(lock->writer_mutex);
81
82 lock->num_readers = 0;
83 lock->reader_mutex = NULL;
84 lock->writer_mutex = NULL;
85}
86
87/*******************************************************************************
88 *
89 * FUNCTION: acpi_ut_acquire_read_lock
90 * acpi_ut_release_read_lock
91 *
92 * PARAMETERS: Lock - Pointer to a valid RW lock
93 *
94 * RETURN: Status
95 *
96 * DESCRIPTION: Reader interfaces for reader/writer locks. On acquisition,
97 * only the first reader acquires the write mutex. On release,
98 * only the last reader releases the write mutex. Although this
99 * algorithm can in theory starve writers, this should not be a
100 * problem with ACPICA since the subsystem is infrequently used
101 * in comparison to (for example) an I/O system.
102 *
103 ******************************************************************************/
104
105acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock)
106{
107 acpi_status status;
108
109 status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER);
110 if (ACPI_FAILURE(status)) {
111 return status;
112 }
113
114 /* Acquire the write lock only for the first reader */
115
116 lock->num_readers++;
117 if (lock->num_readers == 1) {
118 status =
119 acpi_os_acquire_mutex(lock->writer_mutex,
120 ACPI_WAIT_FOREVER);
121 }
122
123 acpi_os_release_mutex(lock->reader_mutex);
124 return status;
125}
126
127acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock)
128{
129 acpi_status status;
130
131 status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER);
132 if (ACPI_FAILURE(status)) {
133 return status;
134 }
135
136 /* Release the write lock only for the very last reader */
137
138 lock->num_readers--;
139 if (lock->num_readers == 0) {
140 acpi_os_release_mutex(lock->writer_mutex);
141 }
142
143 acpi_os_release_mutex(lock->reader_mutex);
144 return status;
145}
146
147/*******************************************************************************
148 *
149 * FUNCTION: acpi_ut_acquire_write_lock
150 * acpi_ut_release_write_lock
151 *
152 * PARAMETERS: Lock - Pointer to a valid RW lock
153 *
154 * RETURN: Status
155 *
156 * DESCRIPTION: Writer interfaces for reader/writer locks. Simply acquire or
157 * release the writer mutex associated with the lock. Acquisition
158 * of the lock is fully exclusive and will block all readers and
159 * writers until it is released.
160 *
161 ******************************************************************************/
162
163acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock)
164{
165 acpi_status status;
166
167 status = acpi_os_acquire_mutex(lock->writer_mutex, ACPI_WAIT_FOREVER);
168 return status;
169}
170
171void acpi_ut_release_write_lock(struct acpi_rw_lock *lock)
172{
173
174 acpi_os_release_mutex(lock->writer_mutex);
175}
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c
index 14eb52c4d647..26c93a748e64 100644
--- a/drivers/acpi/acpica/utmutex.c
+++ b/drivers/acpi/acpica/utmutex.c
@@ -60,7 +60,8 @@ static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id);
60 * 60 *
61 * RETURN: Status 61 * RETURN: Status
62 * 62 *
63 * DESCRIPTION: Create the system mutex objects. 63 * DESCRIPTION: Create the system mutex objects. This includes mutexes,
64 * spin locks, and reader/writer locks.
64 * 65 *
65 ******************************************************************************/ 66 ******************************************************************************/
66 67
@@ -71,9 +72,8 @@ acpi_status acpi_ut_mutex_initialize(void)
71 72
72 ACPI_FUNCTION_TRACE(ut_mutex_initialize); 73 ACPI_FUNCTION_TRACE(ut_mutex_initialize);
73 74
74 /* 75 /* Create each of the predefined mutex objects */
75 * Create each of the predefined mutex objects 76
76 */
77 for (i = 0; i < ACPI_NUM_MUTEX; i++) { 77 for (i = 0; i < ACPI_NUM_MUTEX; i++) {
78 status = acpi_ut_create_mutex(i); 78 status = acpi_ut_create_mutex(i);
79 if (ACPI_FAILURE(status)) { 79 if (ACPI_FAILURE(status)) {
@@ -86,6 +86,9 @@ acpi_status acpi_ut_mutex_initialize(void)
86 spin_lock_init(acpi_gbl_gpe_lock); 86 spin_lock_init(acpi_gbl_gpe_lock);
87 spin_lock_init(acpi_gbl_hardware_lock); 87 spin_lock_init(acpi_gbl_hardware_lock);
88 88
89 /* Create the reader/writer lock for namespace access */
90
91 status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock);
89 return_ACPI_STATUS(status); 92 return_ACPI_STATUS(status);
90} 93}
91 94
@@ -97,7 +100,8 @@ acpi_status acpi_ut_mutex_initialize(void)
97 * 100 *
98 * RETURN: None. 101 * RETURN: None.
99 * 102 *
100 * DESCRIPTION: Delete all of the system mutex objects. 103 * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes,
104 * spin locks, and reader/writer locks.
101 * 105 *
102 ******************************************************************************/ 106 ******************************************************************************/
103 107
@@ -107,9 +111,8 @@ void acpi_ut_mutex_terminate(void)
107 111
108 ACPI_FUNCTION_TRACE(ut_mutex_terminate); 112 ACPI_FUNCTION_TRACE(ut_mutex_terminate);
109 113
110 /* 114 /* Delete each predefined mutex object */
111 * Delete each predefined mutex object 115
112 */
113 for (i = 0; i < ACPI_NUM_MUTEX; i++) { 116 for (i = 0; i < ACPI_NUM_MUTEX; i++) {
114 (void)acpi_ut_delete_mutex(i); 117 (void)acpi_ut_delete_mutex(i);
115 } 118 }
@@ -118,6 +121,10 @@ void acpi_ut_mutex_terminate(void)
118 121
119 acpi_os_delete_lock(acpi_gbl_gpe_lock); 122 acpi_os_delete_lock(acpi_gbl_gpe_lock);
120 acpi_os_delete_lock(acpi_gbl_hardware_lock); 123 acpi_os_delete_lock(acpi_gbl_hardware_lock);
124
125 /* Delete the reader/writer lock */
126
127 acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock);
121 return_VOID; 128 return_VOID;
122} 129}
123 130