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);