Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /*******************************************************************************
0003  *
0004  * Module Name: utmutex - local mutex support
0005  *
0006  ******************************************************************************/
0007 
0008 #include <acpi/acpi.h>
0009 #include "accommon.h"
0010 
0011 #define _COMPONENT          ACPI_UTILITIES
0012 ACPI_MODULE_NAME("utmutex")
0013 
0014 /* Local prototypes */
0015 static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id);
0016 
0017 static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id);
0018 
0019 /*******************************************************************************
0020  *
0021  * FUNCTION:    acpi_ut_mutex_initialize
0022  *
0023  * PARAMETERS:  None.
0024  *
0025  * RETURN:      Status
0026  *
0027  * DESCRIPTION: Create the system mutex objects. This includes mutexes,
0028  *              spin locks, and reader/writer locks.
0029  *
0030  ******************************************************************************/
0031 
0032 acpi_status acpi_ut_mutex_initialize(void)
0033 {
0034     u32 i;
0035     acpi_status status;
0036 
0037     ACPI_FUNCTION_TRACE(ut_mutex_initialize);
0038 
0039     /* Create each of the predefined mutex objects */
0040 
0041     for (i = 0; i < ACPI_NUM_MUTEX; i++) {
0042         status = acpi_ut_create_mutex(i);
0043         if (ACPI_FAILURE(status)) {
0044             return_ACPI_STATUS(status);
0045         }
0046     }
0047 
0048     /* Create the spinlocks for use at interrupt level or for speed */
0049 
0050     status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
0051     if (ACPI_FAILURE (status)) {
0052         return_ACPI_STATUS (status);
0053     }
0054 
0055     status = acpi_os_create_raw_lock(&acpi_gbl_hardware_lock);
0056     if (ACPI_FAILURE (status)) {
0057         return_ACPI_STATUS (status);
0058     }
0059 
0060     status = acpi_os_create_lock(&acpi_gbl_reference_count_lock);
0061     if (ACPI_FAILURE(status)) {
0062         return_ACPI_STATUS(status);
0063     }
0064 
0065     /* Mutex for _OSI support */
0066 
0067     status = acpi_os_create_mutex(&acpi_gbl_osi_mutex);
0068     if (ACPI_FAILURE(status)) {
0069         return_ACPI_STATUS(status);
0070     }
0071 
0072     /* Create the reader/writer lock for namespace access */
0073 
0074     status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock);
0075     if (ACPI_FAILURE(status)) {
0076         return_ACPI_STATUS(status);
0077     }
0078 
0079     return_ACPI_STATUS(status);
0080 }
0081 
0082 /*******************************************************************************
0083  *
0084  * FUNCTION:    acpi_ut_mutex_terminate
0085  *
0086  * PARAMETERS:  None.
0087  *
0088  * RETURN:      None.
0089  *
0090  * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes,
0091  *              spin locks, and reader/writer locks.
0092  *
0093  ******************************************************************************/
0094 
0095 void acpi_ut_mutex_terminate(void)
0096 {
0097     u32 i;
0098 
0099     ACPI_FUNCTION_TRACE(ut_mutex_terminate);
0100 
0101     /* Delete each predefined mutex object */
0102 
0103     for (i = 0; i < ACPI_NUM_MUTEX; i++) {
0104         acpi_ut_delete_mutex(i);
0105     }
0106 
0107     acpi_os_delete_mutex(acpi_gbl_osi_mutex);
0108 
0109     /* Delete the spinlocks */
0110 
0111     acpi_os_delete_lock(acpi_gbl_gpe_lock);
0112     acpi_os_delete_raw_lock(acpi_gbl_hardware_lock);
0113     acpi_os_delete_lock(acpi_gbl_reference_count_lock);
0114 
0115     /* Delete the reader/writer lock */
0116 
0117     acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock);
0118     return_VOID;
0119 }
0120 
0121 /*******************************************************************************
0122  *
0123  * FUNCTION:    acpi_ut_create_mutex
0124  *
0125  * PARAMETERS:  mutex_ID        - ID of the mutex to be created
0126  *
0127  * RETURN:      Status
0128  *
0129  * DESCRIPTION: Create a mutex object.
0130  *
0131  ******************************************************************************/
0132 
0133 static acpi_status acpi_ut_create_mutex(acpi_mutex_handle mutex_id)
0134 {
0135     acpi_status status = AE_OK;
0136 
0137     ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id);
0138 
0139     if (!acpi_gbl_mutex_info[mutex_id].mutex) {
0140         status =
0141             acpi_os_create_mutex(&acpi_gbl_mutex_info[mutex_id].mutex);
0142         acpi_gbl_mutex_info[mutex_id].thread_id =
0143             ACPI_MUTEX_NOT_ACQUIRED;
0144         acpi_gbl_mutex_info[mutex_id].use_count = 0;
0145     }
0146 
0147     return_ACPI_STATUS(status);
0148 }
0149 
0150 /*******************************************************************************
0151  *
0152  * FUNCTION:    acpi_ut_delete_mutex
0153  *
0154  * PARAMETERS:  mutex_ID        - ID of the mutex to be deleted
0155  *
0156  * RETURN:      Status
0157  *
0158  * DESCRIPTION: Delete a mutex object.
0159  *
0160  ******************************************************************************/
0161 
0162 static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)
0163 {
0164 
0165     ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id);
0166 
0167     acpi_os_delete_mutex(acpi_gbl_mutex_info[mutex_id].mutex);
0168 
0169     acpi_gbl_mutex_info[mutex_id].mutex = NULL;
0170     acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
0171 
0172     return_VOID;
0173 }
0174 
0175 /*******************************************************************************
0176  *
0177  * FUNCTION:    acpi_ut_acquire_mutex
0178  *
0179  * PARAMETERS:  mutex_ID        - ID of the mutex to be acquired
0180  *
0181  * RETURN:      Status
0182  *
0183  * DESCRIPTION: Acquire a mutex object.
0184  *
0185  ******************************************************************************/
0186 
0187 acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
0188 {
0189     acpi_status status;
0190     acpi_thread_id this_thread_id;
0191 
0192     ACPI_FUNCTION_NAME(ut_acquire_mutex);
0193 
0194     if (mutex_id > ACPI_MAX_MUTEX) {
0195         return (AE_BAD_PARAMETER);
0196     }
0197 
0198     this_thread_id = acpi_os_get_thread_id();
0199 
0200 #ifdef ACPI_MUTEX_DEBUG
0201     {
0202         u32 i;
0203         /*
0204          * Mutex debug code, for internal debugging only.
0205          *
0206          * Deadlock prevention. Check if this thread owns any mutexes of value
0207          * greater than or equal to this one. If so, the thread has violated
0208          * the mutex ordering rule. This indicates a coding error somewhere in
0209          * the ACPI subsystem code.
0210          */
0211         for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
0212             if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
0213                 if (i == mutex_id) {
0214                     ACPI_ERROR((AE_INFO,
0215                             "Mutex [%s] already acquired by this thread [%u]",
0216                             acpi_ut_get_mutex_name
0217                             (mutex_id),
0218                             (u32)this_thread_id));
0219 
0220                     return (AE_ALREADY_ACQUIRED);
0221                 }
0222 
0223                 ACPI_ERROR((AE_INFO,
0224                         "Invalid acquire order: Thread %u owns [%s], wants [%s]",
0225                         (u32)this_thread_id,
0226                         acpi_ut_get_mutex_name(i),
0227                         acpi_ut_get_mutex_name(mutex_id)));
0228 
0229                 return (AE_ACQUIRE_DEADLOCK);
0230             }
0231         }
0232     }
0233 #endif
0234 
0235     ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
0236               "Thread %u attempting to acquire Mutex [%s]\n",
0237               (u32)this_thread_id,
0238               acpi_ut_get_mutex_name(mutex_id)));
0239 
0240     status =
0241         acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
0242                   ACPI_WAIT_FOREVER);
0243     if (ACPI_SUCCESS(status)) {
0244         ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
0245                   "Thread %u acquired Mutex [%s]\n",
0246                   (u32)this_thread_id,
0247                   acpi_ut_get_mutex_name(mutex_id)));
0248 
0249         acpi_gbl_mutex_info[mutex_id].use_count++;
0250         acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
0251     } else {
0252         ACPI_EXCEPTION((AE_INFO, status,
0253                 "Thread %u could not acquire Mutex [%s] (0x%X)",
0254                 (u32)this_thread_id,
0255                 acpi_ut_get_mutex_name(mutex_id), mutex_id));
0256     }
0257 
0258     return (status);
0259 }
0260 
0261 /*******************************************************************************
0262  *
0263  * FUNCTION:    acpi_ut_release_mutex
0264  *
0265  * PARAMETERS:  mutex_ID        - ID of the mutex to be released
0266  *
0267  * RETURN:      Status
0268  *
0269  * DESCRIPTION: Release a mutex object.
0270  *
0271  ******************************************************************************/
0272 
0273 acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
0274 {
0275     ACPI_FUNCTION_NAME(ut_release_mutex);
0276 
0277     ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n",
0278               (u32)acpi_os_get_thread_id(),
0279               acpi_ut_get_mutex_name(mutex_id)));
0280 
0281     if (mutex_id > ACPI_MAX_MUTEX) {
0282         return (AE_BAD_PARAMETER);
0283     }
0284 
0285     /*
0286      * Mutex must be acquired in order to release it!
0287      */
0288     if (acpi_gbl_mutex_info[mutex_id].thread_id == ACPI_MUTEX_NOT_ACQUIRED) {
0289         ACPI_ERROR((AE_INFO,
0290                 "Mutex [%s] (0x%X) is not acquired, cannot release",
0291                 acpi_ut_get_mutex_name(mutex_id), mutex_id));
0292 
0293         return (AE_NOT_ACQUIRED);
0294     }
0295 #ifdef ACPI_MUTEX_DEBUG
0296     {
0297         u32 i;
0298         /*
0299          * Mutex debug code, for internal debugging only.
0300          *
0301          * Deadlock prevention. Check if this thread owns any mutexes of value
0302          * greater than this one. If so, the thread has violated the mutex
0303          * ordering rule. This indicates a coding error somewhere in
0304          * the ACPI subsystem code.
0305          */
0306         for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
0307             if (acpi_gbl_mutex_info[i].thread_id ==
0308                 acpi_os_get_thread_id()) {
0309                 if (i == mutex_id) {
0310                     continue;
0311                 }
0312 
0313                 ACPI_ERROR((AE_INFO,
0314                         "Invalid release order: owns [%s], releasing [%s]",
0315                         acpi_ut_get_mutex_name(i),
0316                         acpi_ut_get_mutex_name(mutex_id)));
0317 
0318                 return (AE_RELEASE_DEADLOCK);
0319             }
0320         }
0321     }
0322 #endif
0323 
0324     /* Mark unlocked FIRST */
0325 
0326     acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
0327 
0328     acpi_os_release_mutex(acpi_gbl_mutex_info[mutex_id].mutex);
0329     return (AE_OK);
0330 }