1/******************************************************************************* 2 * 3 * Module Name: utmutex - local mutex support 4 * 5 ******************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2007, R. Byron Moore 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 <acpi/acpi.h> 45 46#define _COMPONENT ACPI_UTILITIES 47ACPI_MODULE_NAME("utmutex") 48 49/* Local prototypes */ 50static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id); 51 52static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id); 53 54/******************************************************************************* 55 * 56 * FUNCTION: acpi_ut_mutex_initialize 57 * 58 * PARAMETERS: None. 59 * 60 * RETURN: Status 61 * 62 * DESCRIPTION: Create the system mutex objects. 63 * 64 ******************************************************************************/ 65 66acpi_status acpi_ut_mutex_initialize(void) 67{ 68 u32 i; 69 acpi_status status; 70 71 ACPI_FUNCTION_TRACE(ut_mutex_initialize); 72 73 /* 74 * Create each of the predefined mutex objects 75 */ 76 for (i = 0; i < ACPI_NUM_MUTEX; i++) { 77 status = acpi_ut_create_mutex(i); 78 if (ACPI_FAILURE(status)) { 79 return_ACPI_STATUS(status); 80 } 81 } 82 83 /* Create the spinlocks for use at interrupt level */ 84 85 spin_lock_init(acpi_gbl_gpe_lock); 86 spin_lock_init(acpi_gbl_hardware_lock); 87 88 return_ACPI_STATUS(status); 89} 90 91/******************************************************************************* 92 * 93 * FUNCTION: acpi_ut_mutex_terminate 94 * 95 * PARAMETERS: None. 96 * 97 * RETURN: None. 98 * 99 * DESCRIPTION: Delete all of the system mutex objects. 100 * 101 ******************************************************************************/ 102 103void acpi_ut_mutex_terminate(void) 104{ 105 u32 i; 106 107 ACPI_FUNCTION_TRACE(ut_mutex_terminate); 108 109 /* 110 * Delete each predefined mutex object 111 */ 112 for (i = 0; i < ACPI_NUM_MUTEX; i++) { 113 (void)acpi_ut_delete_mutex(i); 114 } 115 116 /* Delete the spinlocks */ 117 118 acpi_os_delete_lock(acpi_gbl_gpe_lock); 119 acpi_os_delete_lock(acpi_gbl_hardware_lock); 120 return_VOID; 121} 122 123/******************************************************************************* 124 * 125 * FUNCTION: acpi_ut_create_mutex 126 * 127 * PARAMETERS: mutex_iD - ID of the mutex to be created 128 * 129 * RETURN: Status 130 * 131 * DESCRIPTION: Create a mutex object. 132 * 133 ******************************************************************************/ 134 135static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id) 136{ 137 acpi_status status = AE_OK; 138 139 ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id); 140 141 if (mutex_id > ACPI_MAX_MUTEX) { 142 return_ACPI_STATUS(AE_BAD_PARAMETER); 143 } 144 145 if (!acpi_gbl_mutex_info[mutex_id].mutex) { 146 status = 147 acpi_os_create_mutex(&acpi_gbl_mutex_info[mutex_id].mutex); 148 acpi_gbl_mutex_info[mutex_id].thread_id = 149 ACPI_MUTEX_NOT_ACQUIRED; 150 acpi_gbl_mutex_info[mutex_id].use_count = 0; 151 } 152 153 return_ACPI_STATUS(status); 154} 155 156/******************************************************************************* 157 * 158 * FUNCTION: acpi_ut_delete_mutex 159 * 160 * PARAMETERS: mutex_iD - ID of the mutex to be deleted 161 * 162 * RETURN: Status 163 * 164 * DESCRIPTION: Delete a mutex object. 165 * 166 ******************************************************************************/ 167 168static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id) 169{ 170 171 ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id); 172 173 if (mutex_id > ACPI_MAX_MUTEX) { 174 return_ACPI_STATUS(AE_BAD_PARAMETER); 175 } 176 177 acpi_os_delete_mutex(acpi_gbl_mutex_info[mutex_id].mutex); 178 179 acpi_gbl_mutex_info[mutex_id].mutex = NULL; 180 acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; 181 182 return_ACPI_STATUS(AE_OK); 183} 184 185/******************************************************************************* 186 * 187 * FUNCTION: acpi_ut_acquire_mutex 188 * 189 * PARAMETERS: mutex_iD - ID of the mutex to be acquired 190 * 191 * RETURN: Status 192 * 193 * DESCRIPTION: Acquire a mutex object. 194 * 195 ******************************************************************************/ 196 197acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) 198{ 199 acpi_status status; 200 acpi_thread_id this_thread_id; 201 202 ACPI_FUNCTION_NAME(ut_acquire_mutex); 203 204 if (mutex_id > ACPI_MAX_MUTEX) { 205 return (AE_BAD_PARAMETER); 206 } 207 208 this_thread_id = acpi_os_get_thread_id(); 209 210#ifdef ACPI_MUTEX_DEBUG 211 { 212 u32 i; 213 /* 214 * Mutex debug code, for internal debugging only. 215 * 216 * Deadlock prevention. Check if this thread owns any mutexes of value 217 * greater than or equal to this one. If so, the thread has violated 218 * the mutex ordering rule. This indicates a coding error somewhere in 219 * the ACPI subsystem code. 220 */ 221 for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) { 222 if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { 223 if (i == mutex_id) { 224 ACPI_ERROR((AE_INFO, 225 "Mutex [%s] already acquired by this thread [%X]", 226 acpi_ut_get_mutex_name 227 (mutex_id), 228 this_thread_id)); 229 230 return (AE_ALREADY_ACQUIRED); 231 } 232 233 ACPI_ERROR((AE_INFO, 234 "Invalid acquire order: Thread %X owns [%s], wants [%s]", 235 this_thread_id, 236 acpi_ut_get_mutex_name(i), 237 acpi_ut_get_mutex_name(mutex_id))); 238 239 return (AE_ACQUIRE_DEADLOCK); 240 } 241 } 242 } 243#endif 244 245 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, 246 "Thread %lX attempting to acquire Mutex [%s]\n", 247 (unsigned long)this_thread_id, 248 acpi_ut_get_mutex_name(mutex_id))); 249 250 status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex, 251 ACPI_WAIT_FOREVER); 252 if (ACPI_SUCCESS(status)) { 253 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, 254 "Thread %lX acquired Mutex [%s]\n", 255 (unsigned long)this_thread_id, 256 acpi_ut_get_mutex_name(mutex_id))); 257 258 acpi_gbl_mutex_info[mutex_id].use_count++; 259 acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id; 260 } else { 261 ACPI_EXCEPTION((AE_INFO, status, 262 "Thread %lX could not acquire Mutex [%X]", 263 (unsigned long)this_thread_id, mutex_id)); 264 } 265 266 return (status); 267} 268 269/******************************************************************************* 270 * 271 * FUNCTION: acpi_ut_release_mutex 272 * 273 * PARAMETERS: mutex_iD - ID of the mutex to be released 274 * 275 * RETURN: Status 276 * 277 * DESCRIPTION: Release a mutex object. 278 * 279 ******************************************************************************/ 280 281acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) 282{ 283 acpi_thread_id this_thread_id; 284 285 ACPI_FUNCTION_NAME(ut_release_mutex); 286 287 this_thread_id = acpi_os_get_thread_id(); 288 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, 289 "Thread %lX releasing Mutex [%s]\n", 290 (unsigned long)this_thread_id, 291 acpi_ut_get_mutex_name(mutex_id))); 292 293 if (mutex_id > ACPI_MAX_MUTEX) { 294 return (AE_BAD_PARAMETER); 295 } 296 297 /* 298 * Mutex must be acquired in order to release it! 299 */ 300 if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) { 301 ACPI_ERROR((AE_INFO, 302 "Mutex [%X] is not acquired, cannot release", 303 mutex_id)); 304 305 return (AE_NOT_ACQUIRED); 306 } 307#ifdef ACPI_MUTEX_DEBUG 308 { 309 u32 i; 310 /* 311 * Mutex debug code, for internal debugging only. 312 * 313 * Deadlock prevention. Check if this thread owns any mutexes of value 314 * greater than this one. If so, the thread has violated the mutex 315 * ordering rule. This indicates a coding error somewhere in 316 * the ACPI subsystem code. 317 */ 318 for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) { 319 if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { 320 if (i == mutex_id) { 321 continue; 322 } 323 324 ACPI_ERROR((AE_INFO, 325 "Invalid release order: owns [%s], releasing [%s]", 326 acpi_ut_get_mutex_name(i), 327 acpi_ut_get_mutex_name(mutex_id))); 328 329 return (AE_RELEASE_DEADLOCK); 330 } 331 } 332 } 333#endif 334 335 /* Mark unlocked FIRST */ 336 337 acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED; 338 339 acpi_os_release_mutex(acpi_gbl_mutex_info[mutex_id].mutex); 340 return (AE_OK); 341} 342