[PATCH] acpica: fwts_acpica: force indefinite AML Wait() to timeout

Colin King colin.king at canonical.com
Fri Jan 4 17:46:34 UTC 2013


From: Colin Ian King <colin.king at canonical.com>

Quite a few _EJ0 implementations make the ACPI method test block
forever because they are using an AML Wait() that is waiting
indefinitely for an external event (which fwts cannot generate).
Instead of the test waiting forever for the event, make these
waits timeout after 20 seconds.  We force this by causing an alarm
signal which interrupts the blocked sem_wait and we can detect this
and report back to the user that we aborted the wait.  This is ugly
but effective.

Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
 src/acpica/fwts_acpica.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/src/acpica/fwts_acpica.c b/src/acpica/fwts_acpica.c
index 26b6a13..65caa18 100644
--- a/src/acpica/fwts_acpica.c
+++ b/src/acpica/fwts_acpica.c
@@ -55,6 +55,8 @@ static pthread_mutex_t mutex_thread_info;
 #define MAX_SEMAPHORES		(1024)
 #define MAX_THREADS		(128)
 
+#define MAX_WAIT_TIMEOUT	(20)	/* Seconds */
+
 typedef struct {
 	sem_t		sem;	/* Semaphore handle */
 	int		count;	/* count > 0 if acquired */
@@ -546,6 +548,10 @@ ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_HANDLE Handle)
 	return ret;
 }
 
+static void sem_alarm(int dummy)
+{
+	/* Do nothing apart from interrupt sem_wait() */
+}
 
 /*
  *  AcpiOsWaitSemaphore()
@@ -556,6 +562,7 @@ ACPI_STATUS AcpiOsWaitSemaphore(ACPI_HANDLE handle, UINT32 Units, UINT16 Timeout
 {
 	sem_info *sem = (sem_info *)handle;
 	struct timespec	tm;
+	struct sigaction sa;
 
 	if (!handle)
 		return AE_BAD_PARAMETER;
@@ -567,8 +574,34 @@ ACPI_STATUS AcpiOsWaitSemaphore(ACPI_HANDLE handle, UINT32 Units, UINT16 Timeout
 		break;
 
 	case ACPI_WAIT_FOREVER:
-		if (sem_wait(&sem->sem))
+		/*
+		 *  The semantics are "wait forever", but
+		 *  really we actually detect a lock up
+		 *  after a long wait and break out rather
+		 *  than waiting for the sun to turn into
+		 *  a lump of coal.  This allows us to
+		 *  handle controls such as _EJ0 that may
+		 *  be waiting forever for a event to signal
+		 *  control to continue.  It is evil.
+		 */
+		sa.sa_handler = sem_alarm;
+		sa.sa_flags = 0;
+		sigaction(SIGALRM, &sa, NULL);
+		alarm(MAX_WAIT_TIMEOUT);
+
+		if (sem_wait(&sem->sem)) {
+			alarm(0);
+			if (errno == EINTR)
+				fwts_log_info(fwts_acpica_fw,
+					"AML was blocked waiting for "
+					"an external event, fwts detected "
+					"this and forced a timeout after "
+					"%d seconds on a Wait() that had "
+					"an indefinite timeout.",
+					MAX_WAIT_TIMEOUT);
 			return AE_TIME;
+		}
+		alarm(0);
 		break;
 	default:
 		tm.tv_sec = Timeout / 1000;
-- 
1.8.0




More information about the fwts-devel mailing list