1 /******************************************************************************* 2 * 3 * Module Name: utmutex - local mutex support 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <contrib/dev/acpica/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 47 #define _COMPONENT ACPI_UTILITIES 48 ACPI_MODULE_NAME ("utmutex") 49 50 /* Local prototypes */ 51 52 static ACPI_STATUS 53 AcpiUtCreateMutex ( 54 ACPI_MUTEX_HANDLE MutexId); 55 56 static void 57 AcpiUtDeleteMutex ( 58 ACPI_MUTEX_HANDLE MutexId); 59 60 61 /******************************************************************************* 62 * 63 * FUNCTION: AcpiUtMutexInitialize 64 * 65 * PARAMETERS: None. 66 * 67 * RETURN: Status 68 * 69 * DESCRIPTION: Create the system mutex objects. This includes mutexes, 70 * spin locks, and reader/writer locks. 71 * 72 ******************************************************************************/ 73 74 ACPI_STATUS 75 AcpiUtMutexInitialize ( 76 void) 77 { 78 UINT32 i; 79 ACPI_STATUS Status; 80 81 82 ACPI_FUNCTION_TRACE (UtMutexInitialize); 83 84 85 /* Create each of the predefined mutex objects */ 86 87 for (i = 0; i < ACPI_NUM_MUTEX; i++) 88 { 89 Status = AcpiUtCreateMutex (i); 90 if (ACPI_FAILURE (Status)) 91 { 92 return_ACPI_STATUS (Status); 93 } 94 } 95 96 /* Create the spinlocks for use at interrupt level or for speed */ 97 98 Status = AcpiOsCreateLock (&AcpiGbl_GpeLock); 99 if (ACPI_FAILURE (Status)) 100 { 101 return_ACPI_STATUS (Status); 102 } 103 104 Status = AcpiOsCreateLock (&AcpiGbl_HardwareLock); 105 if (ACPI_FAILURE (Status)) 106 { 107 return_ACPI_STATUS (Status); 108 } 109 110 Status = AcpiOsCreateLock (&AcpiGbl_ReferenceCountLock); 111 if (ACPI_FAILURE (Status)) 112 { 113 return_ACPI_STATUS (Status); 114 } 115 116 /* Mutex for _OSI support */ 117 118 Status = AcpiOsCreateMutex (&AcpiGbl_OsiMutex); 119 if (ACPI_FAILURE (Status)) 120 { 121 return_ACPI_STATUS (Status); 122 } 123 124 /* Create the reader/writer lock for namespace access */ 125 126 Status = AcpiUtCreateRwLock (&AcpiGbl_NamespaceRwLock); 127 return_ACPI_STATUS (Status); 128 } 129 130 131 /******************************************************************************* 132 * 133 * FUNCTION: AcpiUtMutexTerminate 134 * 135 * PARAMETERS: None. 136 * 137 * RETURN: None. 138 * 139 * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, 140 * spin locks, and reader/writer locks. 141 * 142 ******************************************************************************/ 143 144 void 145 AcpiUtMutexTerminate ( 146 void) 147 { 148 UINT32 i; 149 150 151 ACPI_FUNCTION_TRACE (UtMutexTerminate); 152 153 154 /* Delete each predefined mutex object */ 155 156 for (i = 0; i < ACPI_NUM_MUTEX; i++) 157 { 158 AcpiUtDeleteMutex (i); 159 } 160 161 AcpiOsDeleteMutex (AcpiGbl_OsiMutex); 162 163 /* Delete the spinlocks */ 164 165 AcpiOsDeleteLock (AcpiGbl_GpeLock); 166 AcpiOsDeleteLock (AcpiGbl_HardwareLock); 167 AcpiOsDeleteLock (AcpiGbl_ReferenceCountLock); 168 169 /* Delete the reader/writer lock */ 170 171 AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock); 172 return_VOID; 173 } 174 175 176 /******************************************************************************* 177 * 178 * FUNCTION: AcpiUtCreateMutex 179 * 180 * PARAMETERS: MutexID - ID of the mutex to be created 181 * 182 * RETURN: Status 183 * 184 * DESCRIPTION: Create a mutex object. 185 * 186 ******************************************************************************/ 187 188 static ACPI_STATUS 189 AcpiUtCreateMutex ( 190 ACPI_MUTEX_HANDLE MutexId) 191 { 192 ACPI_STATUS Status = AE_OK; 193 194 195 ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId); 196 197 198 if (!AcpiGbl_MutexInfo[MutexId].Mutex) 199 { 200 Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex); 201 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 202 AcpiGbl_MutexInfo[MutexId].UseCount = 0; 203 } 204 205 return_ACPI_STATUS (Status); 206 } 207 208 209 /******************************************************************************* 210 * 211 * FUNCTION: AcpiUtDeleteMutex 212 * 213 * PARAMETERS: MutexID - ID of the mutex to be deleted 214 * 215 * RETURN: Status 216 * 217 * DESCRIPTION: Delete a mutex object. 218 * 219 ******************************************************************************/ 220 221 static void 222 AcpiUtDeleteMutex ( 223 ACPI_MUTEX_HANDLE MutexId) 224 { 225 226 ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId); 227 228 229 AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 230 231 AcpiGbl_MutexInfo[MutexId].Mutex = NULL; 232 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 233 234 return_VOID; 235 } 236 237 238 /******************************************************************************* 239 * 240 * FUNCTION: AcpiUtAcquireMutex 241 * 242 * PARAMETERS: MutexID - ID of the mutex to be acquired 243 * 244 * RETURN: Status 245 * 246 * DESCRIPTION: Acquire a mutex object. 247 * 248 ******************************************************************************/ 249 250 ACPI_STATUS 251 AcpiUtAcquireMutex ( 252 ACPI_MUTEX_HANDLE MutexId) 253 { 254 ACPI_STATUS Status; 255 ACPI_THREAD_ID ThisThreadId; 256 257 258 ACPI_FUNCTION_NAME (UtAcquireMutex); 259 260 261 if (MutexId > ACPI_MAX_MUTEX) 262 { 263 return (AE_BAD_PARAMETER); 264 } 265 266 ThisThreadId = AcpiOsGetThreadId (); 267 268 #ifdef ACPI_MUTEX_DEBUG 269 { 270 UINT32 i; 271 /* 272 * Mutex debug code, for internal debugging only. 273 * 274 * Deadlock prevention. Check if this thread owns any mutexes of value 275 * greater than or equal to this one. If so, the thread has violated 276 * the mutex ordering rule. This indicates a coding error somewhere in 277 * the ACPI subsystem code. 278 */ 279 for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 280 { 281 if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) 282 { 283 if (i == MutexId) 284 { 285 ACPI_ERROR ((AE_INFO, 286 "Mutex [%s] already acquired by this thread [%u]", 287 AcpiUtGetMutexName (MutexId), 288 (UINT32) ThisThreadId)); 289 290 return (AE_ALREADY_ACQUIRED); 291 } 292 293 ACPI_ERROR ((AE_INFO, 294 "Invalid acquire order: Thread %u owns [%s], wants [%s]", 295 (UINT32) ThisThreadId, AcpiUtGetMutexName (i), 296 AcpiUtGetMutexName (MutexId))); 297 298 return (AE_ACQUIRE_DEADLOCK); 299 } 300 } 301 } 302 #endif 303 304 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 305 "Thread %u attempting to acquire Mutex [%s]\n", 306 (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 307 308 Status = AcpiOsAcquireMutex (AcpiGbl_MutexInfo[MutexId].Mutex, 309 ACPI_WAIT_FOREVER); 310 if (ACPI_SUCCESS (Status)) 311 { 312 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u acquired Mutex [%s]\n", 313 (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 314 315 AcpiGbl_MutexInfo[MutexId].UseCount++; 316 AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId; 317 } 318 else 319 { 320 ACPI_EXCEPTION ((AE_INFO, Status, 321 "Thread %u could not acquire Mutex [0x%X]", 322 (UINT32) ThisThreadId, MutexId)); 323 } 324 325 return (Status); 326 } 327 328 329 /******************************************************************************* 330 * 331 * FUNCTION: AcpiUtReleaseMutex 332 * 333 * PARAMETERS: MutexID - ID of the mutex to be released 334 * 335 * RETURN: Status 336 * 337 * DESCRIPTION: Release a mutex object. 338 * 339 ******************************************************************************/ 340 341 ACPI_STATUS 342 AcpiUtReleaseMutex ( 343 ACPI_MUTEX_HANDLE MutexId) 344 { 345 ACPI_FUNCTION_NAME (UtReleaseMutex); 346 347 348 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", 349 (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId))); 350 351 if (MutexId > ACPI_MAX_MUTEX) 352 { 353 return (AE_BAD_PARAMETER); 354 } 355 356 /* 357 * Mutex must be acquired in order to release it! 358 */ 359 if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED) 360 { 361 ACPI_ERROR ((AE_INFO, 362 "Mutex [0x%X] is not acquired, cannot release", MutexId)); 363 364 return (AE_NOT_ACQUIRED); 365 } 366 367 #ifdef ACPI_MUTEX_DEBUG 368 { 369 UINT32 i; 370 /* 371 * Mutex debug code, for internal debugging only. 372 * 373 * Deadlock prevention. Check if this thread owns any mutexes of value 374 * greater than this one. If so, the thread has violated the mutex 375 * ordering rule. This indicates a coding error somewhere in 376 * the ACPI subsystem code. 377 */ 378 for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 379 { 380 if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ()) 381 { 382 if (i == MutexId) 383 { 384 continue; 385 } 386 387 ACPI_ERROR ((AE_INFO, 388 "Invalid release order: owns [%s], releasing [%s]", 389 AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); 390 391 return (AE_RELEASE_DEADLOCK); 392 } 393 } 394 } 395 #endif 396 397 /* Mark unlocked FIRST */ 398 399 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 400 401 AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 402 return (AE_OK); 403 } 404