Print this page
acpica-unix2-20130823
PANKOVs restructure
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/intel/io/acpica/executer/exmutex.c
+++ new/usr/src/common/acpica/components/executer/exmutex.c
1 -
2 1 /******************************************************************************
3 2 *
4 3 * Module Name: exmutex - ASL Mutex Acquire/Release functions
5 4 *
6 5 *****************************************************************************/
7 6
8 7 /*
9 - * Copyright (C) 2000 - 2011, Intel Corp.
8 + * Copyright (C) 2000 - 2013, Intel Corp.
10 9 * All rights reserved.
11 10 *
12 11 * Redistribution and use in source and binary forms, with or without
13 12 * modification, are permitted provided that the following conditions
14 13 * are met:
15 14 * 1. Redistributions of source code must retain the above copyright
16 15 * notice, this list of conditions, and the following disclaimer,
17 16 * without modification.
18 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 18 * substantially similar to the "NO WARRANTY" disclaimer below
20 19 * ("Disclaimer") and any redistribution must be conditioned upon
21 20 * including a substantially similar Disclaimer requirement for further
22 21 * binary redistribution.
23 22 * 3. Neither the names of the above-listed copyright holders nor the names
24 23 * of any contributors may be used to endorse or promote products derived
25 24 * from this software without specific prior written permission.
26 25 *
27 26 * Alternatively, this software may be distributed under the terms of the
28 27 * GNU General Public License ("GPL") version 2 as published by the Free
29 28 * Software Foundation.
30 29 *
31 30 * NO WARRANTY
32 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 41 * POSSIBILITY OF SUCH DAMAGES.
43 42 */
44 43
45 44 #define __EXMUTEX_C__
46 45
47 46 #include "acpi.h"
48 47 #include "accommon.h"
49 48 #include "acinterp.h"
50 49 #include "acevents.h"
51 50
52 51 #define _COMPONENT ACPI_EXECUTER
53 52 ACPI_MODULE_NAME ("exmutex")
54 53
55 54 /* Local prototypes */
56 55
57 56 static void
58 57 AcpiExLinkMutex (
59 58 ACPI_OPERAND_OBJECT *ObjDesc,
60 59 ACPI_THREAD_STATE *Thread);
61 60
62 61
63 62 /*******************************************************************************
64 63 *
65 64 * FUNCTION: AcpiExUnlinkMutex
66 65 *
67 66 * PARAMETERS: ObjDesc - The mutex to be unlinked
68 67 *
69 68 * RETURN: None
70 69 *
71 70 * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list
72 71 *
73 72 ******************************************************************************/
74 73
75 74 void
76 75 AcpiExUnlinkMutex (
77 76 ACPI_OPERAND_OBJECT *ObjDesc)
78 77 {
79 78 ACPI_THREAD_STATE *Thread = ObjDesc->Mutex.OwnerThread;
80 79
81 80
82 81 if (!Thread)
83 82 {
84 83 return;
85 84 }
86 85
87 86 /* Doubly linked list */
88 87
89 88 if (ObjDesc->Mutex.Next)
90 89 {
91 90 (ObjDesc->Mutex.Next)->Mutex.Prev = ObjDesc->Mutex.Prev;
92 91 }
93 92
94 93 if (ObjDesc->Mutex.Prev)
95 94 {
96 95 (ObjDesc->Mutex.Prev)->Mutex.Next = ObjDesc->Mutex.Next;
97 96
98 97 /*
99 98 * Migrate the previous sync level associated with this mutex to
100 99 * the previous mutex on the list so that it may be preserved.
101 100 * This handles the case where several mutexes have been acquired
102 101 * at the same level, but are not released in opposite order.
103 102 */
104 103 (ObjDesc->Mutex.Prev)->Mutex.OriginalSyncLevel =
105 104 ObjDesc->Mutex.OriginalSyncLevel;
106 105 }
107 106 else
108 107 {
109 108 Thread->AcquiredMutexList = ObjDesc->Mutex.Next;
110 109 }
111 110 }
112 111
113 112
114 113 /*******************************************************************************
115 114 *
116 115 * FUNCTION: AcpiExLinkMutex
117 116 *
118 117 * PARAMETERS: ObjDesc - The mutex to be linked
119 118 * Thread - Current executing thread object
120 119 *
121 120 * RETURN: None
122 121 *
123 122 * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk
124 123 *
125 124 ******************************************************************************/
126 125
127 126 static void
128 127 AcpiExLinkMutex (
129 128 ACPI_OPERAND_OBJECT *ObjDesc,
130 129 ACPI_THREAD_STATE *Thread)
131 130 {
132 131 ACPI_OPERAND_OBJECT *ListHead;
133 132
134 133
135 134 ListHead = Thread->AcquiredMutexList;
136 135
137 136 /* This object will be the first object in the list */
138 137
139 138 ObjDesc->Mutex.Prev = NULL;
140 139 ObjDesc->Mutex.Next = ListHead;
141 140
142 141 /* Update old first object to point back to this object */
143 142
144 143 if (ListHead)
145 144 {
146 145 ListHead->Mutex.Prev = ObjDesc;
147 146 }
148 147
149 148 /* Update list head */
150 149
151 150 Thread->AcquiredMutexList = ObjDesc;
152 151 }
153 152
154 153
155 154 /*******************************************************************************
156 155 *
157 156 * FUNCTION: AcpiExAcquireMutexObject
158 157 *
159 158 * PARAMETERS: Timeout - Timeout in milliseconds
160 159 * ObjDesc - Mutex object
161 160 * ThreadId - Current thread state
162 161 *
163 162 * RETURN: Status
164 163 *
165 164 * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common
166 165 * path that supports multiple acquires by the same thread.
167 166 *
168 167 * MUTEX: Interpreter must be locked
169 168 *
170 169 * NOTE: This interface is called from three places:
171 170 * 1) From AcpiExAcquireMutex, via an AML Acquire() operator
172 171 * 2) From AcpiExAcquireGlobalLock when an AML Field access requires the
173 172 * global lock
174 173 * 3) From the external interface, AcpiAcquireGlobalLock
175 174 *
176 175 ******************************************************************************/
177 176
178 177 ACPI_STATUS
179 178 AcpiExAcquireMutexObject (
180 179 UINT16 Timeout,
181 180 ACPI_OPERAND_OBJECT *ObjDesc,
182 181 ACPI_THREAD_ID ThreadId)
183 182 {
184 183 ACPI_STATUS Status;
185 184
186 185
187 186 ACPI_FUNCTION_TRACE_PTR (ExAcquireMutexObject, ObjDesc);
188 187
189 188
190 189 if (!ObjDesc)
191 190 {
192 191 return_ACPI_STATUS (AE_BAD_PARAMETER);
193 192 }
194 193
195 194 /* Support for multiple acquires by the owning thread */
196 195
197 196 if (ObjDesc->Mutex.ThreadId == ThreadId)
198 197 {
199 198 /*
200 199 * The mutex is already owned by this thread, just increment the
201 200 * acquisition depth
202 201 */
203 202 ObjDesc->Mutex.AcquisitionDepth++;
204 203 return_ACPI_STATUS (AE_OK);
205 204 }
206 205
207 206 /* Acquire the mutex, wait if necessary. Special case for Global Lock */
208 207
209 208 if (ObjDesc == AcpiGbl_GlobalLockMutex)
210 209 {
211 210 Status = AcpiEvAcquireGlobalLock (Timeout);
212 211 }
213 212 else
214 213 {
215 214 Status = AcpiExSystemWaitMutex (ObjDesc->Mutex.OsMutex,
216 215 Timeout);
217 216 }
218 217
219 218 if (ACPI_FAILURE (Status))
220 219 {
221 220 /* Includes failure from a timeout on TimeDesc */
222 221
223 222 return_ACPI_STATUS (Status);
224 223 }
225 224
226 225 /* Acquired the mutex: update mutex object */
227 226
228 227 ObjDesc->Mutex.ThreadId = ThreadId;
229 228 ObjDesc->Mutex.AcquisitionDepth = 1;
230 229 ObjDesc->Mutex.OriginalSyncLevel = 0;
231 230 ObjDesc->Mutex.OwnerThread = NULL; /* Used only for AML Acquire() */
232 231
233 232 return_ACPI_STATUS (AE_OK);
234 233 }
235 234
236 235
237 236 /*******************************************************************************
238 237 *
239 238 * FUNCTION: AcpiExAcquireMutex
240 239 *
241 240 * PARAMETERS: TimeDesc - Timeout integer
242 241 * ObjDesc - Mutex object
243 242 * WalkState - Current method execution state
244 243 *
245 244 * RETURN: Status
246 245 *
247 246 * DESCRIPTION: Acquire an AML mutex
248 247 *
249 248 ******************************************************************************/
250 249
251 250 ACPI_STATUS
252 251 AcpiExAcquireMutex (
253 252 ACPI_OPERAND_OBJECT *TimeDesc,
254 253 ACPI_OPERAND_OBJECT *ObjDesc,
255 254 ACPI_WALK_STATE *WalkState)
256 255 {
257 256 ACPI_STATUS Status;
258 257
259 258
260 259 ACPI_FUNCTION_TRACE_PTR (ExAcquireMutex, ObjDesc);
261 260
262 261
263 262 if (!ObjDesc)
264 263 {
265 264 return_ACPI_STATUS (AE_BAD_PARAMETER);
266 265 }
267 266
268 267 /* Must have a valid thread state struct */
269 268
270 269 if (!WalkState->Thread)
271 270 {
272 271 ACPI_ERROR ((AE_INFO,
273 272 "Cannot acquire Mutex [%4.4s], null thread info",
274 273 AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
275 274 return_ACPI_STATUS (AE_AML_INTERNAL);
276 275 }
277 276
278 277 /*
279 278 * Current sync level must be less than or equal to the sync level of the
280 279 * mutex. This mechanism provides some deadlock prevention
281 280 */
282 281 if (WalkState->Thread->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel)
283 282 {
284 283 ACPI_ERROR ((AE_INFO,
285 284 "Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%u)",
286 285 AcpiUtGetNodeName (ObjDesc->Mutex.Node),
287 286 WalkState->Thread->CurrentSyncLevel));
288 287 return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
289 288 }
290 289
291 290 Status = AcpiExAcquireMutexObject ((UINT16) TimeDesc->Integer.Value,
292 291 ObjDesc, WalkState->Thread->ThreadId);
293 292 if (ACPI_SUCCESS (Status) && ObjDesc->Mutex.AcquisitionDepth == 1)
294 293 {
295 294 /* Save Thread object, original/current sync levels */
296 295
297 296 ObjDesc->Mutex.OwnerThread = WalkState->Thread;
298 297 ObjDesc->Mutex.OriginalSyncLevel = WalkState->Thread->CurrentSyncLevel;
299 298 WalkState->Thread->CurrentSyncLevel = ObjDesc->Mutex.SyncLevel;
300 299
301 300 /* Link the mutex to the current thread for force-unlock at method exit */
302 301
303 302 AcpiExLinkMutex (ObjDesc, WalkState->Thread);
304 303 }
305 304
306 305 return_ACPI_STATUS (Status);
307 306 }
308 307
309 308
310 309 /*******************************************************************************
311 310 *
312 311 * FUNCTION: AcpiExReleaseMutexObject
313 312 *
314 313 * PARAMETERS: ObjDesc - The object descriptor for this op
315 314 *
316 315 * RETURN: Status
317 316 *
318 317 * DESCRIPTION: Release a previously acquired Mutex, low level interface.
319 318 * Provides a common path that supports multiple releases (after
320 319 * previous multiple acquires) by the same thread.
321 320 *
322 321 * MUTEX: Interpreter must be locked
323 322 *
324 323 * NOTE: This interface is called from three places:
325 324 * 1) From AcpiExReleaseMutex, via an AML Acquire() operator
326 325 * 2) From AcpiExReleaseGlobalLock when an AML Field access requires the
327 326 * global lock
328 327 * 3) From the external interface, AcpiReleaseGlobalLock
329 328 *
330 329 ******************************************************************************/
331 330
332 331 ACPI_STATUS
333 332 AcpiExReleaseMutexObject (
↓ open down ↓ |
314 lines elided |
↑ open up ↑ |
334 333 ACPI_OPERAND_OBJECT *ObjDesc)
335 334 {
336 335 ACPI_STATUS Status = AE_OK;
337 336
338 337
339 338 ACPI_FUNCTION_TRACE (ExReleaseMutexObject);
340 339
341 340
342 341 if (ObjDesc->Mutex.AcquisitionDepth == 0)
343 342 {
344 - return (AE_NOT_ACQUIRED);
343 + return_ACPI_STATUS (AE_NOT_ACQUIRED);
345 344 }
346 345
347 346 /* Match multiple Acquires with multiple Releases */
348 347
349 348 ObjDesc->Mutex.AcquisitionDepth--;
350 349 if (ObjDesc->Mutex.AcquisitionDepth != 0)
351 350 {
352 351 /* Just decrement the depth and return */
353 352
354 353 return_ACPI_STATUS (AE_OK);
355 354 }
356 355
357 356 if (ObjDesc->Mutex.OwnerThread)
358 357 {
359 358 /* Unlink the mutex from the owner's list */
360 359
361 360 AcpiExUnlinkMutex (ObjDesc);
362 361 ObjDesc->Mutex.OwnerThread = NULL;
363 362 }
364 363
365 364 /* Release the mutex, special case for Global Lock */
366 365
367 366 if (ObjDesc == AcpiGbl_GlobalLockMutex)
368 367 {
369 368 Status = AcpiEvReleaseGlobalLock ();
370 369 }
371 370 else
372 371 {
373 372 AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex);
374 373 }
375 374
376 375 /* Clear mutex info */
377 376
378 377 ObjDesc->Mutex.ThreadId = 0;
379 378 return_ACPI_STATUS (Status);
380 379 }
381 380
382 381
383 382 /*******************************************************************************
384 383 *
385 384 * FUNCTION: AcpiExReleaseMutex
386 385 *
387 386 * PARAMETERS: ObjDesc - The object descriptor for this op
388 387 * WalkState - Current method execution state
389 388 *
390 389 * RETURN: Status
391 390 *
392 391 * DESCRIPTION: Release a previously acquired Mutex.
393 392 *
394 393 ******************************************************************************/
395 394
396 395 ACPI_STATUS
397 396 AcpiExReleaseMutex (
398 397 ACPI_OPERAND_OBJECT *ObjDesc,
399 398 ACPI_WALK_STATE *WalkState)
400 399 {
401 400 ACPI_STATUS Status = AE_OK;
402 401 UINT8 PreviousSyncLevel;
403 402 ACPI_THREAD_STATE *OwnerThread;
404 403
405 404
406 405 ACPI_FUNCTION_TRACE (ExReleaseMutex);
407 406
408 407
409 408 if (!ObjDesc)
410 409 {
411 410 return_ACPI_STATUS (AE_BAD_PARAMETER);
412 411 }
413 412
414 413 OwnerThread = ObjDesc->Mutex.OwnerThread;
415 414
416 415 /* The mutex must have been previously acquired in order to release it */
417 416
418 417 if (!OwnerThread)
419 418 {
420 419 ACPI_ERROR ((AE_INFO,
421 420 "Cannot release Mutex [%4.4s], not acquired",
422 421 AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
423 422 return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED);
424 423 }
425 424
426 425 /* Must have a valid thread ID */
427 426
428 427 if (!WalkState->Thread)
429 428 {
430 429 ACPI_ERROR ((AE_INFO,
431 430 "Cannot release Mutex [%4.4s], null thread info",
432 431 AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
433 432 return_ACPI_STATUS (AE_AML_INTERNAL);
434 433 }
435 434
436 435 /*
437 436 * The Mutex is owned, but this thread must be the owner.
438 437 * Special case for Global Lock, any thread can release
439 438 */
440 439 if ((OwnerThread->ThreadId != WalkState->Thread->ThreadId) &&
441 440 (ObjDesc != AcpiGbl_GlobalLockMutex))
442 441 {
443 442 ACPI_ERROR ((AE_INFO,
444 443 "Thread %u cannot release Mutex [%4.4s] acquired by thread %u",
445 444 (UINT32) WalkState->Thread->ThreadId,
446 445 AcpiUtGetNodeName (ObjDesc->Mutex.Node),
447 446 (UINT32) OwnerThread->ThreadId));
448 447 return_ACPI_STATUS (AE_AML_NOT_OWNER);
449 448 }
450 449
451 450 /*
452 451 * The sync level of the mutex must be equal to the current sync level. In
453 452 * other words, the current level means that at least one mutex at that
454 453 * level is currently being held. Attempting to release a mutex of a
455 454 * different level can only mean that the mutex ordering rule is being
456 455 * violated. This behavior is clarified in ACPI 4.0 specification.
457 456 */
458 457 if (ObjDesc->Mutex.SyncLevel != OwnerThread->CurrentSyncLevel)
459 458 {
460 459 ACPI_ERROR ((AE_INFO,
461 460 "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u",
462 461 AcpiUtGetNodeName (ObjDesc->Mutex.Node),
463 462 ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel));
464 463 return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
465 464 }
466 465
467 466 /*
468 467 * Get the previous SyncLevel from the head of the acquired mutex list.
469 468 * This handles the case where several mutexes at the same level have been
470 469 * acquired, but are not released in reverse order.
471 470 */
472 471 PreviousSyncLevel =
473 472 OwnerThread->AcquiredMutexList->Mutex.OriginalSyncLevel;
474 473
475 474 Status = AcpiExReleaseMutexObject (ObjDesc);
476 475 if (ACPI_FAILURE (Status))
477 476 {
478 477 return_ACPI_STATUS (Status);
479 478 }
480 479
481 480 if (ObjDesc->Mutex.AcquisitionDepth == 0)
482 481 {
483 482 /* Restore the previous SyncLevel */
484 483
485 484 OwnerThread->CurrentSyncLevel = PreviousSyncLevel;
486 485 }
487 486
488 487 return_ACPI_STATUS (Status);
489 488 }
490 489
491 490
492 491 /*******************************************************************************
493 492 *
494 493 * FUNCTION: AcpiExReleaseAllMutexes
495 494 *
496 495 * PARAMETERS: Thread - Current executing thread object
497 496 *
498 497 * RETURN: Status
499 498 *
500 499 * DESCRIPTION: Release all mutexes held by this thread
501 500 *
502 501 * NOTE: This function is called as the thread is exiting the interpreter.
503 502 * Mutexes are not released when an individual control method is exited, but
504 503 * only when the parent thread actually exits the interpreter. This allows one
505 504 * method to acquire a mutex, and a different method to release it, as long as
506 505 * this is performed underneath a single parent control method.
507 506 *
↓ open down ↓ |
153 lines elided |
↑ open up ↑ |
508 507 ******************************************************************************/
509 508
510 509 void
511 510 AcpiExReleaseAllMutexes (
512 511 ACPI_THREAD_STATE *Thread)
513 512 {
514 513 ACPI_OPERAND_OBJECT *Next = Thread->AcquiredMutexList;
515 514 ACPI_OPERAND_OBJECT *ObjDesc;
516 515
517 516
518 - ACPI_FUNCTION_ENTRY ();
517 + ACPI_FUNCTION_NAME (ExReleaseAllMutexes);
519 518
520 519
521 520 /* Traverse the list of owned mutexes, releasing each one */
522 521
523 522 while (Next)
524 523 {
525 524 ObjDesc = Next;
526 525 Next = ObjDesc->Mutex.Next;
527 526
528 527 ObjDesc->Mutex.Prev = NULL;
529 528 ObjDesc->Mutex.Next = NULL;
530 529 ObjDesc->Mutex.AcquisitionDepth = 0;
531 530
531 + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
532 + "Force-releasing held mutex: %p\n", ObjDesc));
533 +
532 534 /* Release the mutex, special case for Global Lock */
533 535
534 536 if (ObjDesc == AcpiGbl_GlobalLockMutex)
535 537 {
536 538 /* Ignore errors */
537 539
538 540 (void) AcpiEvReleaseGlobalLock ();
539 541 }
540 542 else
541 543 {
542 544 AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex);
543 545 }
544 546
545 547 /* Mark mutex unowned */
546 548
547 549 ObjDesc->Mutex.OwnerThread = NULL;
548 550 ObjDesc->Mutex.ThreadId = 0;
549 551
550 552 /* Update Thread SyncLevel (Last mutex is the important one) */
551 553
552 554 Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel;
553 555 }
554 556 }
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX