/******************************************************************************* * * FUNCTION: acpi_ex_system_wait_semaphore * * PARAMETERS: semaphore - Semaphore to wait on * timeout - Max time to wait * * RETURN: Status * * DESCRIPTION: Implements a semaphore wait with a check to see if the * semaphore is available immediately. If it is not, the * interpreter is released before waiting. * ******************************************************************************/ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) { acpi_status status; ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); status = acpi_os_wait_semaphore(semaphore, 1, ACPI_DO_NOT_WAIT); if (ACPI_SUCCESS(status)) { return_ACPI_STATUS(status); } if (status == AE_TIME) { /* We must wait, so unlock the interpreter */ acpi_ex_exit_interpreter(); status = acpi_os_wait_semaphore(semaphore, 1, timeout); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*** Thread awake after blocking, %s\n", acpi_format_exception(status))); /* Reacquire the interpreter */ acpi_ex_enter_interpreter(); } return_ACPI_STATUS(status); }
acpi_status acpi_ex_system_wait_semaphore ( acpi_handle semaphore, u16 timeout) { acpi_status status; acpi_status status2; ACPI_FUNCTION_TRACE ("ex_system_wait_semaphore"); status = acpi_os_wait_semaphore (semaphore, 1, 0); if (ACPI_SUCCESS (status)) { return_ACPI_STATUS (status); } if (status == AE_TIME) { /* We must wait, so unlock the interpreter */ acpi_ex_exit_interpreter (); status = acpi_os_wait_semaphore (semaphore, 1, timeout); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*** Thread awake after blocking, %s\n", acpi_format_exception (status))); /* Reacquire the interpreter */ status2 = acpi_ex_enter_interpreter (); if (ACPI_FAILURE (status2)) { /* Report fatal error, could not acquire interpreter */ return_ACPI_STATUS (status2); } } return_ACPI_STATUS (status); }
ACPI_STATUS acpi_cm_acquire_mutex ( ACPI_MUTEX_HANDLE mutex_id) { ACPI_STATUS status; if (mutex_id > MAX_MTX) { return (AE_BAD_PARAMETER); } status = acpi_os_wait_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, 1, WAIT_FOREVER); if (ACPI_SUCCESS (status)) { acpi_gbl_acpi_mutex_info[mutex_id].locked = TRUE; acpi_gbl_acpi_mutex_info[mutex_id].use_count++; } return (status); }
acpi_cpu_flags acpi_os_acquire_lock(acpi_handle handle) { acpi_os_wait_semaphore(handle, 1, 0xFFFF); return (0); }
acpi_status acpi_ut_acquire_mutex ( acpi_mutex_handle mutex_id) { acpi_status status; u32 this_thread_id; ACPI_FUNCTION_NAME ("ut_acquire_mutex"); if (mutex_id > MAX_MUTEX) { return (AE_BAD_PARAMETER); } this_thread_id = acpi_os_get_thread_id (); #ifdef ACPI_MUTEX_DEBUG { u32 i; /* * Mutex debug code, for internal debugging only. * * Deadlock prevention. Check if this thread owns any mutexes of value * greater than or equal to 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) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Mutex [%s] already acquired by this thread [%X]\n", acpi_ut_get_mutex_name (mutex_id), this_thread_id)); return (AE_ALREADY_ACQUIRED); } ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid acquire order: Thread %X owns [%s], wants [%s]\n", this_thread_id, acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id))); return (AE_ACQUIRE_DEADLOCK); } } } #endif ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X attempting to acquire Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); status = acpi_os_wait_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1, ACPI_WAIT_FOREVER); if (ACPI_SUCCESS (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); acpi_gbl_mutex_info[mutex_id].use_count++; acpi_gbl_mutex_info[mutex_id].owner_id = this_thread_id; } else { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not acquire Mutex [%s] %s\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id), acpi_format_exception (status))); } return (status); }
void acpi_db_create_execution_threads ( NATIVE_CHAR *num_threads_arg, NATIVE_CHAR *num_loops_arg, NATIVE_CHAR *method_name_arg) { acpi_status status; u32 num_threads; u32 num_loops; u32 i; acpi_handle thread_gate; /* Get the arguments */ num_threads = STRTOUL (num_threads_arg, NULL, 0); num_loops = STRTOUL (num_loops_arg, NULL, 0); if (!num_threads || !num_loops) { acpi_os_printf ("Bad argument: Threads %X, Loops %X\n", num_threads, num_loops); return; } /* Create the synchronization semaphore */ status = acpi_os_create_semaphore (1, 0, &thread_gate); if (ACPI_FAILURE (status)) { acpi_os_printf ("Could not create semaphore, %s\n", acpi_format_exception (status)); return; } /* Setup the context to be passed to each thread */ acpi_gbl_db_method_info.name = method_name_arg; acpi_gbl_db_method_info.args = NULL; acpi_gbl_db_method_info.flags = 0; acpi_gbl_db_method_info.num_loops = num_loops; acpi_gbl_db_method_info.thread_gate = thread_gate; acpi_db_execute_setup (&acpi_gbl_db_method_info); /* Create the threads */ acpi_os_printf ("Creating %X threads to execute %X times each\n", num_threads, num_loops); for (i = 0; i < (num_threads); i++) { acpi_os_queue_for_execution (OSD_PRIORITY_MED, acpi_db_method_thread, &acpi_gbl_db_method_info); } /* Wait for all threads to complete */ i = num_threads; while (i) /* Brain damage for OSD implementations that only support wait of 1 unit */ { status = acpi_os_wait_semaphore (thread_gate, 1, WAIT_FOREVER); i--; } /* Cleanup and exit */ acpi_os_delete_semaphore (thread_gate); acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); acpi_os_printf ("All threads (%X) have completed\n", num_threads); acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); }