From patchwork Fri Jan 4 17:46:34 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: acpica: fwts_acpica: force indefinite AML Wait() to timeout Date: Fri, 04 Jan 2013 07:46:34 -0000 From: Colin King X-Patchwork-Id: 209504 Message-Id: <1357321594-2062-1-git-send-email-colin.king@canonical.com> To: fwts-devel@lists.ubuntu.com From: Colin Ian King 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 Acked-by: Keng-Yu Lin Acked-by: Ivan Hu --- 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;