177422Smsmith/****************************************************************************** 277422Smsmith * 377422Smsmith * Module Name: exmutex - ASL Mutex Acquire/Release functions 477422Smsmith * 577422Smsmith *****************************************************************************/ 677422Smsmith 7316303Sjkim/****************************************************************************** 8316303Sjkim * 9316303Sjkim * 1. Copyright Notice 10316303Sjkim * 11316303Sjkim * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp. 1277422Smsmith * All rights reserved. 1377422Smsmith * 14316303Sjkim * 2. License 15316303Sjkim * 16316303Sjkim * 2.1. This is your license from Intel Corp. under its intellectual property 17316303Sjkim * rights. You may have additional license terms from the party that provided 18316303Sjkim * you this software, covering your right to use that party's intellectual 19316303Sjkim * property rights. 20316303Sjkim * 21316303Sjkim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22316303Sjkim * copy of the source code appearing in this file ("Covered Code") an 23316303Sjkim * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24316303Sjkim * base code distributed originally by Intel ("Original Intel Code") to copy, 25316303Sjkim * make derivatives, distribute, use and display any portion of the Covered 26316303Sjkim * Code in any form, with the right to sublicense such rights; and 27316303Sjkim * 28316303Sjkim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29316303Sjkim * license (with the right to sublicense), under only those claims of Intel 30316303Sjkim * patents that are infringed by the Original Intel Code, to make, use, sell, 31316303Sjkim * offer to sell, and import the Covered Code and derivative works thereof 32316303Sjkim * solely to the minimum extent necessary to exercise the above copyright 33316303Sjkim * license, and in no event shall the patent license extend to any additions 34316303Sjkim * to or modifications of the Original Intel Code. No other license or right 35316303Sjkim * is granted directly or by implication, estoppel or otherwise; 36316303Sjkim * 37316303Sjkim * The above copyright and patent license is granted only if the following 38316303Sjkim * conditions are met: 39316303Sjkim * 40316303Sjkim * 3. Conditions 41316303Sjkim * 42316303Sjkim * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43316303Sjkim * Redistribution of source code of any substantial portion of the Covered 44316303Sjkim * Code or modification with rights to further distribute source must include 45316303Sjkim * the above Copyright Notice, the above License, this list of Conditions, 46316303Sjkim * and the following Disclaimer and Export Compliance provision. In addition, 47316303Sjkim * Licensee must cause all Covered Code to which Licensee contributes to 48316303Sjkim * contain a file documenting the changes Licensee made to create that Covered 49316303Sjkim * Code and the date of any change. Licensee must include in that file the 50316303Sjkim * documentation of any changes made by any predecessor Licensee. Licensee 51316303Sjkim * must include a prominent statement that the modification is derived, 52316303Sjkim * directly or indirectly, from Original Intel Code. 53316303Sjkim * 54316303Sjkim * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55316303Sjkim * Redistribution of source code of any substantial portion of the Covered 56316303Sjkim * Code or modification without rights to further distribute source must 57316303Sjkim * include the following Disclaimer and Export Compliance provision in the 58316303Sjkim * documentation and/or other materials provided with distribution. In 59316303Sjkim * addition, Licensee may not authorize further sublicense of source of any 60316303Sjkim * portion of the Covered Code, and must include terms to the effect that the 61316303Sjkim * license from Licensee to its licensee is limited to the intellectual 62316303Sjkim * property embodied in the software Licensee provides to its licensee, and 63316303Sjkim * not to intellectual property embodied in modifications its licensee may 64316303Sjkim * make. 65316303Sjkim * 66316303Sjkim * 3.3. Redistribution of Executable. Redistribution in executable form of any 67316303Sjkim * substantial portion of the Covered Code or modification must reproduce the 68316303Sjkim * above Copyright Notice, and the following Disclaimer and Export Compliance 69316303Sjkim * provision in the documentation and/or other materials provided with the 70316303Sjkim * distribution. 71316303Sjkim * 72316303Sjkim * 3.4. Intel retains all right, title, and interest in and to the Original 73316303Sjkim * Intel Code. 74316303Sjkim * 75316303Sjkim * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76316303Sjkim * Intel shall be used in advertising or otherwise to promote the sale, use or 77316303Sjkim * other dealings in products derived from or relating to the Covered Code 78316303Sjkim * without prior written authorization from Intel. 79316303Sjkim * 80316303Sjkim * 4. Disclaimer and Export Compliance 81316303Sjkim * 82316303Sjkim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83316303Sjkim * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84316303Sjkim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85316303Sjkim * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86316303Sjkim * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87316303Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88316303Sjkim * PARTICULAR PURPOSE. 89316303Sjkim * 90316303Sjkim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91316303Sjkim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92316303Sjkim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93316303Sjkim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94316303Sjkim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95316303Sjkim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96316303Sjkim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97316303Sjkim * LIMITED REMEDY. 98316303Sjkim * 99316303Sjkim * 4.3. Licensee shall not export, either directly or indirectly, any of this 100316303Sjkim * software or system incorporating such software without first obtaining any 101316303Sjkim * required license or other approval from the U. S. Department of Commerce or 102316303Sjkim * any other agency or department of the United States Government. In the 103316303Sjkim * event Licensee exports any such software from the United States or 104316303Sjkim * re-exports any such software from a foreign destination, Licensee shall 105316303Sjkim * ensure that the distribution and export/re-export of the software is in 106316303Sjkim * compliance with all laws, regulations, orders, or other restrictions of the 107316303Sjkim * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108316303Sjkim * any of its subsidiaries will export/re-export any technical data, process, 109316303Sjkim * software, or service, directly or indirectly, to any country for which the 110316303Sjkim * United States government or any agency thereof requires an export license, 111316303Sjkim * other governmental approval, or letter of assurance, without first obtaining 112316303Sjkim * such license, approval or letter. 113316303Sjkim * 114316303Sjkim ***************************************************************************** 115316303Sjkim * 116316303Sjkim * Alternatively, you may choose to be licensed under the terms of the 117316303Sjkim * following license: 118316303Sjkim * 119217365Sjkim * Redistribution and use in source and binary forms, with or without 120217365Sjkim * modification, are permitted provided that the following conditions 121217365Sjkim * are met: 122217365Sjkim * 1. Redistributions of source code must retain the above copyright 123217365Sjkim * notice, this list of conditions, and the following disclaimer, 124217365Sjkim * without modification. 125217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 127217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 128217365Sjkim * including a substantially similar Disclaimer requirement for further 129217365Sjkim * binary redistribution. 130217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 131217365Sjkim * of any contributors may be used to endorse or promote products derived 132217365Sjkim * from this software without specific prior written permission. 13377422Smsmith * 134316303Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135316303Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136316303Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137316303Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138316303Sjkim * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139316303Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140316303Sjkim * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141316303Sjkim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142316303Sjkim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143316303Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144316303Sjkim * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145316303Sjkim * 146316303Sjkim * Alternatively, you may choose to be licensed under the terms of the 147217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 148217365Sjkim * Software Foundation. 14977422Smsmith * 150316303Sjkim *****************************************************************************/ 15177422Smsmith 152193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 153193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 154193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 155193341Sjkim#include <contrib/dev/acpica/include/acevents.h> 15677422Smsmith 15777422Smsmith#define _COMPONENT ACPI_EXECUTER 15891116Smsmith ACPI_MODULE_NAME ("exmutex") 15977422Smsmith 160151937Sjkim/* Local prototypes */ 16177422Smsmith 162151937Sjkimstatic void 163151937SjkimAcpiExLinkMutex ( 164151937Sjkim ACPI_OPERAND_OBJECT *ObjDesc, 165151937Sjkim ACPI_THREAD_STATE *Thread); 166151937Sjkim 167151937Sjkim 16877422Smsmith/******************************************************************************* 16977422Smsmith * 17077422Smsmith * FUNCTION: AcpiExUnlinkMutex 17177422Smsmith * 172129684Snjl * PARAMETERS: ObjDesc - The mutex to be unlinked 17377422Smsmith * 174151937Sjkim * RETURN: None 17577422Smsmith * 17677422Smsmith * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list 17777422Smsmith * 17877422Smsmith ******************************************************************************/ 17977422Smsmith 18077422Smsmithvoid 18177422SmsmithAcpiExUnlinkMutex ( 18277422Smsmith ACPI_OPERAND_OBJECT *ObjDesc) 18377422Smsmith{ 18487031Smsmith ACPI_THREAD_STATE *Thread = ObjDesc->Mutex.OwnerThread; 18577422Smsmith 18687031Smsmith 18787031Smsmith if (!Thread) 18887031Smsmith { 18987031Smsmith return; 19087031Smsmith } 19187031Smsmith 192129684Snjl /* Doubly linked list */ 193129684Snjl 19477422Smsmith if (ObjDesc->Mutex.Next) 19577422Smsmith { 19677422Smsmith (ObjDesc->Mutex.Next)->Mutex.Prev = ObjDesc->Mutex.Prev; 19777422Smsmith } 19887031Smsmith 19977422Smsmith if (ObjDesc->Mutex.Prev) 20077422Smsmith { 20177422Smsmith (ObjDesc->Mutex.Prev)->Mutex.Next = ObjDesc->Mutex.Next; 202193267Sjkim 203193267Sjkim /* 204206117Sjkim * Migrate the previous sync level associated with this mutex to 205206117Sjkim * the previous mutex on the list so that it may be preserved. 206206117Sjkim * This handles the case where several mutexes have been acquired 207206117Sjkim * at the same level, but are not released in opposite order. 208193267Sjkim */ 209193267Sjkim (ObjDesc->Mutex.Prev)->Mutex.OriginalSyncLevel = 210193267Sjkim ObjDesc->Mutex.OriginalSyncLevel; 21177422Smsmith } 21287031Smsmith else 21387031Smsmith { 21487031Smsmith Thread->AcquiredMutexList = ObjDesc->Mutex.Next; 21587031Smsmith } 21677422Smsmith} 21777422Smsmith 21877422Smsmith 21977422Smsmith/******************************************************************************* 22077422Smsmith * 22177422Smsmith * FUNCTION: AcpiExLinkMutex 22277422Smsmith * 223206117Sjkim * PARAMETERS: ObjDesc - The mutex to be linked 224206117Sjkim * Thread - Current executing thread object 22577422Smsmith * 226151937Sjkim * RETURN: None 22777422Smsmith * 22877422Smsmith * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk 22977422Smsmith * 23077422Smsmith ******************************************************************************/ 23177422Smsmith 232151937Sjkimstatic void 23377422SmsmithAcpiExLinkMutex ( 23477422Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 23587031Smsmith ACPI_THREAD_STATE *Thread) 23677422Smsmith{ 23787031Smsmith ACPI_OPERAND_OBJECT *ListHead; 23877422Smsmith 23987031Smsmith 24087031Smsmith ListHead = Thread->AcquiredMutexList; 24187031Smsmith 24277422Smsmith /* This object will be the first object in the list */ 24377422Smsmith 24487031Smsmith ObjDesc->Mutex.Prev = NULL; 24587031Smsmith ObjDesc->Mutex.Next = ListHead; 24677422Smsmith 24777422Smsmith /* Update old first object to point back to this object */ 24877422Smsmith 24987031Smsmith if (ListHead) 25077422Smsmith { 25187031Smsmith ListHead->Mutex.Prev = ObjDesc; 25277422Smsmith } 25377422Smsmith 25477422Smsmith /* Update list head */ 25577422Smsmith 25687031Smsmith Thread->AcquiredMutexList = ObjDesc; 25777422Smsmith} 25877422Smsmith 25977422Smsmith 26077422Smsmith/******************************************************************************* 26177422Smsmith * 262167802Sjkim * FUNCTION: AcpiExAcquireMutexObject 263167802Sjkim * 264206117Sjkim * PARAMETERS: Timeout - Timeout in milliseconds 265167802Sjkim * ObjDesc - Mutex object 266206117Sjkim * ThreadId - Current thread state 267167802Sjkim * 268167802Sjkim * RETURN: Status 269167802Sjkim * 270167802Sjkim * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common 271167802Sjkim * path that supports multiple acquires by the same thread. 272167802Sjkim * 273167802Sjkim * MUTEX: Interpreter must be locked 274167802Sjkim * 275167802Sjkim * NOTE: This interface is called from three places: 276167802Sjkim * 1) From AcpiExAcquireMutex, via an AML Acquire() operator 277167802Sjkim * 2) From AcpiExAcquireGlobalLock when an AML Field access requires the 278167802Sjkim * global lock 279167802Sjkim * 3) From the external interface, AcpiAcquireGlobalLock 280167802Sjkim * 281167802Sjkim ******************************************************************************/ 282167802Sjkim 283167802SjkimACPI_STATUS 284167802SjkimAcpiExAcquireMutexObject ( 285167802Sjkim UINT16 Timeout, 286167802Sjkim ACPI_OPERAND_OBJECT *ObjDesc, 287167802Sjkim ACPI_THREAD_ID ThreadId) 288167802Sjkim{ 289167802Sjkim ACPI_STATUS Status; 290167802Sjkim 291167802Sjkim 292167802Sjkim ACPI_FUNCTION_TRACE_PTR (ExAcquireMutexObject, ObjDesc); 293167802Sjkim 294167802Sjkim 295167802Sjkim if (!ObjDesc) 296167802Sjkim { 297167802Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 298167802Sjkim } 299167802Sjkim 300167802Sjkim /* Support for multiple acquires by the owning thread */ 301167802Sjkim 302167802Sjkim if (ObjDesc->Mutex.ThreadId == ThreadId) 303167802Sjkim { 304167802Sjkim /* 305167802Sjkim * The mutex is already owned by this thread, just increment the 306167802Sjkim * acquisition depth 307167802Sjkim */ 308167802Sjkim ObjDesc->Mutex.AcquisitionDepth++; 309167802Sjkim return_ACPI_STATUS (AE_OK); 310167802Sjkim } 311167802Sjkim 312167802Sjkim /* Acquire the mutex, wait if necessary. Special case for Global Lock */ 313167802Sjkim 314167802Sjkim if (ObjDesc == AcpiGbl_GlobalLockMutex) 315167802Sjkim { 316167802Sjkim Status = AcpiEvAcquireGlobalLock (Timeout); 317167802Sjkim } 318167802Sjkim else 319167802Sjkim { 320298714Sjkim Status = AcpiExSystemWaitMutex (ObjDesc->Mutex.OsMutex, Timeout); 321167802Sjkim } 322167802Sjkim 323167802Sjkim if (ACPI_FAILURE (Status)) 324167802Sjkim { 325167802Sjkim /* Includes failure from a timeout on TimeDesc */ 326167802Sjkim 327167802Sjkim return_ACPI_STATUS (Status); 328167802Sjkim } 329167802Sjkim 330167802Sjkim /* Acquired the mutex: update mutex object */ 331167802Sjkim 332167802Sjkim ObjDesc->Mutex.ThreadId = ThreadId; 333167802Sjkim ObjDesc->Mutex.AcquisitionDepth = 1; 334167802Sjkim ObjDesc->Mutex.OriginalSyncLevel = 0; 335167802Sjkim ObjDesc->Mutex.OwnerThread = NULL; /* Used only for AML Acquire() */ 336167802Sjkim 337167802Sjkim return_ACPI_STATUS (AE_OK); 338167802Sjkim} 339167802Sjkim 340167802Sjkim 341167802Sjkim/******************************************************************************* 342167802Sjkim * 34377422Smsmith * FUNCTION: AcpiExAcquireMutex 34477422Smsmith * 345151937Sjkim * PARAMETERS: TimeDesc - Timeout integer 346151937Sjkim * ObjDesc - Mutex object 347151937Sjkim * WalkState - Current method execution state 34877422Smsmith * 34977422Smsmith * RETURN: Status 35077422Smsmith * 35177422Smsmith * DESCRIPTION: Acquire an AML mutex 35277422Smsmith * 35377422Smsmith ******************************************************************************/ 35477422Smsmith 35577422SmsmithACPI_STATUS 35677422SmsmithAcpiExAcquireMutex ( 35777422Smsmith ACPI_OPERAND_OBJECT *TimeDesc, 35877422Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 35977422Smsmith ACPI_WALK_STATE *WalkState) 36077422Smsmith{ 36177422Smsmith ACPI_STATUS Status; 36277422Smsmith 36377422Smsmith 364167802Sjkim ACPI_FUNCTION_TRACE_PTR (ExAcquireMutex, ObjDesc); 36577422Smsmith 366107325Siwasaki 36777422Smsmith if (!ObjDesc) 36877422Smsmith { 36977422Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 37077422Smsmith } 37177422Smsmith 372206117Sjkim /* Must have a valid thread state struct */ 373107325Siwasaki 374107325Siwasaki if (!WalkState->Thread) 375107325Siwasaki { 376206117Sjkim ACPI_ERROR ((AE_INFO, 377206117Sjkim "Cannot acquire Mutex [%4.4s], null thread info", 378151937Sjkim AcpiUtGetNodeName (ObjDesc->Mutex.Node))); 379107325Siwasaki return_ACPI_STATUS (AE_AML_INTERNAL); 380107325Siwasaki } 381107325Siwasaki 38277422Smsmith /* 383298714Sjkim * Current sync level must be less than or equal to the sync level 384298714Sjkim * of the mutex. This mechanism provides some deadlock prevention. 38577422Smsmith */ 38687031Smsmith if (WalkState->Thread->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel) 38777422Smsmith { 388167802Sjkim ACPI_ERROR ((AE_INFO, 389298714Sjkim "Cannot acquire Mutex [%4.4s], " 390298714Sjkim "current SyncLevel is too large (%u)", 391167802Sjkim AcpiUtGetNodeName (ObjDesc->Mutex.Node), 392167802Sjkim WalkState->Thread->CurrentSyncLevel)); 39377422Smsmith return_ACPI_STATUS (AE_AML_MUTEX_ORDER); 39477422Smsmith } 39577422Smsmith 396298714Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 397298714Sjkim "Acquiring: Mutex SyncLevel %u, Thread SyncLevel %u, " 398298714Sjkim "Depth %u TID %p\n", 399298714Sjkim ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel, 400298714Sjkim ObjDesc->Mutex.AcquisitionDepth, WalkState->Thread)); 401298714Sjkim 402167802Sjkim Status = AcpiExAcquireMutexObject ((UINT16) TimeDesc->Integer.Value, 403298714Sjkim ObjDesc, WalkState->Thread->ThreadId); 404298714Sjkim 405167802Sjkim if (ACPI_SUCCESS (Status) && ObjDesc->Mutex.AcquisitionDepth == 1) 406127175Snjl { 407167802Sjkim /* Save Thread object, original/current sync levels */ 408107325Siwasaki 409167802Sjkim ObjDesc->Mutex.OwnerThread = WalkState->Thread; 410298714Sjkim ObjDesc->Mutex.OriginalSyncLevel = 411298714Sjkim WalkState->Thread->CurrentSyncLevel; 412298714Sjkim WalkState->Thread->CurrentSyncLevel = 413298714Sjkim ObjDesc->Mutex.SyncLevel; 414167802Sjkim 415167802Sjkim /* Link the mutex to the current thread for force-unlock at method exit */ 416167802Sjkim 417167802Sjkim AcpiExLinkMutex (ObjDesc, WalkState->Thread); 41877422Smsmith } 41977422Smsmith 420298714Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 421298714Sjkim "Acquired: Mutex SyncLevel %u, Thread SyncLevel %u, Depth %u\n", 422298714Sjkim ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel, 423298714Sjkim ObjDesc->Mutex.AcquisitionDepth)); 424298714Sjkim 425167802Sjkim return_ACPI_STATUS (Status); 426167802Sjkim} 42777422Smsmith 428167802Sjkim 429167802Sjkim/******************************************************************************* 430167802Sjkim * 431167802Sjkim * FUNCTION: AcpiExReleaseMutexObject 432167802Sjkim * 433167802Sjkim * PARAMETERS: ObjDesc - The object descriptor for this op 434167802Sjkim * 435167802Sjkim * RETURN: Status 436167802Sjkim * 437167802Sjkim * DESCRIPTION: Release a previously acquired Mutex, low level interface. 438167802Sjkim * Provides a common path that supports multiple releases (after 439167802Sjkim * previous multiple acquires) by the same thread. 440167802Sjkim * 441167802Sjkim * MUTEX: Interpreter must be locked 442167802Sjkim * 443167802Sjkim * NOTE: This interface is called from three places: 444167802Sjkim * 1) From AcpiExReleaseMutex, via an AML Acquire() operator 445167802Sjkim * 2) From AcpiExReleaseGlobalLock when an AML Field access requires the 446167802Sjkim * global lock 447167802Sjkim * 3) From the external interface, AcpiReleaseGlobalLock 448167802Sjkim * 449167802Sjkim ******************************************************************************/ 450167802Sjkim 451167802SjkimACPI_STATUS 452167802SjkimAcpiExReleaseMutexObject ( 453167802Sjkim ACPI_OPERAND_OBJECT *ObjDesc) 454167802Sjkim{ 455167802Sjkim ACPI_STATUS Status = AE_OK; 456167802Sjkim 457167802Sjkim 458167802Sjkim ACPI_FUNCTION_TRACE (ExReleaseMutexObject); 459167802Sjkim 460167802Sjkim 461167802Sjkim if (ObjDesc->Mutex.AcquisitionDepth == 0) 46277422Smsmith { 463241973Sjkim return_ACPI_STATUS (AE_NOT_ACQUIRED); 464167802Sjkim } 46577422Smsmith 466167802Sjkim /* Match multiple Acquires with multiple Releases */ 467167802Sjkim 468167802Sjkim ObjDesc->Mutex.AcquisitionDepth--; 469167802Sjkim if (ObjDesc->Mutex.AcquisitionDepth != 0) 470167802Sjkim { 471167802Sjkim /* Just decrement the depth and return */ 472167802Sjkim 473167802Sjkim return_ACPI_STATUS (AE_OK); 47477422Smsmith } 47577422Smsmith 476167802Sjkim if (ObjDesc->Mutex.OwnerThread) 477167802Sjkim { 478167802Sjkim /* Unlink the mutex from the owner's list */ 47977422Smsmith 480167802Sjkim AcpiExUnlinkMutex (ObjDesc); 481167802Sjkim ObjDesc->Mutex.OwnerThread = NULL; 482167802Sjkim } 48377422Smsmith 484167802Sjkim /* Release the mutex, special case for Global Lock */ 48577422Smsmith 486167802Sjkim if (ObjDesc == AcpiGbl_GlobalLockMutex) 487167802Sjkim { 488167802Sjkim Status = AcpiEvReleaseGlobalLock (); 489167802Sjkim } 490167802Sjkim else 491167802Sjkim { 492167802Sjkim AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex); 493167802Sjkim } 49477422Smsmith 495167802Sjkim /* Clear mutex info */ 49687031Smsmith 497167802Sjkim ObjDesc->Mutex.ThreadId = 0; 498167802Sjkim return_ACPI_STATUS (Status); 49977422Smsmith} 50077422Smsmith 50177422Smsmith 50277422Smsmith/******************************************************************************* 50377422Smsmith * 50477422Smsmith * FUNCTION: AcpiExReleaseMutex 50577422Smsmith * 506129684Snjl * PARAMETERS: ObjDesc - The object descriptor for this op 507151937Sjkim * WalkState - Current method execution state 50877422Smsmith * 50977422Smsmith * RETURN: Status 51077422Smsmith * 51177422Smsmith * DESCRIPTION: Release a previously acquired Mutex. 51277422Smsmith * 51377422Smsmith ******************************************************************************/ 51477422Smsmith 51577422SmsmithACPI_STATUS 51677422SmsmithAcpiExReleaseMutex ( 51777422Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 51877422Smsmith ACPI_WALK_STATE *WalkState) 51977422Smsmith{ 520193267Sjkim UINT8 PreviousSyncLevel; 521204773Sjkim ACPI_THREAD_STATE *OwnerThread; 522298714Sjkim ACPI_STATUS Status = AE_OK; 52377422Smsmith 52477422Smsmith 525167802Sjkim ACPI_FUNCTION_TRACE (ExReleaseMutex); 52677422Smsmith 52777422Smsmith 52877422Smsmith if (!ObjDesc) 52977422Smsmith { 53077422Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 53177422Smsmith } 53277422Smsmith 533204773Sjkim OwnerThread = ObjDesc->Mutex.OwnerThread; 534204773Sjkim 53583174Smsmith /* The mutex must have been previously acquired in order to release it */ 53677422Smsmith 537204773Sjkim if (!OwnerThread) 53877422Smsmith { 539206117Sjkim ACPI_ERROR ((AE_INFO, 540206117Sjkim "Cannot release Mutex [%4.4s], not acquired", 541167802Sjkim AcpiUtGetNodeName (ObjDesc->Mutex.Node))); 54277422Smsmith return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED); 54377422Smsmith } 54477422Smsmith 545200553Sjkim /* Must have a valid thread ID */ 546200553Sjkim 547200553Sjkim if (!WalkState->Thread) 548200553Sjkim { 549206117Sjkim ACPI_ERROR ((AE_INFO, 550206117Sjkim "Cannot release Mutex [%4.4s], null thread info", 551200553Sjkim AcpiUtGetNodeName (ObjDesc->Mutex.Node))); 552200553Sjkim return_ACPI_STATUS (AE_AML_INTERNAL); 553200553Sjkim } 554200553Sjkim 555129684Snjl /* 556127175Snjl * The Mutex is owned, but this thread must be the owner. 557127175Snjl * Special case for Global Lock, any thread can release 558127175Snjl */ 559204773Sjkim if ((OwnerThread->ThreadId != WalkState->Thread->ThreadId) && 560167802Sjkim (ObjDesc != AcpiGbl_GlobalLockMutex)) 56177422Smsmith { 562167802Sjkim ACPI_ERROR ((AE_INFO, 563212761Sjkim "Thread %u cannot release Mutex [%4.4s] acquired by thread %u", 564212761Sjkim (UINT32) WalkState->Thread->ThreadId, 565123315Snjl AcpiUtGetNodeName (ObjDesc->Mutex.Node), 566212761Sjkim (UINT32) OwnerThread->ThreadId)); 56777422Smsmith return_ACPI_STATUS (AE_AML_NOT_OWNER); 56877422Smsmith } 56977422Smsmith 57077422Smsmith /* 571193267Sjkim * The sync level of the mutex must be equal to the current sync level. In 572193267Sjkim * other words, the current level means that at least one mutex at that 573193267Sjkim * level is currently being held. Attempting to release a mutex of a 574193267Sjkim * different level can only mean that the mutex ordering rule is being 575193267Sjkim * violated. This behavior is clarified in ACPI 4.0 specification. 57677422Smsmith */ 577204773Sjkim if (ObjDesc->Mutex.SyncLevel != OwnerThread->CurrentSyncLevel) 57877422Smsmith { 579167802Sjkim ACPI_ERROR ((AE_INFO, 580298714Sjkim "Cannot release Mutex [%4.4s], SyncLevel mismatch: " 581298714Sjkim "mutex %u current %u", 582167802Sjkim AcpiUtGetNodeName (ObjDesc->Mutex.Node), 583167802Sjkim ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel)); 58477422Smsmith return_ACPI_STATUS (AE_AML_MUTEX_ORDER); 58577422Smsmith } 58677422Smsmith 587193267Sjkim /* 588193267Sjkim * Get the previous SyncLevel from the head of the acquired mutex list. 589193267Sjkim * This handles the case where several mutexes at the same level have been 590193267Sjkim * acquired, but are not released in reverse order. 591193267Sjkim */ 592193267Sjkim PreviousSyncLevel = 593204773Sjkim OwnerThread->AcquiredMutexList->Mutex.OriginalSyncLevel; 594193267Sjkim 595298714Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 596298714Sjkim "Releasing: Object SyncLevel %u, Thread SyncLevel %u, " 597298714Sjkim "Prev SyncLevel %u, Depth %u TID %p\n", 598298714Sjkim ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel, 599298714Sjkim PreviousSyncLevel, ObjDesc->Mutex.AcquisitionDepth, 600298714Sjkim WalkState->Thread)); 601298714Sjkim 602167802Sjkim Status = AcpiExReleaseMutexObject (ObjDesc); 603193267Sjkim if (ACPI_FAILURE (Status)) 604193267Sjkim { 605193267Sjkim return_ACPI_STATUS (Status); 606193267Sjkim } 607129684Snjl 608167802Sjkim if (ObjDesc->Mutex.AcquisitionDepth == 0) 60977422Smsmith { 610193267Sjkim /* Restore the previous SyncLevel */ 61177422Smsmith 612204773Sjkim OwnerThread->CurrentSyncLevel = PreviousSyncLevel; 61377422Smsmith } 614206117Sjkim 615298714Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 616298714Sjkim "Released: Object SyncLevel %u, Thread SyncLevel, %u, " 617298714Sjkim "Prev SyncLevel %u, Depth %u\n", 618298714Sjkim ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel, 619298714Sjkim PreviousSyncLevel, ObjDesc->Mutex.AcquisitionDepth)); 620298714Sjkim 62177422Smsmith return_ACPI_STATUS (Status); 62277422Smsmith} 62377422Smsmith 62477422Smsmith 62577422Smsmith/******************************************************************************* 62677422Smsmith * 62777422Smsmith * FUNCTION: AcpiExReleaseAllMutexes 62877422Smsmith * 629206117Sjkim * PARAMETERS: Thread - Current executing thread object 63077422Smsmith * 63177422Smsmith * RETURN: Status 63277422Smsmith * 633151937Sjkim * DESCRIPTION: Release all mutexes held by this thread 63477422Smsmith * 635167802Sjkim * NOTE: This function is called as the thread is exiting the interpreter. 636167802Sjkim * Mutexes are not released when an individual control method is exited, but 637167802Sjkim * only when the parent thread actually exits the interpreter. This allows one 638167802Sjkim * method to acquire a mutex, and a different method to release it, as long as 639167802Sjkim * this is performed underneath a single parent control method. 640167802Sjkim * 64177422Smsmith ******************************************************************************/ 64277422Smsmith 64399679Siwasakivoid 64477422SmsmithAcpiExReleaseAllMutexes ( 64587031Smsmith ACPI_THREAD_STATE *Thread) 64677422Smsmith{ 64787031Smsmith ACPI_OPERAND_OBJECT *Next = Thread->AcquiredMutexList; 648167802Sjkim ACPI_OPERAND_OBJECT *ObjDesc; 64977422Smsmith 65077422Smsmith 651298714Sjkim ACPI_FUNCTION_TRACE (ExReleaseAllMutexes); 65283174Smsmith 65383174Smsmith 654129684Snjl /* Traverse the list of owned mutexes, releasing each one */ 655129684Snjl 65677422Smsmith while (Next) 65777422Smsmith { 658167802Sjkim ObjDesc = Next; 659241973Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 660298714Sjkim "Mutex [%4.4s] force-release, SyncLevel %u Depth %u\n", 661298714Sjkim ObjDesc->Mutex.Node->Name.Ascii, ObjDesc->Mutex.SyncLevel, 662298714Sjkim ObjDesc->Mutex.AcquisitionDepth)); 663241973Sjkim 664167802Sjkim /* Release the mutex, special case for Global Lock */ 66577422Smsmith 666167802Sjkim if (ObjDesc == AcpiGbl_GlobalLockMutex) 66799679Siwasaki { 668167802Sjkim /* Ignore errors */ 669167802Sjkim 670167802Sjkim (void) AcpiEvReleaseGlobalLock (); 67199679Siwasaki } 672167802Sjkim else 673167802Sjkim { 674167802Sjkim AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex); 675167802Sjkim } 67687031Smsmith 677298714Sjkim /* Update Thread SyncLevel (Last mutex is the important one) */ 678298714Sjkim 679298714Sjkim Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel; 680298714Sjkim 68187031Smsmith /* Mark mutex unowned */ 68287031Smsmith 683298714Sjkim Next = ObjDesc->Mutex.Next; 684298714Sjkim 685298714Sjkim ObjDesc->Mutex.Prev = NULL; 686298714Sjkim ObjDesc->Mutex.Next = NULL; 687298714Sjkim ObjDesc->Mutex.AcquisitionDepth = 0; 688167802Sjkim ObjDesc->Mutex.OwnerThread = NULL; 689167802Sjkim ObjDesc->Mutex.ThreadId = 0; 690298714Sjkim } 691129684Snjl 692298714Sjkim return_VOID; 69377422Smsmith} 694