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