1 /******************************************************************************
2 *
3 * Module Name: exmutex - ASL Mutex Acquire/Release functions
4 *
5 *****************************************************************************/
6
7 /******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2023, Intel Corp.
12 * All rights reserved.
13 *
14 * 2. License
15 *
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
20 *
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
27 *
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code. No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
36 *
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
39 *
40 * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision. In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change. Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee. Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution. In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government. In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************
115 *
116 * Alternatively, you may choose to be licensed under the terms of the
117 * following license:
118 *
119 * Redistribution and use in source and binary forms, with or without
120 * modification, are permitted provided that the following conditions
121 * are met:
122 * 1. Redistributions of source code must retain the above copyright
123 * notice, this list of conditions, and the following disclaimer,
124 * without modification.
125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126 * substantially similar to the "NO WARRANTY" disclaimer below
127 * ("Disclaimer") and any redistribution must be conditioned upon
128 * including a substantially similar Disclaimer requirement for further
129 * binary redistribution.
130 * 3. Neither the names of the above-listed copyright holders nor the names
131 * of any contributors may be used to endorse or promote products derived
132 * from this software without specific prior written permission.
133 *
134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145 *
146 * Alternatively, you may choose to be licensed under the terms of the
147 * GNU General Public License ("GPL") version 2 as published by the Free
148 * Software Foundation.
149 *
150 *****************************************************************************/
151
152 #include "acpi.h"
153 #include "accommon.h"
154 #include "acinterp.h"
155 #include "acevents.h"
156
157 #define _COMPONENT ACPI_EXECUTER
158 ACPI_MODULE_NAME ("exmutex")
159
160 /* Local prototypes */
161
162 static void
163 AcpiExLinkMutex (
164 ACPI_OPERAND_OBJECT *ObjDesc,
165 ACPI_THREAD_STATE *Thread);
166
167
168 /*******************************************************************************
169 *
170 * FUNCTION: AcpiExUnlinkMutex
171 *
172 * PARAMETERS: ObjDesc - The mutex to be unlinked
173 *
174 * RETURN: None
175 *
176 * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list
177 *
178 ******************************************************************************/
179
180 void
AcpiExUnlinkMutex(ACPI_OPERAND_OBJECT * ObjDesc)181 AcpiExUnlinkMutex (
182 ACPI_OPERAND_OBJECT *ObjDesc)
183 {
184 ACPI_THREAD_STATE *Thread = ObjDesc->Mutex.OwnerThread;
185
186
187 if (!Thread)
188 {
189 return;
190 }
191
192 /* Doubly linked list */
193
194 if (ObjDesc->Mutex.Next)
195 {
196 (ObjDesc->Mutex.Next)->Mutex.Prev = ObjDesc->Mutex.Prev;
197 }
198
199 if (ObjDesc->Mutex.Prev)
200 {
201 (ObjDesc->Mutex.Prev)->Mutex.Next = ObjDesc->Mutex.Next;
202
203 /*
204 * Migrate the previous sync level associated with this mutex to
205 * the previous mutex on the list so that it may be preserved.
206 * This handles the case where several mutexes have been acquired
207 * at the same level, but are not released in opposite order.
208 */
209 (ObjDesc->Mutex.Prev)->Mutex.OriginalSyncLevel =
210 ObjDesc->Mutex.OriginalSyncLevel;
211 }
212 else
213 {
214 Thread->AcquiredMutexList = ObjDesc->Mutex.Next;
215 }
216 }
217
218
219 /*******************************************************************************
220 *
221 * FUNCTION: AcpiExLinkMutex
222 *
223 * PARAMETERS: ObjDesc - The mutex to be linked
224 * Thread - Current executing thread object
225 *
226 * RETURN: None
227 *
228 * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk
229 *
230 ******************************************************************************/
231
232 static void
AcpiExLinkMutex(ACPI_OPERAND_OBJECT * ObjDesc,ACPI_THREAD_STATE * Thread)233 AcpiExLinkMutex (
234 ACPI_OPERAND_OBJECT *ObjDesc,
235 ACPI_THREAD_STATE *Thread)
236 {
237 ACPI_OPERAND_OBJECT *ListHead;
238
239
240 ListHead = Thread->AcquiredMutexList;
241
242 /* This object will be the first object in the list */
243
244 ObjDesc->Mutex.Prev = NULL;
245 ObjDesc->Mutex.Next = ListHead;
246
247 /* Update old first object to point back to this object */
248
249 if (ListHead)
250 {
251 ListHead->Mutex.Prev = ObjDesc;
252 }
253
254 /* Update list head */
255
256 Thread->AcquiredMutexList = ObjDesc;
257 }
258
259
260 /*******************************************************************************
261 *
262 * FUNCTION: AcpiExAcquireMutexObject
263 *
264 * PARAMETERS: Timeout - Timeout in milliseconds
265 * ObjDesc - Mutex object
266 * ThreadId - Current thread state
267 *
268 * RETURN: Status
269 *
270 * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common
271 * path that supports multiple acquires by the same thread.
272 *
273 * MUTEX: Interpreter must be locked
274 *
275 * NOTE: This interface is called from three places:
276 * 1) From AcpiExAcquireMutex, via an AML Acquire() operator
277 * 2) From AcpiExAcquireGlobalLock when an AML Field access requires the
278 * global lock
279 * 3) From the external interface, AcpiAcquireGlobalLock
280 *
281 ******************************************************************************/
282
283 ACPI_STATUS
AcpiExAcquireMutexObject(UINT16 Timeout,ACPI_OPERAND_OBJECT * ObjDesc,ACPI_THREAD_ID ThreadId)284 AcpiExAcquireMutexObject (
285 UINT16 Timeout,
286 ACPI_OPERAND_OBJECT *ObjDesc,
287 ACPI_THREAD_ID ThreadId)
288 {
289 ACPI_STATUS Status;
290
291
292 ACPI_FUNCTION_TRACE_PTR (ExAcquireMutexObject, ObjDesc);
293
294
295 if (!ObjDesc)
296 {
297 return_ACPI_STATUS (AE_BAD_PARAMETER);
298 }
299
300 /* Support for multiple acquires by the owning thread */
301
302 if (ObjDesc->Mutex.ThreadId == ThreadId)
303 {
304 /*
305 * The mutex is already owned by this thread, just increment the
306 * acquisition depth
307 */
308 ObjDesc->Mutex.AcquisitionDepth++;
309 return_ACPI_STATUS (AE_OK);
310 }
311
312 /* Acquire the mutex, wait if necessary. Special case for Global Lock */
313
314 if (ObjDesc == AcpiGbl_GlobalLockMutex)
315 {
316 Status = AcpiEvAcquireGlobalLock (Timeout);
317 }
318 else
319 {
320 Status = AcpiExSystemWaitMutex (ObjDesc->Mutex.OsMutex, Timeout);
321 }
322
323 if (ACPI_FAILURE (Status))
324 {
325 /* Includes failure from a timeout on TimeDesc */
326
327 return_ACPI_STATUS (Status);
328 }
329
330 /* Acquired the mutex: update mutex object */
331
332 ObjDesc->Mutex.ThreadId = ThreadId;
333 ObjDesc->Mutex.AcquisitionDepth = 1;
334 ObjDesc->Mutex.OriginalSyncLevel = 0;
335 ObjDesc->Mutex.OwnerThread = NULL; /* Used only for AML Acquire() */
336
337 return_ACPI_STATUS (AE_OK);
338 }
339
340
341 /*******************************************************************************
342 *
343 * FUNCTION: AcpiExAcquireMutex
344 *
345 * PARAMETERS: TimeDesc - Timeout integer
346 * ObjDesc - Mutex object
347 * WalkState - Current method execution state
348 *
349 * RETURN: Status
350 *
351 * DESCRIPTION: Acquire an AML mutex
352 *
353 ******************************************************************************/
354
355 ACPI_STATUS
AcpiExAcquireMutex(ACPI_OPERAND_OBJECT * TimeDesc,ACPI_OPERAND_OBJECT * ObjDesc,ACPI_WALK_STATE * WalkState)356 AcpiExAcquireMutex (
357 ACPI_OPERAND_OBJECT *TimeDesc,
358 ACPI_OPERAND_OBJECT *ObjDesc,
359 ACPI_WALK_STATE *WalkState)
360 {
361 ACPI_STATUS Status;
362
363
364 ACPI_FUNCTION_TRACE_PTR (ExAcquireMutex, ObjDesc);
365
366
367 if (!ObjDesc)
368 {
369 return_ACPI_STATUS (AE_BAD_PARAMETER);
370 }
371
372 /* Must have a valid thread state struct */
373
374 if (!WalkState->Thread)
375 {
376 ACPI_ERROR ((AE_INFO,
377 "Cannot acquire Mutex [%4.4s], null thread info",
378 AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
379 return_ACPI_STATUS (AE_AML_INTERNAL);
380 }
381
382 /*
383 * Current sync level must be less than or equal to the sync level
384 * of the mutex. This mechanism provides some deadlock prevention.
385 */
386 if (WalkState->Thread->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel)
387 {
388 ACPI_ERROR ((AE_INFO,
389 "Cannot acquire Mutex [%4.4s], "
390 "current SyncLevel is too large (%u)",
391 AcpiUtGetNodeName (ObjDesc->Mutex.Node),
392 WalkState->Thread->CurrentSyncLevel));
393 return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
394 }
395
396 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
397 "Acquiring: Mutex SyncLevel %u, Thread SyncLevel %u, "
398 "Depth %u TID %p\n",
399 ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel,
400 ObjDesc->Mutex.AcquisitionDepth, WalkState->Thread));
401
402 Status = AcpiExAcquireMutexObject ((UINT16) TimeDesc->Integer.Value,
403 ObjDesc, WalkState->Thread->ThreadId);
404
405 if (ACPI_SUCCESS (Status) && ObjDesc->Mutex.AcquisitionDepth == 1)
406 {
407 /* Save Thread object, original/current sync levels */
408
409 ObjDesc->Mutex.OwnerThread = WalkState->Thread;
410 ObjDesc->Mutex.OriginalSyncLevel =
411 WalkState->Thread->CurrentSyncLevel;
412 WalkState->Thread->CurrentSyncLevel =
413 ObjDesc->Mutex.SyncLevel;
414
415 /* Link the mutex to the current thread for force-unlock at method exit */
416
417 AcpiExLinkMutex (ObjDesc, WalkState->Thread);
418 }
419
420 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
421 "Acquired: Mutex SyncLevel %u, Thread SyncLevel %u, Depth %u\n",
422 ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel,
423 ObjDesc->Mutex.AcquisitionDepth));
424
425 return_ACPI_STATUS (Status);
426 }
427
428
429 /*******************************************************************************
430 *
431 * FUNCTION: AcpiExReleaseMutexObject
432 *
433 * PARAMETERS: ObjDesc - The object descriptor for this op
434 *
435 * RETURN: Status
436 *
437 * DESCRIPTION: Release a previously acquired Mutex, low level interface.
438 * Provides a common path that supports multiple releases (after
439 * previous multiple acquires) by the same thread.
440 *
441 * MUTEX: Interpreter must be locked
442 *
443 * NOTE: This interface is called from three places:
444 * 1) From AcpiExReleaseMutex, via an AML Acquire() operator
445 * 2) From AcpiExReleaseGlobalLock when an AML Field access requires the
446 * global lock
447 * 3) From the external interface, AcpiReleaseGlobalLock
448 *
449 ******************************************************************************/
450
451 ACPI_STATUS
AcpiExReleaseMutexObject(ACPI_OPERAND_OBJECT * ObjDesc)452 AcpiExReleaseMutexObject (
453 ACPI_OPERAND_OBJECT *ObjDesc)
454 {
455 ACPI_STATUS Status = AE_OK;
456
457
458 ACPI_FUNCTION_TRACE (ExReleaseMutexObject);
459
460
461 if (ObjDesc->Mutex.AcquisitionDepth == 0)
462 {
463 return_ACPI_STATUS (AE_NOT_ACQUIRED);
464 }
465
466 /* Match multiple Acquires with multiple Releases */
467
468 ObjDesc->Mutex.AcquisitionDepth--;
469 if (ObjDesc->Mutex.AcquisitionDepth != 0)
470 {
471 /* Just decrement the depth and return */
472
473 return_ACPI_STATUS (AE_OK);
474 }
475
476 if (ObjDesc->Mutex.OwnerThread)
477 {
478 /* Unlink the mutex from the owner's list */
479
480 AcpiExUnlinkMutex (ObjDesc);
481 ObjDesc->Mutex.OwnerThread = NULL;
482 }
483
484 /* Release the mutex, special case for Global Lock */
485
486 if (ObjDesc == AcpiGbl_GlobalLockMutex)
487 {
488 Status = AcpiEvReleaseGlobalLock ();
489 }
490 else
491 {
492 AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex);
493 }
494
495 /* Clear mutex info */
496
497 ObjDesc->Mutex.ThreadId = 0;
498 return_ACPI_STATUS (Status);
499 }
500
501
502 /*******************************************************************************
503 *
504 * FUNCTION: AcpiExReleaseMutex
505 *
506 * PARAMETERS: ObjDesc - The object descriptor for this op
507 * WalkState - Current method execution state
508 *
509 * RETURN: Status
510 *
511 * DESCRIPTION: Release a previously acquired Mutex.
512 *
513 ******************************************************************************/
514
515 ACPI_STATUS
AcpiExReleaseMutex(ACPI_OPERAND_OBJECT * ObjDesc,ACPI_WALK_STATE * WalkState)516 AcpiExReleaseMutex (
517 ACPI_OPERAND_OBJECT *ObjDesc,
518 ACPI_WALK_STATE *WalkState)
519 {
520 UINT8 PreviousSyncLevel;
521 ACPI_THREAD_STATE *OwnerThread;
522 ACPI_STATUS Status = AE_OK;
523
524
525 ACPI_FUNCTION_TRACE (ExReleaseMutex);
526
527
528 if (!ObjDesc)
529 {
530 return_ACPI_STATUS (AE_BAD_PARAMETER);
531 }
532
533 OwnerThread = ObjDesc->Mutex.OwnerThread;
534
535 /* The mutex must have been previously acquired in order to release it */
536
537 if (!OwnerThread)
538 {
539 ACPI_ERROR ((AE_INFO,
540 "Cannot release Mutex [%4.4s], not acquired",
541 AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
542 return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED);
543 }
544
545 /* Must have a valid thread ID */
546
547 if (!WalkState->Thread)
548 {
549 ACPI_ERROR ((AE_INFO,
550 "Cannot release Mutex [%4.4s], null thread info",
551 AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
552 return_ACPI_STATUS (AE_AML_INTERNAL);
553 }
554
555 /*
556 * The Mutex is owned, but this thread must be the owner.
557 * Special case for Global Lock, any thread can release
558 */
559 if ((OwnerThread->ThreadId != WalkState->Thread->ThreadId) &&
560 (ObjDesc != AcpiGbl_GlobalLockMutex))
561 {
562 ACPI_ERROR ((AE_INFO,
563 "Thread %u cannot release Mutex [%4.4s] acquired by thread %u",
564 (UINT32) WalkState->Thread->ThreadId,
565 AcpiUtGetNodeName (ObjDesc->Mutex.Node),
566 (UINT32) OwnerThread->ThreadId));
567 return_ACPI_STATUS (AE_AML_NOT_OWNER);
568 }
569
570 /*
571 * The sync level of the mutex must be equal to the current sync level. In
572 * other words, the current level means that at least one mutex at that
573 * level is currently being held. Attempting to release a mutex of a
574 * different level can only mean that the mutex ordering rule is being
575 * violated. This behavior is clarified in ACPI 4.0 specification.
576 */
577 if (ObjDesc->Mutex.SyncLevel != OwnerThread->CurrentSyncLevel)
578 {
579 ACPI_ERROR ((AE_INFO,
580 "Cannot release Mutex [%4.4s], SyncLevel mismatch: "
581 "mutex %u current %u",
582 AcpiUtGetNodeName (ObjDesc->Mutex.Node),
583 ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel));
584 return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
585 }
586
587 /*
588 * Get the previous SyncLevel from the head of the acquired mutex list.
589 * This handles the case where several mutexes at the same level have been
590 * acquired, but are not released in reverse order.
591 */
592 PreviousSyncLevel =
593 OwnerThread->AcquiredMutexList->Mutex.OriginalSyncLevel;
594
595 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
596 "Releasing: Object SyncLevel %u, Thread SyncLevel %u, "
597 "Prev SyncLevel %u, Depth %u TID %p\n",
598 ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel,
599 PreviousSyncLevel, ObjDesc->Mutex.AcquisitionDepth,
600 WalkState->Thread));
601
602 Status = AcpiExReleaseMutexObject (ObjDesc);
603 if (ACPI_FAILURE (Status))
604 {
605 return_ACPI_STATUS (Status);
606 }
607
608 if (ObjDesc->Mutex.AcquisitionDepth == 0)
609 {
610 /* Restore the previous SyncLevel */
611
612 OwnerThread->CurrentSyncLevel = PreviousSyncLevel;
613 }
614
615 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
616 "Released: Object SyncLevel %u, Thread SyncLevel, %u, "
617 "Prev SyncLevel %u, Depth %u\n",
618 ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel,
619 PreviousSyncLevel, ObjDesc->Mutex.AcquisitionDepth));
620
621 return_ACPI_STATUS (Status);
622 }
623
624
625 /*******************************************************************************
626 *
627 * FUNCTION: AcpiExReleaseAllMutexes
628 *
629 * PARAMETERS: Thread - Current executing thread object
630 *
631 * RETURN: Status
632 *
633 * DESCRIPTION: Release all mutexes held by this thread
634 *
635 * NOTE: This function is called as the thread is exiting the interpreter.
636 * Mutexes are not released when an individual control method is exited, but
637 * only when the parent thread actually exits the interpreter. This allows one
638 * method to acquire a mutex, and a different method to release it, as long as
639 * this is performed underneath a single parent control method.
640 *
641 ******************************************************************************/
642
643 void
AcpiExReleaseAllMutexes(ACPI_THREAD_STATE * Thread)644 AcpiExReleaseAllMutexes (
645 ACPI_THREAD_STATE *Thread)
646 {
647 ACPI_OPERAND_OBJECT *Next = Thread->AcquiredMutexList;
648 ACPI_OPERAND_OBJECT *ObjDesc;
649
650
651 ACPI_FUNCTION_TRACE (ExReleaseAllMutexes);
652
653
654 /* Traverse the list of owned mutexes, releasing each one */
655
656 while (Next)
657 {
658 ObjDesc = Next;
659 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
660 "Mutex [%4.4s] force-release, SyncLevel %u Depth %u\n",
661 ObjDesc->Mutex.Node->Name.Ascii, ObjDesc->Mutex.SyncLevel,
662 ObjDesc->Mutex.AcquisitionDepth));
663
664 /* Release the mutex, special case for Global Lock */
665
666 if (ObjDesc == AcpiGbl_GlobalLockMutex)
667 {
668 /* Ignore errors */
669
670 (void) AcpiEvReleaseGlobalLock ();
671 }
672 else
673 {
674 AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex);
675 }
676
677 /* Update Thread SyncLevel (Last mutex is the important one) */
678
679 Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel;
680
681 /* Mark mutex unowned */
682
683 Next = ObjDesc->Mutex.Next;
684
685 ObjDesc->Mutex.Prev = NULL;
686 ObjDesc->Mutex.Next = NULL;
687 ObjDesc->Mutex.AcquisitionDepth = 0;
688 ObjDesc->Mutex.OwnerThread = NULL;
689 ObjDesc->Mutex.ThreadId = 0;
690 }
691
692 return_VOID;
693 }
694