Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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