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
162static void
163AcpiExLinkMutex (
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
180void
181AcpiExUnlinkMutex (
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
232static void
233AcpiExLinkMutex (
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
283ACPI_STATUS
284AcpiExAcquireMutexObject (
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
355ACPI_STATUS
356AcpiExAcquireMutex (
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
451ACPI_STATUS
452AcpiExReleaseMutexObject (
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
515ACPI_STATUS
516AcpiExReleaseMutex (
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
643void
644AcpiExReleaseAllMutexes (
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