Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.13-rc6 376 lines 11 kB view raw
1 2/****************************************************************************** 3 * 4 * Module Name: exmutex - ASL Mutex Acquire/Release functions 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000 - 2005, R. Byron Moore 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 46#include <acpi/acpi.h> 47#include <acpi/acinterp.h> 48 49#define _COMPONENT ACPI_EXECUTER 50 ACPI_MODULE_NAME ("exmutex") 51 52/* Local prototypes */ 53 54static void 55acpi_ex_link_mutex ( 56 union acpi_operand_object *obj_desc, 57 struct acpi_thread_state *thread); 58 59 60/******************************************************************************* 61 * 62 * FUNCTION: acpi_ex_unlink_mutex 63 * 64 * PARAMETERS: obj_desc - The mutex to be unlinked 65 * 66 * RETURN: None 67 * 68 * DESCRIPTION: Remove a mutex from the "acquired_mutex" list 69 * 70 ******************************************************************************/ 71 72void 73acpi_ex_unlink_mutex ( 74 union acpi_operand_object *obj_desc) 75{ 76 struct acpi_thread_state *thread = obj_desc->mutex.owner_thread; 77 78 79 if (!thread) { 80 return; 81 } 82 83 /* Doubly linked list */ 84 85 if (obj_desc->mutex.next) { 86 (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev; 87 } 88 89 if (obj_desc->mutex.prev) { 90 (obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next; 91 } 92 else { 93 thread->acquired_mutex_list = obj_desc->mutex.next; 94 } 95} 96 97 98/******************************************************************************* 99 * 100 * FUNCTION: acpi_ex_link_mutex 101 * 102 * PARAMETERS: obj_desc - The mutex to be linked 103 * Thread - Current executing thread object 104 * 105 * RETURN: None 106 * 107 * DESCRIPTION: Add a mutex to the "acquired_mutex" list for this walk 108 * 109 ******************************************************************************/ 110 111static void 112acpi_ex_link_mutex ( 113 union acpi_operand_object *obj_desc, 114 struct acpi_thread_state *thread) 115{ 116 union acpi_operand_object *list_head; 117 118 119 list_head = thread->acquired_mutex_list; 120 121 /* This object will be the first object in the list */ 122 123 obj_desc->mutex.prev = NULL; 124 obj_desc->mutex.next = list_head; 125 126 /* Update old first object to point back to this object */ 127 128 if (list_head) { 129 list_head->mutex.prev = obj_desc; 130 } 131 132 /* Update list head */ 133 134 thread->acquired_mutex_list = obj_desc; 135} 136 137 138/******************************************************************************* 139 * 140 * FUNCTION: acpi_ex_acquire_mutex 141 * 142 * PARAMETERS: time_desc - Timeout integer 143 * obj_desc - Mutex object 144 * walk_state - Current method execution state 145 * 146 * RETURN: Status 147 * 148 * DESCRIPTION: Acquire an AML mutex 149 * 150 ******************************************************************************/ 151 152acpi_status 153acpi_ex_acquire_mutex ( 154 union acpi_operand_object *time_desc, 155 union acpi_operand_object *obj_desc, 156 struct acpi_walk_state *walk_state) 157{ 158 acpi_status status; 159 160 161 ACPI_FUNCTION_TRACE_PTR ("ex_acquire_mutex", obj_desc); 162 163 164 if (!obj_desc) { 165 return_ACPI_STATUS (AE_BAD_PARAMETER); 166 } 167 168 /* Sanity check -- we must have a valid thread ID */ 169 170 if (!walk_state->thread) { 171 ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], null thread info\n", 172 acpi_ut_get_node_name (obj_desc->mutex.node))); 173 return_ACPI_STATUS (AE_AML_INTERNAL); 174 } 175 176 /* 177 * Current Sync must be less than or equal to the sync level of the 178 * mutex. This mechanism provides some deadlock prevention 179 */ 180 if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { 181 ACPI_REPORT_ERROR (( 182 "Cannot acquire Mutex [%4.4s], incorrect sync_level\n", 183 acpi_ut_get_node_name (obj_desc->mutex.node))); 184 return_ACPI_STATUS (AE_AML_MUTEX_ORDER); 185 } 186 187 /* Support for multiple acquires by the owning thread */ 188 189 if (obj_desc->mutex.owner_thread) { 190 /* Special case for Global Lock, allow all threads */ 191 192 if ((obj_desc->mutex.owner_thread->thread_id == 193 walk_state->thread->thread_id) || 194 (obj_desc->mutex.semaphore == 195 acpi_gbl_global_lock_semaphore)) { 196 /* 197 * The mutex is already owned by this thread, 198 * just increment the acquisition depth 199 */ 200 obj_desc->mutex.acquisition_depth++; 201 return_ACPI_STATUS (AE_OK); 202 } 203 } 204 205 /* Acquire the mutex, wait if necessary */ 206 207 status = acpi_ex_system_acquire_mutex (time_desc, obj_desc); 208 if (ACPI_FAILURE (status)) { 209 /* Includes failure from a timeout on time_desc */ 210 211 return_ACPI_STATUS (status); 212 } 213 214 /* Have the mutex: update mutex and walk info and save the sync_level */ 215 216 obj_desc->mutex.owner_thread = walk_state->thread; 217 obj_desc->mutex.acquisition_depth = 1; 218 obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level; 219 220 walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; 221 222 /* Link the mutex to the current thread for force-unlock at method exit */ 223 224 acpi_ex_link_mutex (obj_desc, walk_state->thread); 225 226 return_ACPI_STATUS (AE_OK); 227} 228 229 230/******************************************************************************* 231 * 232 * FUNCTION: acpi_ex_release_mutex 233 * 234 * PARAMETERS: obj_desc - The object descriptor for this op 235 * walk_state - Current method execution state 236 * 237 * RETURN: Status 238 * 239 * DESCRIPTION: Release a previously acquired Mutex. 240 * 241 ******************************************************************************/ 242 243acpi_status 244acpi_ex_release_mutex ( 245 union acpi_operand_object *obj_desc, 246 struct acpi_walk_state *walk_state) 247{ 248 acpi_status status; 249 250 251 ACPI_FUNCTION_TRACE ("ex_release_mutex"); 252 253 254 if (!obj_desc) { 255 return_ACPI_STATUS (AE_BAD_PARAMETER); 256 } 257 258 /* The mutex must have been previously acquired in order to release it */ 259 260 if (!obj_desc->mutex.owner_thread) { 261 ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], not acquired\n", 262 acpi_ut_get_node_name (obj_desc->mutex.node))); 263 return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED); 264 } 265 266 /* Sanity check -- we must have a valid thread ID */ 267 268 if (!walk_state->thread) { 269 ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], null thread info\n", 270 acpi_ut_get_node_name (obj_desc->mutex.node))); 271 return_ACPI_STATUS (AE_AML_INTERNAL); 272 } 273 274 /* 275 * The Mutex is owned, but this thread must be the owner. 276 * Special case for Global Lock, any thread can release 277 */ 278 if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) && 279 (obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) { 280 ACPI_REPORT_ERROR (( 281 "Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n", 282 walk_state->thread->thread_id, 283 acpi_ut_get_node_name (obj_desc->mutex.node), 284 obj_desc->mutex.owner_thread->thread_id)); 285 return_ACPI_STATUS (AE_AML_NOT_OWNER); 286 } 287 288 /* 289 * The sync level of the mutex must be less than or 290 * equal to the current sync level 291 */ 292 if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { 293 ACPI_REPORT_ERROR (( 294 "Cannot release Mutex [%4.4s], incorrect sync_level\n", 295 acpi_ut_get_node_name (obj_desc->mutex.node))); 296 return_ACPI_STATUS (AE_AML_MUTEX_ORDER); 297 } 298 299 /* Match multiple Acquires with multiple Releases */ 300 301 obj_desc->mutex.acquisition_depth--; 302 if (obj_desc->mutex.acquisition_depth != 0) { 303 /* Just decrement the depth and return */ 304 305 return_ACPI_STATUS (AE_OK); 306 } 307 308 /* Unlink the mutex from the owner's list */ 309 310 acpi_ex_unlink_mutex (obj_desc); 311 312 /* Release the mutex */ 313 314 status = acpi_ex_system_release_mutex (obj_desc); 315 316 /* Update the mutex and walk state, restore sync_level before acquire */ 317 318 obj_desc->mutex.owner_thread = NULL; 319 walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level; 320 321 return_ACPI_STATUS (status); 322} 323 324 325/******************************************************************************* 326 * 327 * FUNCTION: acpi_ex_release_all_mutexes 328 * 329 * PARAMETERS: Thread - Current executing thread object 330 * 331 * RETURN: Status 332 * 333 * DESCRIPTION: Release all mutexes held by this thread 334 * 335 ******************************************************************************/ 336 337void 338acpi_ex_release_all_mutexes ( 339 struct acpi_thread_state *thread) 340{ 341 union acpi_operand_object *next = thread->acquired_mutex_list; 342 union acpi_operand_object *this; 343 acpi_status status; 344 345 346 ACPI_FUNCTION_ENTRY (); 347 348 349 /* Traverse the list of owned mutexes, releasing each one */ 350 351 while (next) { 352 this = next; 353 next = this->mutex.next; 354 355 this->mutex.acquisition_depth = 1; 356 this->mutex.prev = NULL; 357 this->mutex.next = NULL; 358 359 /* Release the mutex */ 360 361 status = acpi_ex_system_release_mutex (this); 362 if (ACPI_FAILURE (status)) { 363 continue; 364 } 365 366 /* Mark mutex unowned */ 367 368 this->mutex.owner_thread = NULL; 369 370 /* Update Thread sync_level (Last mutex is the important one) */ 371 372 thread->current_sync_level = this->mutex.original_sync_level; 373 } 374} 375 376