> Date: Tue, 8 Jan 2019 18:02:27 +0100 (CET)
> From: Mark Kettenis <mark.kette...@xs4all.nl>
>
> > Date: Tue, 8 Jan 2019 17:46:37 +0100 (CET)
> > From: Mark Kettenis <mark.kette...@xs4all.nl>
> >
> > I have a Shuttle NC02U "nano" PC that ends up with the the acpi0
> > kernel thread blocked on the "acpievt" wait channel. I tracked this
> > down to an incorrect implementation of the Signal() and Wait()
> > operations.
> >
> > This changes the implementation to be a proper semaphore. It also
> > releases the acpi interpreter lock. This is necessary because the
> > acpivout(4) implementation directly executes AML code from the calling
> > thread instead of using an acpi task. Maybe that should be fixed
> > instead but it is non-trivial and the current code results in a hard
> > hang during the initial mode setting stage.
> >
> > ok?
>
> Better diff. We shouldn't call delay() if we ran a task.
And instead of tsleep(9), use rwlseep(9).
Index: dev/acpi/dsdt.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v
retrieving revision 1.243
diff -u -p -r1.243 dsdt.c
--- dev/acpi/dsdt.c 19 Aug 2018 08:23:47 -0000 1.243
+++ dev/acpi/dsdt.c 8 Jan 2019 18:55:14 -0000
@@ -2905,29 +2905,33 @@ int
acpi_event_wait(struct aml_scope *scope, struct aml_value *evt, int timeout)
{
/* Wait for event to occur; do work in meantime */
- evt->v_evt.state = 0;
- while (!evt->v_evt.state) {
- if (!acpi_dotask(acpi_softc) && !cold)
- tsleep(evt, PWAIT, "acpievt", 1);
- else
- delay(100);
+ while (evt->v_evt.state == 0 && timeout >= 0) {
+ if (acpi_dotask(acpi_softc))
+ continue;
+ if (!cold) {
+ if (rwsleep(evt, &acpi_softc->sc_lck, PWAIT,
+ "acpievt", 1) == EWOULDBLOCK) {
+ if (timeout < 0xffff)
+ timeout -= (1000 / hz);
+ }
+ } else {
+ delay(1000);
+ if (timeout < 0xffff)
+ timeout--;
+ }
}
- if (evt->v_evt.state == 1) {
- /* Object is signaled */
- return (0);
- } else if (timeout == 0) {
- /* Zero timeout */
+ if (evt->v_evt.state == 0)
return (-1);
- }
- /* Wait for timeout or signal */
+ evt->v_evt.state--;
return (0);
}
void
acpi_event_signal(struct aml_scope *scope, struct aml_value *evt)
{
- evt->v_evt.state = 1;
- /* Wakeup waiters */
+ evt->v_evt.state++;
+ if (evt->v_evt.state > 0)
+ wakeup_one(evt);
}
void
@@ -4215,7 +4219,7 @@ aml_parse(struct aml_scope *scope, int r
case AMLOP_EVENT:
/* Event: N */
rv = _aml_setvalue(opargs[0], AML_OBJTYPE_EVENT, 0, 0);
- rv->v_integer = 0;
+ rv->v_evt.state = 0;
break;
case AMLOP_MUTEX:
/* Mutex: Nw */