static u32 acpi_ev_global_lock_handler(void *context) { acpi_status status; acpi_cpu_flags flags; flags = acpi_os_acquire_lock(acpi_gbl_global_lock_pending_lock); /* * If a request for the global lock is not actually pending, * we are done. This handles "spurious" global lock interrupts * which are possible (and have been seen) with bad BIOSs. */ if (!acpi_gbl_global_lock_pending) { goto cleanup_and_exit; } /* * Send a unit to the global lock semaphore. The actual acquisition * of the global lock will be performed by the waiting thread. */ status = acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore, 1); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore")); } acpi_gbl_global_lock_pending = FALSE; cleanup_and_exit: acpi_os_release_lock(acpi_gbl_global_lock_pending_lock, flags); return (ACPI_INTERRUPT_HANDLED); }
static u32 acpi_ev_global_lock_handler(void *context) { u8 acquired = FALSE; /* * Attempt to get the lock. * * If we don't get it now, it will be marked pending and we will * take another interrupt when it becomes free. */ ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); if (acquired) { /* Got the lock, now wake all threads waiting for it */ acpi_gbl_global_lock_acquired = TRUE; /* Send a unit to the semaphore */ if (ACPI_FAILURE (acpi_os_signal_semaphore (acpi_gbl_global_lock_semaphore, 1))) { ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore")); } } return (ACPI_INTERRUPT_HANDLED); }
acpi_status acpi_ex_system_release_mutex ( union acpi_operand_object *obj_desc) { acpi_status status = AE_OK; ACPI_FUNCTION_TRACE ("ex_system_release_mutex"); if (!obj_desc) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Support for the _GL_ Mutex object -- release the global lock */ if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { status = acpi_ev_release_global_lock (); return_ACPI_STATUS (status); } status = acpi_os_signal_semaphore (obj_desc->mutex.semaphore, 1); return_ACPI_STATUS (status); }
static u32 acpi_ev_global_lock_handler(void *context) { acpi_status status; acpi_cpu_flags flags; flags = acpi_os_acquire_lock(acpi_ev_global_lock_pending_lock); if (!acpi_ev_global_lock_pending) { goto out; } /* Send a unit to the semaphore */ status = acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore, 1); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore")); } acpi_ev_global_lock_pending = FALSE; out: acpi_os_release_lock(acpi_ev_global_lock_pending_lock, flags); return (ACPI_INTERRUPT_HANDLED); }
void acpi_db_method_thread ( void *context) { acpi_status status; db_method_info *info = context; u32 i; acpi_buffer return_obj; for (i = 0; i < info->num_loops; i++) { status = acpi_db_execute_method (info, &return_obj); if (ACPI_SUCCESS (status)) { if (return_obj.length) { acpi_os_printf ("Execution of %s returned object %p Buflen %X\n", info->pathname, return_obj.pointer, return_obj.length); acpi_db_dump_object (return_obj.pointer, 1); } } } /* Signal our completion */ acpi_os_signal_semaphore (info->thread_gate, 1); }
acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc) { acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(ex_system_signal_event); if (obj_desc) { status = acpi_os_signal_semaphore(obj_desc->event.os_semaphore, 1); } return_ACPI_STATUS(status); }
static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread ( void *context) { acpi_status status; /* Signal threads that are waiting for the lock */ if (acpi_gbl_global_lock_thread_count) { /* Send sufficient units to the semaphore */ status = acpi_os_signal_semaphore (acpi_gbl_global_lock_semaphore, acpi_gbl_global_lock_thread_count); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("Could not signal Global Lock semaphore\n")); } } }
ACPI_STATUS acpi_cm_release_mutex ( ACPI_MUTEX_HANDLE mutex_id) { ACPI_STATUS status; if (mutex_id > MAX_MTX) { return (AE_BAD_PARAMETER); } acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE; /* Mark before unlocking */ status = acpi_os_signal_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, 1); return (status); }
void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) { union acpi_operand_object *obj_desc; struct acpi_namespace_node *method_node; acpi_status status; ACPI_FUNCTION_TRACE_PTR("ds_terminate_control_method", walk_state); if (!walk_state) { return_VOID; } /* The current method object was saved in the walk state */ obj_desc = walk_state->method_desc; if (!obj_desc) { return_VOID; } /* Delete all arguments and locals */ acpi_ds_method_data_delete_all(walk_state); /* * Lock the parser while we terminate this method. * If this is the last thread executing the method, * we have additional cleanup to perform */ status = acpi_ut_acquire_mutex(ACPI_MTX_PARSER); if (ACPI_FAILURE(status)) { return_VOID; } /* Signal completion of the execution of this method if necessary */ if (walk_state->method_desc->method.semaphore) { status = acpi_os_signal_semaphore(walk_state->method_desc->method. semaphore, 1); if (ACPI_FAILURE(status)) { ACPI_REPORT_ERROR(("Could not signal method semaphore\n")); /* Ignore error and continue cleanup */ } } if (walk_state->method_desc->method.thread_count) { ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "*** Not deleting method namespace, there are still %d threads\n", walk_state->method_desc->method. thread_count)); } else { /* This is the last executing thread */ /* * Support to dynamically change a method from not_serialized to * Serialized if it appears that the method is written foolishly and * does not support multiple thread execution. The best example of this * is if such a method creates namespace objects and blocks. A second * thread will fail with an AE_ALREADY_EXISTS exception * * This code is here because we must wait until the last thread exits * before creating the synchronization semaphore. */ if ((walk_state->method_desc->method.concurrency == 1) && (!walk_state->method_desc->method.semaphore)) { status = acpi_os_create_semaphore(1, 1, &walk_state-> method_desc->method. semaphore); } /* * There are no more threads executing this method. Perform * additional cleanup. * * The method Node is stored in the walk state */ method_node = walk_state->method_node; /* * Delete any namespace entries created immediately underneath * the method */ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { goto exit; } if (method_node->child) { acpi_ns_delete_namespace_subtree(method_node); } /* * Delete any namespace entries created anywhere else within * the namespace */ acpi_ns_delete_namespace_by_owner(walk_state->method_desc-> method.owner_id); status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); acpi_ut_release_owner_id(&walk_state->method_desc->method. owner_id); } exit: (void)acpi_ut_release_mutex(ACPI_MTX_PARSER); return_VOID; }
void acpi_os_release_lock(acpi_spinlock handle, acpi_cpu_flags flags) { acpi_os_signal_semaphore(handle, 1); }
acpi_status acpi_ut_release_mutex ( acpi_mutex_handle mutex_id) { acpi_status status; u32 i; u32 this_thread_id; ACPI_FUNCTION_NAME ("ut_release_mutex"); this_thread_id = acpi_os_get_thread_id (); ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X releasing Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); if (mutex_id > MAX_MUTEX) { return (AE_BAD_PARAMETER); } /* * Mutex must be acquired in order to release it! */ if (acpi_gbl_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Mutex [%s] is not acquired, cannot release\n", acpi_ut_get_mutex_name (mutex_id))); return (AE_NOT_ACQUIRED); } /* * Deadlock prevention. Check if this thread owns any mutexes of value * greater than this one. If so, the thread has violated the mutex * ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ for (i = mutex_id; i < MAX_MUTEX; i++) { if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { if (i == mutex_id) { continue; } ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid release order: owns [%s], releasing [%s]\n", acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id))); return (AE_RELEASE_DEADLOCK); } } /* Mark unlocked FIRST */ acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; status = acpi_os_signal_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not release Mutex [%s] %s\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id), acpi_format_exception (status))); } else { ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); } return (status); }
ACPI_STATUS acpi_ds_terminate_control_method ( ACPI_WALK_STATE *walk_state) { ACPI_STATUS status; ACPI_OPERAND_OBJECT *obj_desc; ACPI_NAMESPACE_NODE *method_node; /* The method object should be stored in the walk state */ obj_desc = walk_state->method_desc; if (!obj_desc) { return (AE_OK); } /* Delete all arguments and locals */ acpi_ds_method_data_delete_all (walk_state); /* * Lock the parser while we terminate this method. * If this is the last thread executing the method, * we have additional cleanup to perform */ acpi_cm_acquire_mutex (ACPI_MTX_PARSER); /* Signal completion of the execution of this method if necessary */ if (walk_state->method_desc->method.semaphore) { status = acpi_os_signal_semaphore ( walk_state->method_desc->method.semaphore, 1); } /* Decrement the thread count on the method parse tree */ walk_state->method_desc->method.thread_count--; if (!walk_state->method_desc->method.thread_count) { /* * There are no more threads executing this method. Perform * additional cleanup. * * The method Node is stored in the walk state */ method_node = walk_state->method_node; /* * Delete any namespace entries created immediately underneath * the method */ acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); if (method_node->child) { acpi_ns_delete_namespace_subtree (method_node); } /* * Delete any namespace entries created anywhere else within * the namespace */ acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id); acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); } acpi_cm_release_mutex (ACPI_MTX_PARSER); return (AE_OK); }