aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/executer/exmutex.c
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2008-04-10 11:06:37 -0400
committerLen Brown <len.brown@intel.com>2008-04-22 14:29:21 -0400
commitba886cd4ac957608777fbc8d137f6b9f0450e775 (patch)
treed7dabaa586af41c293977443ee20df6b6b13d171 /drivers/acpi/executer/exmutex.c
parentf654ecbfacb47d20e8cac087bbada1b947db846b (diff)
ACPICA: Update for mutiple global lock acquisitions by same thread
Allows AcpiAcquireGlobalLock external interface to be called multiple times by the same thread. Allows use of AML fields that require the global lock while the running AML is already holding the global lock. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/executer/exmutex.c')
-rw-r--r--drivers/acpi/executer/exmutex.c194
1 files changed, 126 insertions, 68 deletions
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index 6748e3ef0997..0bebe751aac5 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -126,6 +126,66 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
126 126
127/******************************************************************************* 127/*******************************************************************************
128 * 128 *
129 * FUNCTION: acpi_ex_acquire_mutex_object
130 *
131 * PARAMETERS: time_desc - Timeout in milliseconds
132 * obj_desc - Mutex object
133 * Thread - Current thread state
134 *
135 * RETURN: Status
136 *
137 * DESCRIPTION: Acquire an AML mutex, low-level interface
138 *
139 ******************************************************************************/
140
141acpi_status
142acpi_ex_acquire_mutex_object(u16 timeout,
143 union acpi_operand_object *obj_desc,
144 acpi_thread_id thread_id)
145{
146 acpi_status status;
147
148 ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc);
149
150 /* Support for multiple acquires by the owning thread */
151
152 if (obj_desc->mutex.thread_id == thread_id) {
153 /*
154 * The mutex is already owned by this thread, just increment the
155 * acquisition depth
156 */
157 obj_desc->mutex.acquisition_depth++;
158 return_ACPI_STATUS(AE_OK);
159 }
160
161 /* Acquire the mutex, wait if necessary. Special case for Global Lock */
162
163 if (obj_desc == acpi_gbl_global_lock_mutex) {
164 status = acpi_ev_acquire_global_lock(timeout);
165 } else {
166 status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex,
167 timeout);
168 }
169
170 if (ACPI_FAILURE(status)) {
171
172 /* Includes failure from a timeout on time_desc */
173
174 return_ACPI_STATUS(status);
175 }
176
177 /* Have the mutex: update mutex and save the sync_level */
178
179 obj_desc->mutex.thread_id = thread_id;
180 obj_desc->mutex.acquisition_depth = 1;
181 obj_desc->mutex.original_sync_level = 0;
182 obj_desc->mutex.owner_thread = NULL; /* Used only for AML Acquire() */
183
184 return_ACPI_STATUS(AE_OK);
185}
186
187/*******************************************************************************
188 *
129 * FUNCTION: acpi_ex_acquire_mutex 189 * FUNCTION: acpi_ex_acquire_mutex
130 * 190 *
131 * PARAMETERS: time_desc - Timeout integer 191 * PARAMETERS: time_desc - Timeout integer
@@ -161,7 +221,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
161 } 221 }
162 222
163 /* 223 /*
164 * Current Sync must be less than or equal to the sync level of the 224 * Current Sync level must be less than or equal to the sync level of the
165 * mutex. This mechanism provides some deadlock prevention 225 * mutex. This mechanism provides some deadlock prevention
166 */ 226 */
167 if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { 227 if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
@@ -172,51 +232,70 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
172 return_ACPI_STATUS(AE_AML_MUTEX_ORDER); 232 return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
173 } 233 }
174 234
175 /* Support for multiple acquires by the owning thread */ 235 status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value,
236 obj_desc,
237 walk_state->thread->thread_id);
238 if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) {
239 obj_desc->mutex.owner_thread = walk_state->thread;
240 obj_desc->mutex.original_sync_level =
241 walk_state->thread->current_sync_level;
242 walk_state->thread->current_sync_level =
243 obj_desc->mutex.sync_level;
176 244
177 if (obj_desc->mutex.owner_thread) { 245 /* Link the mutex to the current thread for force-unlock at method exit */
178 if (obj_desc->mutex.owner_thread->thread_id == 246
179 walk_state->thread->thread_id) { 247 acpi_ex_link_mutex(obj_desc, walk_state->thread);
180 /*
181 * The mutex is already owned by this thread, just increment the
182 * acquisition depth
183 */
184 obj_desc->mutex.acquisition_depth++;
185 return_ACPI_STATUS(AE_OK);
186 }
187 } 248 }
188 249
189 /* Acquire the mutex, wait if necessary. Special case for Global Lock */ 250 return_ACPI_STATUS(status);
251}
190 252
191 if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { 253/*******************************************************************************
192 status = 254 *
193 acpi_ev_acquire_global_lock((u16) time_desc->integer.value); 255 * FUNCTION: acpi_ex_release_mutex_object
194 } else { 256 *
195 status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, 257 * PARAMETERS: obj_desc - The object descriptor for this op
196 (u16) time_desc->integer. 258 *
197 value); 259 * RETURN: Status
198 } 260 *
261 * DESCRIPTION: Release a previously acquired Mutex, low level interface.
262 *
263 ******************************************************************************/
199 264
200 if (ACPI_FAILURE(status)) { 265acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
266{
267 acpi_status status = AE_OK;
201 268
202 /* Includes failure from a timeout on time_desc */ 269 ACPI_FUNCTION_TRACE(ex_release_mutex_object);
203 270
204 return_ACPI_STATUS(status); 271 /* Match multiple Acquires with multiple Releases */
272
273 obj_desc->mutex.acquisition_depth--;
274 if (obj_desc->mutex.acquisition_depth != 0) {
275
276 /* Just decrement the depth and return */
277
278 return_ACPI_STATUS(AE_OK);
205 } 279 }
206 280
207 /* Have the mutex: update mutex and walk info and save the sync_level */ 281 if (obj_desc->mutex.owner_thread) {
208 282
209 obj_desc->mutex.owner_thread = walk_state->thread; 283 /* Unlink the mutex from the owner's list */
210 obj_desc->mutex.acquisition_depth = 1; 284
211 obj_desc->mutex.original_sync_level = 285 acpi_ex_unlink_mutex(obj_desc);
212 walk_state->thread->current_sync_level; 286 obj_desc->mutex.owner_thread = NULL;
287 }
213 288
214 walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; 289 /* Release the mutex, special case for Global Lock */
215 290
216 /* Link the mutex to the current thread for force-unlock at method exit */ 291 if (obj_desc == acpi_gbl_global_lock_mutex) {
292 status = acpi_ev_release_global_lock();
293 } else {
294 acpi_os_release_mutex(obj_desc->mutex.os_mutex);
295 }
217 296
218 acpi_ex_link_mutex(obj_desc, walk_state->thread); 297 obj_desc->mutex.thread_id = 0;
219 return_ACPI_STATUS(AE_OK); 298 return_ACPI_STATUS(status);
220} 299}
221 300
222/******************************************************************************* 301/*******************************************************************************
@@ -253,22 +332,13 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
253 return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); 332 return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
254 } 333 }
255 334
256 /* Sanity check: we must have a valid thread ID */
257
258 if (!walk_state->thread) {
259 ACPI_ERROR((AE_INFO,
260 "Cannot release Mutex [%4.4s], null thread info",
261 acpi_ut_get_node_name(obj_desc->mutex.node)));
262 return_ACPI_STATUS(AE_AML_INTERNAL);
263 }
264
265 /* 335 /*
266 * The Mutex is owned, but this thread must be the owner. 336 * The Mutex is owned, but this thread must be the owner.
267 * Special case for Global Lock, any thread can release 337 * Special case for Global Lock, any thread can release
268 */ 338 */
269 if ((obj_desc->mutex.owner_thread->thread_id != 339 if ((obj_desc->mutex.owner_thread->thread_id !=
270 walk_state->thread->thread_id) 340 walk_state->thread->thread_id)
271 && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { 341 && (obj_desc != acpi_gbl_global_lock_mutex)) {
272 ACPI_ERROR((AE_INFO, 342 ACPI_ERROR((AE_INFO,
273 "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", 343 "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX",
274 (unsigned long)walk_state->thread->thread_id, 344 (unsigned long)walk_state->thread->thread_id,
@@ -278,6 +348,15 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
278 return_ACPI_STATUS(AE_AML_NOT_OWNER); 348 return_ACPI_STATUS(AE_AML_NOT_OWNER);
279 } 349 }
280 350
351 /* Sanity check: we must have a valid thread ID */
352
353 if (!walk_state->thread) {
354 ACPI_ERROR((AE_INFO,
355 "Cannot release Mutex [%4.4s], null thread info",
356 acpi_ut_get_node_name(obj_desc->mutex.node)));
357 return_ACPI_STATUS(AE_AML_INTERNAL);
358 }
359
281 /* 360 /*
282 * The sync level of the mutex must be less than or equal to the current 361 * The sync level of the mutex must be less than or equal to the current
283 * sync level 362 * sync level
@@ -289,34 +368,12 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
289 return_ACPI_STATUS(AE_AML_MUTEX_ORDER); 368 return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
290 } 369 }
291 370
292 /* Match multiple Acquires with multiple Releases */ 371 status = acpi_ex_release_mutex_object(obj_desc);
293
294 obj_desc->mutex.acquisition_depth--;
295 if (obj_desc->mutex.acquisition_depth != 0) {
296
297 /* Just decrement the depth and return */
298
299 return_ACPI_STATUS(AE_OK);
300 }
301
302 /* Unlink the mutex from the owner's list */
303 372
304 acpi_ex_unlink_mutex(obj_desc); 373 /* Restore sync_level */
305
306 /* Release the mutex, special case for Global Lock */
307 374
308 if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) {
309 status = acpi_ev_release_global_lock();
310 } else {
311 acpi_os_release_mutex(obj_desc->mutex.os_mutex);
312 }
313
314 /* Update the mutex and restore sync_level */
315
316 obj_desc->mutex.owner_thread = NULL;
317 walk_state->thread->current_sync_level = 375 walk_state->thread->current_sync_level =
318 obj_desc->mutex.original_sync_level; 376 obj_desc->mutex.original_sync_level;
319
320 return_ACPI_STATUS(status); 377 return_ACPI_STATUS(status);
321} 378}
322 379
@@ -357,7 +414,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
357 414
358 /* Release the mutex, special case for Global Lock */ 415 /* Release the mutex, special case for Global Lock */
359 416
360 if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { 417 if (obj_desc == acpi_gbl_global_lock_mutex) {
361 418
362 /* Ignore errors */ 419 /* Ignore errors */
363 420
@@ -369,6 +426,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
369 /* Mark mutex unowned */ 426 /* Mark mutex unowned */
370 427
371 obj_desc->mutex.owner_thread = NULL; 428 obj_desc->mutex.owner_thread = NULL;
429 obj_desc->mutex.thread_id = 0;
372 430
373 /* Update Thread sync_level (Last mutex is the important one) */ 431 /* Update Thread sync_level (Last mutex is the important one) */
374 432