1 /******************************************************************************* 2 * 3 * Module Name: utmutex - local mutex support 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 #define __UTMUTEX_C__ 45 46 #include <contrib/dev/acpica/include/acpi.h> 47 #include <contrib/dev/acpica/include/accommon.h> 48 49 #define _COMPONENT ACPI_UTILITIES 50 ACPI_MODULE_NAME ("utmutex") 51 52 /* Local prototypes */ 53 54 static ACPI_STATUS 55 AcpiUtCreateMutex ( 56 ACPI_MUTEX_HANDLE MutexId); 57 58 static void 59 AcpiUtDeleteMutex ( 60 ACPI_MUTEX_HANDLE MutexId); 61 62 63 /******************************************************************************* 64 * 65 * FUNCTION: AcpiUtMutexInitialize 66 * 67 * PARAMETERS: None. 68 * 69 * RETURN: Status 70 * 71 * DESCRIPTION: Create the system mutex objects. This includes mutexes, 72 * spin locks, and reader/writer locks. 73 * 74 ******************************************************************************/ 75 76 ACPI_STATUS 77 AcpiUtMutexInitialize ( 78 void) 79 { 80 UINT32 i; 81 ACPI_STATUS Status; 82 83 84 ACPI_FUNCTION_TRACE (UtMutexInitialize); 85 86 87 /* Create each of the predefined mutex objects */ 88 89 for (i = 0; i < ACPI_NUM_MUTEX; i++) 90 { 91 Status = AcpiUtCreateMutex (i); 92 if (ACPI_FAILURE (Status)) 93 { 94 return_ACPI_STATUS (Status); 95 } 96 } 97 98 /* Create the spinlocks for use at interrupt level or for speed */ 99 100 Status = AcpiOsCreateLock (&AcpiGbl_GpeLock); 101 if (ACPI_FAILURE (Status)) 102 { 103 return_ACPI_STATUS (Status); 104 } 105 106 Status = AcpiOsCreateLock (&AcpiGbl_HardwareLock); 107 if (ACPI_FAILURE (Status)) 108 { 109 return_ACPI_STATUS (Status); 110 } 111 112 Status = AcpiOsCreateLock (&AcpiGbl_ReferenceCountLock); 113 if (ACPI_FAILURE (Status)) 114 { 115 return_ACPI_STATUS (Status); 116 } 117 118 /* Mutex for _OSI support */ 119 120 Status = AcpiOsCreateMutex (&AcpiGbl_OsiMutex); 121 if (ACPI_FAILURE (Status)) 122 { 123 return_ACPI_STATUS (Status); 124 } 125 126 /* Create the reader/writer lock for namespace access */ 127 128 Status = AcpiUtCreateRwLock (&AcpiGbl_NamespaceRwLock); 129 return_ACPI_STATUS (Status); 130 } 131 132 133 /******************************************************************************* 134 * 135 * FUNCTION: AcpiUtMutexTerminate 136 * 137 * PARAMETERS: None. 138 * 139 * RETURN: None. 140 * 141 * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, 142 * spin locks, and reader/writer locks. 143 * 144 ******************************************************************************/ 145 146 void 147 AcpiUtMutexTerminate ( 148 void) 149 { 150 UINT32 i; 151 152 153 ACPI_FUNCTION_TRACE (UtMutexTerminate); 154 155 156 /* Delete each predefined mutex object */ 157 158 for (i = 0; i < ACPI_NUM_MUTEX; i++) 159 { 160 AcpiUtDeleteMutex (i); 161 } 162 163 AcpiOsDeleteMutex (AcpiGbl_OsiMutex); 164 165 /* Delete the spinlocks */ 166 167 AcpiOsDeleteLock (AcpiGbl_GpeLock); 168 AcpiOsDeleteLock (AcpiGbl_HardwareLock); 169 AcpiOsDeleteLock (AcpiGbl_ReferenceCountLock); 170 171 /* Delete the reader/writer lock */ 172 173 AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock); 174 return_VOID; 175 } 176 177 178 /******************************************************************************* 179 * 180 * FUNCTION: AcpiUtCreateMutex 181 * 182 * PARAMETERS: MutexID - ID of the mutex to be created 183 * 184 * RETURN: Status 185 * 186 * DESCRIPTION: Create a mutex object. 187 * 188 ******************************************************************************/ 189 190 static ACPI_STATUS 191 AcpiUtCreateMutex ( 192 ACPI_MUTEX_HANDLE MutexId) 193 { 194 ACPI_STATUS Status = AE_OK; 195 196 197 ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId); 198 199 200 if (!AcpiGbl_MutexInfo[MutexId].Mutex) 201 { 202 Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex); 203 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 204 AcpiGbl_MutexInfo[MutexId].UseCount = 0; 205 } 206 207 return_ACPI_STATUS (Status); 208 } 209 210 211 /******************************************************************************* 212 * 213 * FUNCTION: AcpiUtDeleteMutex 214 * 215 * PARAMETERS: MutexID - ID of the mutex to be deleted 216 * 217 * RETURN: Status 218 * 219 * DESCRIPTION: Delete a mutex object. 220 * 221 ******************************************************************************/ 222 223 static void 224 AcpiUtDeleteMutex ( 225 ACPI_MUTEX_HANDLE MutexId) 226 { 227 228 ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId); 229 230 231 AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 232 233 AcpiGbl_MutexInfo[MutexId].Mutex = NULL; 234 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 235 236 return_VOID; 237 } 238 239 240 /******************************************************************************* 241 * 242 * FUNCTION: AcpiUtAcquireMutex 243 * 244 * PARAMETERS: MutexID - ID of the mutex to be acquired 245 * 246 * RETURN: Status 247 * 248 * DESCRIPTION: Acquire a mutex object. 249 * 250 ******************************************************************************/ 251 252 ACPI_STATUS 253 AcpiUtAcquireMutex ( 254 ACPI_MUTEX_HANDLE MutexId) 255 { 256 ACPI_STATUS Status; 257 ACPI_THREAD_ID ThisThreadId; 258 259 260 ACPI_FUNCTION_NAME (UtAcquireMutex); 261 262 263 if (MutexId > ACPI_MAX_MUTEX) 264 { 265 return (AE_BAD_PARAMETER); 266 } 267 268 ThisThreadId = AcpiOsGetThreadId (); 269 270 #ifdef ACPI_MUTEX_DEBUG 271 { 272 UINT32 i; 273 /* 274 * Mutex debug code, for internal debugging only. 275 * 276 * Deadlock prevention. Check if this thread owns any mutexes of value 277 * greater than or equal to this one. If so, the thread has violated 278 * the mutex ordering rule. This indicates a coding error somewhere in 279 * the ACPI subsystem code. 280 */ 281 for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 282 { 283 if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) 284 { 285 if (i == MutexId) 286 { 287 ACPI_ERROR ((AE_INFO, 288 "Mutex [%s] already acquired by this thread [%u]", 289 AcpiUtGetMutexName (MutexId), 290 (UINT32) ThisThreadId)); 291 292 return (AE_ALREADY_ACQUIRED); 293 } 294 295 ACPI_ERROR ((AE_INFO, 296 "Invalid acquire order: Thread %u owns [%s], wants [%s]", 297 (UINT32) ThisThreadId, AcpiUtGetMutexName (i), 298 AcpiUtGetMutexName (MutexId))); 299 300 return (AE_ACQUIRE_DEADLOCK); 301 } 302 } 303 } 304 #endif 305 306 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, 307 "Thread %u attempting to acquire Mutex [%s]\n", 308 (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 309 310 Status = AcpiOsAcquireMutex (AcpiGbl_MutexInfo[MutexId].Mutex, 311 ACPI_WAIT_FOREVER); 312 if (ACPI_SUCCESS (Status)) 313 { 314 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u acquired Mutex [%s]\n", 315 (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); 316 317 AcpiGbl_MutexInfo[MutexId].UseCount++; 318 AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId; 319 } 320 else 321 { 322 ACPI_EXCEPTION ((AE_INFO, Status, 323 "Thread %u could not acquire Mutex [0x%X]", 324 (UINT32) ThisThreadId, MutexId)); 325 } 326 327 return (Status); 328 } 329 330 331 /******************************************************************************* 332 * 333 * FUNCTION: AcpiUtReleaseMutex 334 * 335 * PARAMETERS: MutexID - ID of the mutex to be released 336 * 337 * RETURN: Status 338 * 339 * DESCRIPTION: Release a mutex object. 340 * 341 ******************************************************************************/ 342 343 ACPI_STATUS 344 AcpiUtReleaseMutex ( 345 ACPI_MUTEX_HANDLE MutexId) 346 { 347 ACPI_FUNCTION_NAME (UtReleaseMutex); 348 349 350 ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", 351 (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId))); 352 353 if (MutexId > ACPI_MAX_MUTEX) 354 { 355 return (AE_BAD_PARAMETER); 356 } 357 358 /* 359 * Mutex must be acquired in order to release it! 360 */ 361 if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED) 362 { 363 ACPI_ERROR ((AE_INFO, 364 "Mutex [0x%X] is not acquired, cannot release", MutexId)); 365 366 return (AE_NOT_ACQUIRED); 367 } 368 369 #ifdef ACPI_MUTEX_DEBUG 370 { 371 UINT32 i; 372 /* 373 * Mutex debug code, for internal debugging only. 374 * 375 * Deadlock prevention. Check if this thread owns any mutexes of value 376 * greater than this one. If so, the thread has violated the mutex 377 * ordering rule. This indicates a coding error somewhere in 378 * the ACPI subsystem code. 379 */ 380 for (i = MutexId; i < ACPI_NUM_MUTEX; i++) 381 { 382 if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ()) 383 { 384 if (i == MutexId) 385 { 386 continue; 387 } 388 389 ACPI_ERROR ((AE_INFO, 390 "Invalid release order: owns [%s], releasing [%s]", 391 AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); 392 393 return (AE_RELEASE_DEADLOCK); 394 } 395 } 396 } 397 #endif 398 399 /* Mark unlocked FIRST */ 400 401 AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; 402 403 AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex); 404 return (AE_OK); 405 } 406