2 /******************************************************************************
4 * Module Name: ammutex - ASL Mutex Acquire/Release functions
7 *****************************************************************************/
10 * Copyright (C) 2000, 2001 R. Byron Moore
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #define _COMPONENT ACPI_EXECUTER
35 MODULE_NAME ("ammutex")
38 /*******************************************************************************
40 * FUNCTION: Acpi_aml_unlink_mutex
42 * PARAMETERS: *Obj_desc - The mutex to be unlinked
46 * DESCRIPTION: Remove a mutex from the "Acquired_mutex" list
48 ******************************************************************************/
51 acpi_aml_unlink_mutex (
52 ACPI_OPERAND_OBJECT *obj_desc)
55 if (obj_desc->mutex.next) {
56 (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev;
58 if (obj_desc->mutex.prev) {
59 (obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next;
64 /*******************************************************************************
66 * FUNCTION: Acpi_aml_link_mutex
68 * PARAMETERS: *Obj_desc - The mutex to be linked
69 * *List_head - head of the "Acquired_mutex" list
73 * DESCRIPTION: Add a mutex to the "Acquired_mutex" list for this walk
75 ******************************************************************************/
79 ACPI_OPERAND_OBJECT *obj_desc,
80 ACPI_OPERAND_OBJECT *list_head)
83 /* This object will be the first object in the list */
85 obj_desc->mutex.prev = list_head;
86 obj_desc->mutex.next = list_head->mutex.next;
88 /* Update old first object to point back to this object */
90 if (list_head->mutex.next) {
91 (list_head->mutex.next)->mutex.prev = obj_desc;
94 /* Update list head */
96 list_head->mutex.next = obj_desc;
100 /*******************************************************************************
102 * FUNCTION: Acpi_aml_acquire_mutex
104 * PARAMETERS: *Time_desc - The 'time to delay' object descriptor
105 * *Obj_desc - The object descriptor for this op
109 * DESCRIPTION: Acquire an AML mutex
111 ******************************************************************************/
114 acpi_aml_acquire_mutex (
115 ACPI_OPERAND_OBJECT *time_desc,
116 ACPI_OPERAND_OBJECT *obj_desc,
117 ACPI_WALK_STATE *walk_state)
123 return (AE_BAD_PARAMETER);
127 * Current Sync must be less than or equal to the sync level of the
128 * mutex. This mechanism provides some deadlock prevention
130 if (walk_state->current_sync_level > obj_desc->mutex.sync_level) {
131 return (AE_AML_MUTEX_ORDER);
135 * If the mutex is already owned by this thread,
136 * just increment the acquisition depth
138 if (obj_desc->mutex.owner == walk_state) {
139 obj_desc->mutex.acquisition_depth++;
143 /* Acquire the mutex, wait if necessary */
145 status = acpi_aml_system_acquire_mutex (time_desc, obj_desc);
146 if (ACPI_FAILURE (status)) {
147 /* Includes failure from a timeout on Time_desc */
152 /* Have the mutex, update mutex and walk info */
154 obj_desc->mutex.owner = walk_state;
155 obj_desc->mutex.acquisition_depth = 1;
156 walk_state->current_sync_level = obj_desc->mutex.sync_level;
158 /* Link the mutex to the walk state for force-unlock at method exit */
160 acpi_aml_link_mutex (obj_desc, (ACPI_OPERAND_OBJECT *)
161 &(walk_state->walk_list->acquired_mutex_list));
167 /*******************************************************************************
169 * FUNCTION: Acpi_aml_release_mutex
171 * PARAMETERS: *Obj_desc - The object descriptor for this op
175 * DESCRIPTION: Release a previously acquired Mutex.
177 ******************************************************************************/
180 acpi_aml_release_mutex (
181 ACPI_OPERAND_OBJECT *obj_desc,
182 ACPI_WALK_STATE *walk_state)
188 return (AE_BAD_PARAMETER);
191 /* The mutex must have been previously acquired in order to release it */
193 if (!obj_desc->mutex.owner) {
194 return (AE_AML_MUTEX_NOT_ACQUIRED);
197 /* The Mutex is owned, but this thread must be the owner */
199 if (obj_desc->mutex.owner != walk_state) {
200 return (AE_AML_NOT_OWNER);
204 * The sync level of the mutex must be less than or
205 * equal to the current sync level
207 if (obj_desc->mutex.sync_level > walk_state->current_sync_level) {
208 return (AE_AML_MUTEX_ORDER);
212 * Match multiple Acquires with multiple Releases
214 obj_desc->mutex.acquisition_depth--;
215 if (obj_desc->mutex.acquisition_depth != 0) {
216 /* Just decrement the depth and return */
222 /* Release the mutex */
224 status = acpi_aml_system_release_mutex (obj_desc);
226 /* Update the mutex and walk state */
228 obj_desc->mutex.owner = NULL;
229 walk_state->current_sync_level = obj_desc->mutex.sync_level;
231 /* Unlink the mutex from the owner's list */
233 acpi_aml_unlink_mutex (obj_desc);
239 /*******************************************************************************
241 * FUNCTION: Acpi_aml_release_all_mutexes
243 * PARAMETERS: *Mutex_list - Head of the mutex list
247 * DESCRIPTION: Release all mutexes in the list
249 ******************************************************************************/
252 acpi_aml_release_all_mutexes (
253 ACPI_OPERAND_OBJECT *list_head)
255 ACPI_OPERAND_OBJECT *next = list_head->mutex.next;
256 ACPI_OPERAND_OBJECT *this;
260 * Traverse the list of owned mutexes, releasing each one.
264 next = this->mutex.next;
266 /* Mark mutex un-owned */
268 this->mutex.owner = NULL;
269 this->mutex.prev = NULL;
270 this->mutex.next = NULL;
271 this->mutex.acquisition_depth = 0;
273 /* Release the mutex */
275 acpi_aml_system_release_mutex (this);