linux-old/drivers/acpi/executer/exmutex.c
<<
>>
Prefs
   1
   2/******************************************************************************
   3 *
   4 * Module Name: exmutex - ASL Mutex Acquire/Release functions
   5 *
   6 *****************************************************************************/
   7
   8/*
   9 * Copyright (C) 2000 - 2004, 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
  53/*******************************************************************************
  54 *
  55 * FUNCTION:    acpi_ex_unlink_mutex
  56 *
  57 * PARAMETERS:  *obj_desc           - The mutex to be unlinked
  58 *
  59 * RETURN:      Status
  60 *
  61 * DESCRIPTION: Remove a mutex from the "acquired_mutex" list
  62 *
  63 ******************************************************************************/
  64
  65void
  66acpi_ex_unlink_mutex (
  67        union acpi_operand_object       *obj_desc)
  68{
  69        struct acpi_thread_state        *thread = obj_desc->mutex.owner_thread;
  70
  71
  72        if (!thread) {
  73                return;
  74        }
  75
  76        if (obj_desc->mutex.next) {
  77                (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev;
  78        }
  79
  80        if (obj_desc->mutex.prev) {
  81                (obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next;
  82        }
  83        else {
  84                thread->acquired_mutex_list = obj_desc->mutex.next;
  85        }
  86}
  87
  88
  89/*******************************************************************************
  90 *
  91 * FUNCTION:    acpi_ex_link_mutex
  92 *
  93 * PARAMETERS:  *obj_desc           - The mutex to be linked
  94 *              *list_head          - head of the "acquired_mutex" list
  95 *
  96 * RETURN:      Status
  97 *
  98 * DESCRIPTION: Add a mutex to the "acquired_mutex" list for this walk
  99 *
 100 ******************************************************************************/
 101
 102void
 103acpi_ex_link_mutex (
 104        union acpi_operand_object       *obj_desc,
 105        struct acpi_thread_state        *thread)
 106{
 107        union acpi_operand_object       *list_head;
 108
 109
 110        list_head = thread->acquired_mutex_list;
 111
 112        /* This object will be the first object in the list */
 113
 114        obj_desc->mutex.prev = NULL;
 115        obj_desc->mutex.next = list_head;
 116
 117        /* Update old first object to point back to this object */
 118
 119        if (list_head) {
 120                list_head->mutex.prev = obj_desc;
 121        }
 122
 123        /* Update list head */
 124
 125        thread->acquired_mutex_list = obj_desc;
 126}
 127
 128
 129/*******************************************************************************
 130 *
 131 * FUNCTION:    acpi_ex_acquire_mutex
 132 *
 133 * PARAMETERS:  *time_desc          - The 'time to delay' object descriptor
 134 *              *obj_desc           - The object descriptor for this op
 135 *
 136 * RETURN:      Status
 137 *
 138 * DESCRIPTION: Acquire an AML mutex
 139 *
 140 ******************************************************************************/
 141
 142acpi_status
 143acpi_ex_acquire_mutex (
 144        union acpi_operand_object       *time_desc,
 145        union acpi_operand_object       *obj_desc,
 146        struct acpi_walk_state          *walk_state)
 147{
 148        acpi_status                     status;
 149
 150
 151        ACPI_FUNCTION_TRACE_PTR ("ex_acquire_mutex", obj_desc);
 152
 153
 154        if (!obj_desc) {
 155                return_ACPI_STATUS (AE_BAD_PARAMETER);
 156        }
 157
 158        /* Sanity check -- we must have a valid thread ID */
 159
 160        if (!walk_state->thread) {
 161                ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], null thread info\n",
 162                                acpi_ut_get_node_name (obj_desc->mutex.node)));
 163                return_ACPI_STATUS (AE_AML_INTERNAL);
 164        }
 165
 166        /*
 167         * Current Sync must be less than or equal to the sync level of the
 168         * mutex.  This mechanism provides some deadlock prevention
 169         */
 170        if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
 171                ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], incorrect sync_level\n",
 172                                acpi_ut_get_node_name (obj_desc->mutex.node)));
 173                return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
 174        }
 175
 176        /*
 177         * Support for multiple acquires by the owning thread
 178         */
 179        if (obj_desc->mutex.owner_thread) {
 180                /* Special case for Global Lock, allow all threads */
 181
 182                if ((obj_desc->mutex.owner_thread->thread_id == walk_state->thread->thread_id) ||
 183                        (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore)) {
 184                        /*
 185                         * The mutex is already owned by this thread,
 186                         * just increment the acquisition depth
 187                         */
 188                        obj_desc->mutex.acquisition_depth++;
 189                        return_ACPI_STATUS (AE_OK);
 190                }
 191        }
 192
 193        /* Acquire the mutex, wait if necessary */
 194
 195        status = acpi_ex_system_acquire_mutex (time_desc, obj_desc);
 196        if (ACPI_FAILURE (status)) {
 197                /* Includes failure from a timeout on time_desc */
 198
 199                return_ACPI_STATUS (status);
 200        }
 201
 202        /* Have the mutex, update mutex and walk info */
 203
 204        obj_desc->mutex.owner_thread    = walk_state->thread;
 205        obj_desc->mutex.acquisition_depth = 1;
 206
 207        walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
 208
 209        /* Link the mutex to the current thread for force-unlock at method exit */
 210
 211        acpi_ex_link_mutex (obj_desc, walk_state->thread);
 212
 213        return_ACPI_STATUS (AE_OK);
 214}
 215
 216
 217/*******************************************************************************
 218 *
 219 * FUNCTION:    acpi_ex_release_mutex
 220 *
 221 * PARAMETERS:  *obj_desc           - The object descriptor for this op
 222 *
 223 * RETURN:      Status
 224 *
 225 * DESCRIPTION: Release a previously acquired Mutex.
 226 *
 227 ******************************************************************************/
 228
 229acpi_status
 230acpi_ex_release_mutex (
 231        union acpi_operand_object       *obj_desc,
 232        struct acpi_walk_state          *walk_state)
 233{
 234        acpi_status                     status;
 235
 236
 237        ACPI_FUNCTION_TRACE ("ex_release_mutex");
 238
 239
 240        if (!obj_desc) {
 241                return_ACPI_STATUS (AE_BAD_PARAMETER);
 242        }
 243
 244        /* The mutex must have been previously acquired in order to release it */
 245
 246        if (!obj_desc->mutex.owner_thread) {
 247                ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], not acquired\n",
 248                                acpi_ut_get_node_name (obj_desc->mutex.node)));
 249                return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED);
 250        }
 251
 252        /* Sanity check -- we must have a valid thread ID */
 253
 254        if (!walk_state->thread) {
 255                ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], null thread info\n",
 256                                acpi_ut_get_node_name (obj_desc->mutex.node)));
 257                return_ACPI_STATUS (AE_AML_INTERNAL);
 258        }
 259
 260        /*
 261         * The Mutex is owned, but this thread must be the owner.
 262         * Special case for Global Lock, any thread can release
 263         */
 264        if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) &&
 265                (obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) {
 266                ACPI_REPORT_ERROR ((
 267                        "Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n",
 268                        walk_state->thread->thread_id,
 269                        acpi_ut_get_node_name (obj_desc->mutex.node),
 270                        obj_desc->mutex.owner_thread->thread_id));
 271                return_ACPI_STATUS (AE_AML_NOT_OWNER);
 272        }
 273
 274        /*
 275         * The sync level of the mutex must be less than or
 276         * equal to the current sync level
 277         */
 278        if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
 279                ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], incorrect sync_level\n",
 280                                acpi_ut_get_node_name (obj_desc->mutex.node)));
 281                return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
 282        }
 283
 284        /*
 285         * Match multiple Acquires with multiple Releases
 286         */
 287        obj_desc->mutex.acquisition_depth--;
 288        if (obj_desc->mutex.acquisition_depth != 0) {
 289                /* Just decrement the depth and return */
 290
 291                return_ACPI_STATUS (AE_OK);
 292        }
 293
 294        /* Unlink the mutex from the owner's list */
 295
 296        acpi_ex_unlink_mutex (obj_desc);
 297
 298        /* Release the mutex */
 299
 300        status = acpi_ex_system_release_mutex (obj_desc);
 301
 302        /* Update the mutex and walk state */
 303
 304        obj_desc->mutex.owner_thread = NULL;
 305        walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
 306
 307        return_ACPI_STATUS (status);
 308}
 309
 310
 311/*******************************************************************************
 312 *
 313 * FUNCTION:    acpi_ex_release_all_mutexes
 314 *
 315 * PARAMETERS:  *mutex_list           - Head of the mutex list
 316 *
 317 * RETURN:      Status
 318 *
 319 * DESCRIPTION: Release all mutexes in the list
 320 *
 321 ******************************************************************************/
 322
 323void
 324acpi_ex_release_all_mutexes (
 325        struct acpi_thread_state        *thread)
 326{
 327        union acpi_operand_object       *next = thread->acquired_mutex_list;
 328        union acpi_operand_object       *this;
 329        acpi_status                     status;
 330
 331
 332        ACPI_FUNCTION_ENTRY ();
 333
 334
 335        /*
 336         * Traverse the list of owned mutexes, releasing each one.
 337         */
 338        while (next) {
 339                this = next;
 340                next = this->mutex.next;
 341
 342                this->mutex.acquisition_depth = 1;
 343                this->mutex.prev             = NULL;
 344                this->mutex.next             = NULL;
 345
 346                 /* Release the mutex */
 347
 348                status = acpi_ex_system_release_mutex (this);
 349                if (ACPI_FAILURE (status)) {
 350                        continue;
 351                }
 352
 353                /* Mark mutex unowned */
 354
 355                this->mutex.owner_thread     = NULL;
 356        }
 357}
 358
 359
 360
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.