Subversion Repositories Kolibri OS

Rev

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

  1. /******************************************************************************
  2.  *
  3.  * Module Name: exmutex - ASL Mutex Acquire/Release functions
  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. #include "acinterp.h"
  47. #include "acevents.h"
  48.  
  49. #define _COMPONENT          ACPI_EXECUTER
  50. ACPI_MODULE_NAME("exmutex")
  51.  
  52. /* Local prototypes */
  53. static void
  54. acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
  55.                    struct acpi_thread_state *thread);
  56.  
  57. /*******************************************************************************
  58.  *
  59.  * FUNCTION:    acpi_ex_unlink_mutex
  60.  *
  61.  * PARAMETERS:  obj_desc            - The mutex to be unlinked
  62.  *
  63.  * RETURN:      None
  64.  *
  65.  * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list
  66.  *
  67.  ******************************************************************************/
  68.  
  69. void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
  70. {
  71.         struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
  72.  
  73.         if (!thread) {
  74.                 return;
  75.         }
  76.  
  77.         /* Doubly linked list */
  78.  
  79.         if (obj_desc->mutex.next) {
  80.                 (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev;
  81.         }
  82.  
  83.         if (obj_desc->mutex.prev) {
  84.                 (obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next;
  85.  
  86.                 /*
  87.                  * Migrate the previous sync level associated with this mutex to
  88.                  * the previous mutex on the list so that it may be preserved.
  89.                  * This handles the case where several mutexes have been acquired
  90.                  * at the same level, but are not released in opposite order.
  91.                  */
  92.                 (obj_desc->mutex.prev)->mutex.original_sync_level =
  93.                     obj_desc->mutex.original_sync_level;
  94.         } else {
  95.                 thread->acquired_mutex_list = obj_desc->mutex.next;
  96.         }
  97. }
  98.  
  99. /*******************************************************************************
  100.  *
  101.  * FUNCTION:    acpi_ex_link_mutex
  102.  *
  103.  * PARAMETERS:  obj_desc            - The mutex to be linked
  104.  *              thread              - Current executing thread object
  105.  *
  106.  * RETURN:      None
  107.  *
  108.  * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk
  109.  *
  110.  ******************************************************************************/
  111.  
  112. static void
  113. acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
  114.                    struct acpi_thread_state *thread)
  115. {
  116.         union acpi_operand_object *list_head;
  117.  
  118.         list_head = thread->acquired_mutex_list;
  119.  
  120.         /* This object will be the first object in the list */
  121.  
  122.         obj_desc->mutex.prev = NULL;
  123.         obj_desc->mutex.next = list_head;
  124.  
  125.         /* Update old first object to point back to this object */
  126.  
  127.         if (list_head) {
  128.                 list_head->mutex.prev = obj_desc;
  129.         }
  130.  
  131.         /* Update list head */
  132.  
  133.         thread->acquired_mutex_list = obj_desc;
  134. }
  135.  
  136. /*******************************************************************************
  137.  *
  138.  * FUNCTION:    acpi_ex_acquire_mutex_object
  139.  *
  140.  * PARAMETERS:  timeout             - Timeout in milliseconds
  141.  *              obj_desc            - Mutex object
  142.  *              thread_id           - Current thread state
  143.  *
  144.  * RETURN:      Status
  145.  *
  146.  * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common
  147.  *              path that supports multiple acquires by the same thread.
  148.  *
  149.  * MUTEX:       Interpreter must be locked
  150.  *
  151.  * NOTE: This interface is called from three places:
  152.  * 1) From acpi_ex_acquire_mutex, via an AML Acquire() operator
  153.  * 2) From acpi_ex_acquire_global_lock when an AML Field access requires the
  154.  *    global lock
  155.  * 3) From the external interface, acpi_acquire_global_lock
  156.  *
  157.  ******************************************************************************/
  158.  
  159. acpi_status
  160. acpi_ex_acquire_mutex_object(u16 timeout,
  161.                              union acpi_operand_object *obj_desc,
  162.                              acpi_thread_id thread_id)
  163. {
  164.         acpi_status status;
  165.  
  166.         ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc);
  167.  
  168.         if (!obj_desc) {
  169.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  170.         }
  171.  
  172.         /* Support for multiple acquires by the owning thread */
  173.  
  174.         if (obj_desc->mutex.thread_id == thread_id) {
  175.                 /*
  176.                  * The mutex is already owned by this thread, just increment the
  177.                  * acquisition depth
  178.                  */
  179.                 obj_desc->mutex.acquisition_depth++;
  180.                 return_ACPI_STATUS(AE_OK);
  181.         }
  182.  
  183.         /* Acquire the mutex, wait if necessary. Special case for Global Lock */
  184.  
  185.         if (obj_desc == acpi_gbl_global_lock_mutex) {
  186.                 status = acpi_ev_acquire_global_lock(timeout);
  187.         } else {
  188.                 status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex,
  189.                                                    timeout);
  190.         }
  191.  
  192.         if (ACPI_FAILURE(status)) {
  193.  
  194.                 /* Includes failure from a timeout on time_desc */
  195.  
  196.                 return_ACPI_STATUS(status);
  197.         }
  198.  
  199.         /* Acquired the mutex: update mutex object */
  200.  
  201.         obj_desc->mutex.thread_id = thread_id;
  202.         obj_desc->mutex.acquisition_depth = 1;
  203.         obj_desc->mutex.original_sync_level = 0;
  204.         obj_desc->mutex.owner_thread = NULL;    /* Used only for AML Acquire() */
  205.  
  206.         return_ACPI_STATUS(AE_OK);
  207. }
  208.  
  209. /*******************************************************************************
  210.  *
  211.  * FUNCTION:    acpi_ex_acquire_mutex
  212.  *
  213.  * PARAMETERS:  time_desc           - Timeout integer
  214.  *              obj_desc            - Mutex object
  215.  *              walk_state          - Current method execution state
  216.  *
  217.  * RETURN:      Status
  218.  *
  219.  * DESCRIPTION: Acquire an AML mutex
  220.  *
  221.  ******************************************************************************/
  222.  
  223. acpi_status
  224. acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
  225.                       union acpi_operand_object *obj_desc,
  226.                       struct acpi_walk_state *walk_state)
  227. {
  228.         acpi_status status;
  229.  
  230.         ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex, obj_desc);
  231.  
  232.         if (!obj_desc) {
  233.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  234.         }
  235.  
  236.         /* Must have a valid thread state struct */
  237.  
  238.         if (!walk_state->thread) {
  239.                 ACPI_ERROR((AE_INFO,
  240.                             "Cannot acquire Mutex [%4.4s], null thread info",
  241.                             acpi_ut_get_node_name(obj_desc->mutex.node)));
  242.                 return_ACPI_STATUS(AE_AML_INTERNAL);
  243.         }
  244.  
  245.         /*
  246.          * Current sync level must be less than or equal to the sync level of the
  247.          * mutex. This mechanism provides some deadlock prevention
  248.          */
  249.         if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
  250.                 ACPI_ERROR((AE_INFO,
  251.                             "Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%u)",
  252.                             acpi_ut_get_node_name(obj_desc->mutex.node),
  253.                             walk_state->thread->current_sync_level));
  254.                 return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
  255.         }
  256.  
  257.         status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value,
  258.                                               obj_desc,
  259.                                               walk_state->thread->thread_id);
  260.         if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) {
  261.  
  262.                 /* Save Thread object, original/current sync levels */
  263.  
  264.                 obj_desc->mutex.owner_thread = walk_state->thread;
  265.                 obj_desc->mutex.original_sync_level =
  266.                     walk_state->thread->current_sync_level;
  267.                 walk_state->thread->current_sync_level =
  268.                     obj_desc->mutex.sync_level;
  269.  
  270.                 /* Link the mutex to the current thread for force-unlock at method exit */
  271.  
  272.                 acpi_ex_link_mutex(obj_desc, walk_state->thread);
  273.         }
  274.  
  275.         return_ACPI_STATUS(status);
  276. }
  277.  
  278. /*******************************************************************************
  279.  *
  280.  * FUNCTION:    acpi_ex_release_mutex_object
  281.  *
  282.  * PARAMETERS:  obj_desc            - The object descriptor for this op
  283.  *
  284.  * RETURN:      Status
  285.  *
  286.  * DESCRIPTION: Release a previously acquired Mutex, low level interface.
  287.  *              Provides a common path that supports multiple releases (after
  288.  *              previous multiple acquires) by the same thread.
  289.  *
  290.  * MUTEX:       Interpreter must be locked
  291.  *
  292.  * NOTE: This interface is called from three places:
  293.  * 1) From acpi_ex_release_mutex, via an AML Acquire() operator
  294.  * 2) From acpi_ex_release_global_lock when an AML Field access requires the
  295.  *    global lock
  296.  * 3) From the external interface, acpi_release_global_lock
  297.  *
  298.  ******************************************************************************/
  299.  
  300. acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
  301. {
  302.         acpi_status status = AE_OK;
  303.  
  304.         ACPI_FUNCTION_TRACE(ex_release_mutex_object);
  305.  
  306.         if (obj_desc->mutex.acquisition_depth == 0) {
  307.                 return_ACPI_STATUS(AE_NOT_ACQUIRED);
  308.         }
  309.  
  310.         /* Match multiple Acquires with multiple Releases */
  311.  
  312.         obj_desc->mutex.acquisition_depth--;
  313.         if (obj_desc->mutex.acquisition_depth != 0) {
  314.  
  315.                 /* Just decrement the depth and return */
  316.  
  317.                 return_ACPI_STATUS(AE_OK);
  318.         }
  319.  
  320.         if (obj_desc->mutex.owner_thread) {
  321.  
  322.                 /* Unlink the mutex from the owner's list */
  323.  
  324.                 acpi_ex_unlink_mutex(obj_desc);
  325.                 obj_desc->mutex.owner_thread = NULL;
  326.         }
  327.  
  328.         /* Release the mutex, special case for Global Lock */
  329.  
  330.         if (obj_desc == acpi_gbl_global_lock_mutex) {
  331.                 status = acpi_ev_release_global_lock();
  332.         } else {
  333.                 acpi_os_release_mutex(obj_desc->mutex.os_mutex);
  334.         }
  335.  
  336.         /* Clear mutex info */
  337.  
  338.         obj_desc->mutex.thread_id = 0;
  339.         return_ACPI_STATUS(status);
  340. }
  341.  
  342. /*******************************************************************************
  343.  *
  344.  * FUNCTION:    acpi_ex_release_mutex
  345.  *
  346.  * PARAMETERS:  obj_desc            - The object descriptor for this op
  347.  *              walk_state          - Current method execution state
  348.  *
  349.  * RETURN:      Status
  350.  *
  351.  * DESCRIPTION: Release a previously acquired Mutex.
  352.  *
  353.  ******************************************************************************/
  354.  
  355. acpi_status
  356. acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
  357.                       struct acpi_walk_state *walk_state)
  358. {
  359.         acpi_status status = AE_OK;
  360.         u8 previous_sync_level;
  361.         struct acpi_thread_state *owner_thread;
  362.  
  363.         ACPI_FUNCTION_TRACE(ex_release_mutex);
  364.  
  365.         if (!obj_desc) {
  366.                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  367.         }
  368.  
  369.         owner_thread = obj_desc->mutex.owner_thread;
  370.  
  371.         /* The mutex must have been previously acquired in order to release it */
  372.  
  373.         if (!owner_thread) {
  374.                 ACPI_ERROR((AE_INFO,
  375.                             "Cannot release Mutex [%4.4s], not acquired",
  376.                             acpi_ut_get_node_name(obj_desc->mutex.node)));
  377.                 return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
  378.         }
  379.  
  380.         /* Must have a valid thread ID */
  381.  
  382.         if (!walk_state->thread) {
  383.                 ACPI_ERROR((AE_INFO,
  384.                             "Cannot release Mutex [%4.4s], null thread info",
  385.                             acpi_ut_get_node_name(obj_desc->mutex.node)));
  386.                 return_ACPI_STATUS(AE_AML_INTERNAL);
  387.         }
  388.  
  389.         /*
  390.          * The Mutex is owned, but this thread must be the owner.
  391.          * Special case for Global Lock, any thread can release
  392.          */
  393.         if ((owner_thread->thread_id != walk_state->thread->thread_id) &&
  394.             (obj_desc != acpi_gbl_global_lock_mutex)) {
  395.                 ACPI_ERROR((AE_INFO,
  396.                             "Thread %u cannot release Mutex [%4.4s] acquired by thread %u",
  397.                             (u32)walk_state->thread->thread_id,
  398.                             acpi_ut_get_node_name(obj_desc->mutex.node),
  399.                             (u32)owner_thread->thread_id));
  400.                 return_ACPI_STATUS(AE_AML_NOT_OWNER);
  401.         }
  402.  
  403.         /*
  404.          * The sync level of the mutex must be equal to the current sync level. In
  405.          * other words, the current level means that at least one mutex at that
  406.          * level is currently being held. Attempting to release a mutex of a
  407.          * different level can only mean that the mutex ordering rule is being
  408.          * violated. This behavior is clarified in ACPI 4.0 specification.
  409.          */
  410.         if (obj_desc->mutex.sync_level != owner_thread->current_sync_level) {
  411.                 ACPI_ERROR((AE_INFO,
  412.                             "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u",
  413.                             acpi_ut_get_node_name(obj_desc->mutex.node),
  414.                             obj_desc->mutex.sync_level,
  415.                             walk_state->thread->current_sync_level));
  416.                 return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
  417.         }
  418.  
  419.         /*
  420.          * Get the previous sync_level from the head of the acquired mutex list.
  421.          * This handles the case where several mutexes at the same level have been
  422.          * acquired, but are not released in reverse order.
  423.          */
  424.         previous_sync_level =
  425.             owner_thread->acquired_mutex_list->mutex.original_sync_level;
  426.  
  427.         status = acpi_ex_release_mutex_object(obj_desc);
  428.         if (ACPI_FAILURE(status)) {
  429.                 return_ACPI_STATUS(status);
  430.         }
  431.  
  432.         if (obj_desc->mutex.acquisition_depth == 0) {
  433.  
  434.                 /* Restore the previous sync_level */
  435.  
  436.                 owner_thread->current_sync_level = previous_sync_level;
  437.         }
  438.  
  439.         return_ACPI_STATUS(status);
  440. }
  441.  
  442. /*******************************************************************************
  443.  *
  444.  * FUNCTION:    acpi_ex_release_all_mutexes
  445.  *
  446.  * PARAMETERS:  thread              - Current executing thread object
  447.  *
  448.  * RETURN:      Status
  449.  *
  450.  * DESCRIPTION: Release all mutexes held by this thread
  451.  *
  452.  * NOTE: This function is called as the thread is exiting the interpreter.
  453.  * Mutexes are not released when an individual control method is exited, but
  454.  * only when the parent thread actually exits the interpreter. This allows one
  455.  * method to acquire a mutex, and a different method to release it, as long as
  456.  * this is performed underneath a single parent control method.
  457.  *
  458.  ******************************************************************************/
  459.  
  460. void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
  461. {
  462.         union acpi_operand_object *next = thread->acquired_mutex_list;
  463.         union acpi_operand_object *obj_desc;
  464.  
  465.         ACPI_FUNCTION_NAME(ex_release_all_mutexes);
  466.  
  467.         /* Traverse the list of owned mutexes, releasing each one */
  468.  
  469.         while (next) {
  470.                 obj_desc = next;
  471.                 next = obj_desc->mutex.next;
  472.  
  473.                 obj_desc->mutex.prev = NULL;
  474.                 obj_desc->mutex.next = NULL;
  475.                 obj_desc->mutex.acquisition_depth = 0;
  476.  
  477.                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
  478.                                   "Force-releasing held mutex: %p\n",
  479.                                   obj_desc));
  480.  
  481.                 /* Release the mutex, special case for Global Lock */
  482.  
  483.                 if (obj_desc == acpi_gbl_global_lock_mutex) {
  484.  
  485.                         /* Ignore errors */
  486.  
  487.                         (void)acpi_ev_release_global_lock();
  488.                 } else {
  489.                         acpi_os_release_mutex(obj_desc->mutex.os_mutex);
  490.                 }
  491.  
  492.                 /* Mark mutex unowned */
  493.  
  494.                 obj_desc->mutex.owner_thread = NULL;
  495.                 obj_desc->mutex.thread_id = 0;
  496.  
  497.                 /* Update Thread sync_level (Last mutex is the important one) */
  498.  
  499.                 thread->current_sync_level =
  500.                     obj_desc->mutex.original_sync_level;
  501.         }
  502. }
  503.