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

Keng-Yu Lin kengyu at canonical.com
Mon Jan 14 08:03:05 UTC 2013


On Sat, Jan 5, 2013 at 1:46 AM, Colin King <colin.king at canonical.com> wrote:
> 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
>
Acked-by: Keng-Yu Lin <kengyu at canonical.com>



More information about the fwts-devel mailing list