evmisc.c

来自「linux 内核源代码」· C语言 代码 · 共 630 行 · 第 1/2 页

C
630
字号
	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);}/******************************************************************************* * * FUNCTION:    acpi_ev_init_global_lock_handler * * PARAMETERS:  None * * RETURN:      Status * * DESCRIPTION: Install a handler for the global lock release event * ******************************************************************************/acpi_status acpi_ev_init_global_lock_handler(void){	acpi_status status;	ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);	status =	    acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,				    (struct acpi_table_header **)&facs);	if (ACPI_FAILURE(status)) {		return_ACPI_STATUS(status);	}	acpi_gbl_global_lock_present = TRUE;	status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,						  acpi_ev_global_lock_handler,						  NULL);	/*	 * If the global lock does not exist on this platform, the attempt	 * to enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick)	 * Map to AE_OK, but mark global lock as not present.	 * Any attempt to actually use the global lock will be flagged	 * with an error.	 */	if (status == AE_NO_HARDWARE_RESPONSE) {		ACPI_ERROR((AE_INFO,			    "No response from Global Lock hardware, disabling lock"));		acpi_gbl_global_lock_present = FALSE;		status = AE_OK;	}	return_ACPI_STATUS(status);}/******************************************************************************* * * FUNCTION:    acpi_ev_remove_global_lock_handler * * PARAMETERS:  None * * RETURN:      Status * * DESCRIPTION: Remove the handler for the Global Lock * ******************************************************************************/static acpi_status acpi_ev_remove_global_lock_handler(void){	acpi_status status;	ACPI_FUNCTION_TRACE(ev_remove_global_lock_handler);	acpi_gbl_global_lock_present = FALSE;	status = acpi_remove_fixed_event_handler(ACPI_EVENT_GLOBAL,						 acpi_ev_global_lock_handler);	return_ACPI_STATUS(status);}/****************************************************************************** * * FUNCTION:    acpi_ev_acquire_global_lock * * PARAMETERS:  Timeout         - Max time to wait for the lock, in millisec. * * RETURN:      Status * * DESCRIPTION: Attempt to gain ownership of the Global Lock. * * MUTEX:       Interpreter must be locked * * Note: The original implementation allowed multiple threads to "acquire" the * Global Lock, and the OS would hold the lock until the last thread had * released it. However, this could potentially starve the BIOS out of the * lock, especially in the case where there is a tight handshake between the * Embedded Controller driver and the BIOS. Therefore, this implementation * allows only one thread to acquire the HW Global Lock at a time, and makes * the global lock appear as a standard mutex on the OS side. * *****************************************************************************/static acpi_thread_id acpi_ev_global_lock_thread_id;static int acpi_ev_global_lock_acquired;acpi_status acpi_ev_acquire_global_lock(u16 timeout){	acpi_status status = AE_OK;	u8 acquired = FALSE;	ACPI_FUNCTION_TRACE(ev_acquire_global_lock);	/*	 * Only one thread can acquire the GL at a time, the global_lock_mutex	 * enforces this. This interface releases the interpreter if we must wait.	 */	status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0);	if (status == AE_TIME) {		if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) {			acpi_ev_global_lock_acquired++;			return AE_OK;		}	}	if (ACPI_FAILURE(status)) {		status =		    acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex,					      timeout);	}	if (ACPI_FAILURE(status)) {		return_ACPI_STATUS(status);	}	acpi_ev_global_lock_thread_id = acpi_os_get_thread_id();	acpi_ev_global_lock_acquired++;	/*	 * Make sure that a global lock actually exists. If not, just treat	 * the lock as a standard mutex.	 */	if (!acpi_gbl_global_lock_present) {		acpi_gbl_global_lock_acquired = TRUE;		return_ACPI_STATUS(AE_OK);	}	/* Attempt to acquire the actual hardware lock */	ACPI_ACQUIRE_GLOBAL_LOCK(facs, acquired);	if (acquired) {		/* We got the lock */		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,				  "Acquired hardware Global Lock\n"));		acpi_gbl_global_lock_acquired = TRUE;		return_ACPI_STATUS(AE_OK);	}	/*	 * Did not get the lock. The pending bit was set above, and we must now	 * wait until we get the global lock released interrupt.	 */	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n"));	/*	 * Wait for handshake with the global lock interrupt handler.	 * This interface releases the interpreter if we must wait.	 */	status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,					       ACPI_WAIT_FOREVER);	return_ACPI_STATUS(status);}/******************************************************************************* * * FUNCTION:    acpi_ev_release_global_lock * * PARAMETERS:  None * * RETURN:      Status * * DESCRIPTION: Releases ownership of the Global Lock. * ******************************************************************************/acpi_status acpi_ev_release_global_lock(void){	u8 pending = FALSE;	acpi_status status = AE_OK;	ACPI_FUNCTION_TRACE(ev_release_global_lock);	/* Lock must be already acquired */	if (!acpi_gbl_global_lock_acquired) {		ACPI_WARNING((AE_INFO,			      "Cannot release the ACPI Global Lock, it has not been acquired"));		return_ACPI_STATUS(AE_NOT_ACQUIRED);	}	acpi_ev_global_lock_acquired--;	if (acpi_ev_global_lock_acquired > 0) {		return AE_OK;	}	if (acpi_gbl_global_lock_present) {		/* Allow any thread to release the lock */		ACPI_RELEASE_GLOBAL_LOCK(facs, pending);		/*		 * If the pending bit was set, we must write GBL_RLS to the control		 * register		 */		if (pending) {			status =			    acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE,					      1);		}		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,				  "Released hardware Global Lock\n"));	}	acpi_gbl_global_lock_acquired = FALSE;	/* Release the local GL mutex */	acpi_ev_global_lock_thread_id = NULL;	acpi_ev_global_lock_acquired = 0;	acpi_os_release_mutex(acpi_gbl_global_lock_mutex);	return_ACPI_STATUS(status);}/****************************************************************************** * * FUNCTION:    acpi_ev_terminate * * PARAMETERS:  none * * RETURN:      none * * DESCRIPTION: Disable events and free memory allocated for table storage. * ******************************************************************************/void acpi_ev_terminate(void){	acpi_native_uint i;	acpi_status status;	ACPI_FUNCTION_TRACE(ev_terminate);	if (acpi_gbl_events_initialized) {		/*		 * Disable all event-related functionality.		 * In all cases, on error, print a message but obviously we don't abort.		 */		/* Disable all fixed events */		for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {			status = acpi_disable_event((u32) i, 0);			if (ACPI_FAILURE(status)) {				ACPI_ERROR((AE_INFO,					    "Could not disable fixed event %d",					    (u32) i));			}		}		/* Disable all GPEs in all GPE blocks */		status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block);		/* Remove SCI handler */		status = acpi_ev_remove_sci_handler();		if (ACPI_FAILURE(status)) {			ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));		}		status = acpi_ev_remove_global_lock_handler();		if (ACPI_FAILURE(status)) {			ACPI_ERROR((AE_INFO,				    "Could not remove Global Lock handler"));		}	}	/* Deallocate all handler objects installed within GPE info structs */	status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers);	/* Return to original mode if necessary */	if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {		status = acpi_disable();		if (ACPI_FAILURE(status)) {			ACPI_WARNING((AE_INFO, "AcpiDisable failed"));		}	}	return_VOID;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?