summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/syscons/apm/apm_saver.c4
-rw-r--r--sys/i386/bios/apm.c64
-rw-r--r--sys/i386/bios/apm.h5
3 files changed, 46 insertions, 27 deletions
diff --git a/sys/dev/syscons/apm/apm_saver.c b/sys/dev/syscons/apm/apm_saver.c
index cdd5969..567b452 100644
--- a/sys/dev/syscons/apm/apm_saver.c
+++ b/sys/dev/syscons/apm/apm_saver.c
@@ -30,8 +30,12 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/condvar.h>
#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
#include <sys/module.h>
+#include <sys/mutex.h>
#include <sys/consio.h>
#include <sys/fbio.h>
diff --git a/sys/i386/bios/apm.c b/sys/i386/bios/apm.c
index b9b446d..4e3dba3 100644
--- a/sys/i386/bios/apm.c
+++ b/sys/i386/bios/apm.c
@@ -23,10 +23,14 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
+#include <sys/condvar.h>
#include <sys/eventhandler.h>
#include <sys/fcntl.h>
#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
#include <sys/module.h>
+#include <sys/mutex.h>
#include <sys/poll.h>
#include <sys/power.h>
#include <sys/reboot.h>
@@ -98,10 +102,6 @@ static struct apmhook *hook[NAPM_HOOK]; /* XXX */
/* Map version number to integer (keeps ordering of version numbers) */
#define INTVERSION(major, minor) ((major)*100 + (minor))
-static struct callout_handle apm_timeout_ch =
- CALLOUT_HANDLE_INITIALIZER(&apm_timeout_ch);
-
-static timeout_t apm_timeout;
static d_open_t apmopen;
static d_close_t apmclose;
static d_write_t apmwrite;
@@ -728,31 +728,32 @@ apm_cpu_busy(void)
/*
- * APM timeout routine:
+ * APM thread loop.
*
- * This routine is automatically called by timer once per second.
+ * This routine wakes up from time to time to deal with delaying the
+ * suspend of the system, or other events.
*/
-
static void
-apm_timeout(void *dummy)
+apm_event_thread(void *arg)
{
struct apm_softc *sc = &apm_softc;
- if (apm_op_inprog)
- apm_lastreq_notify();
-
- if (sc->standbys && sc->standby_countdown-- <= 0)
- apm_do_standby();
-
- if (sc->suspends && sc->suspend_countdown-- <= 0)
- apm_do_suspend();
-
- if (!sc->bios_busy)
- apm_processevent();
-
- if (sc->active == 1)
- /* Run slightly more oftan than 1 Hz */
- apm_timeout_ch = timeout(apm_timeout, NULL, hz - 1);
+ sc->running = 1;
+ while (sc->active) {
+ if (apm_op_inprog)
+ apm_lastreq_notify();
+ if (sc->standbys && sc->standby_countdown-- <= 0)
+ apm_do_standby();
+ if (sc->suspends && sc->suspend_countdown-- <= 0)
+ apm_do_suspend();
+ if (!sc->bios_busy)
+ apm_processevent();
+ mtx_lock(&sc->mtx);
+ cv_timedwait(&sc->cv, &sc->mtx, 10 * hz / 9);
+ mtx_unlock(&sc->mtx);
+ }
+ sc->running = 0;
+ kthread_exit(0);
}
/* enable APM BIOS */
@@ -766,8 +767,11 @@ apm_event_enable(void)
if (sc == NULL || sc->initialized == 0)
return;
+ /* Start the thread */
sc->active = 1;
- apm_timeout(sc);
+ if (kthread_create(apm_event_thread, sc, &sc->event_thread, 0, 0,
+ "apm worker"))
+ panic("Cannot create apm worker thread");
return;
}
@@ -783,9 +787,14 @@ apm_event_disable(void)
if (sc == NULL || sc->initialized == 0)
return;
- untimeout(apm_timeout, NULL, apm_timeout_ch);
+ mtx_lock(&sc->mtx);
sc->active = 0;
-
+ while (sc->running) {
+ cv_broadcast(&sc->cv);
+ msleep(sc->event_thread, &sc->mtx, PWAIT, "apmdie", 0);
+ }
+ mtx_unlock(&sc->mtx);
+ sc->event_thread = NULL;
return;
}
@@ -1132,6 +1141,8 @@ apm_attach(device_t dev)
#ifdef PC98
int rid;
#endif
+ mtx_init(&sc->mtx, device_get_nameunit(dev), "apm", MTX_DEF);
+ cv_init(&sc->cv, "cbb cv");
if (device_get_flags(dev) & 0x20)
statclock_disable = 1;
@@ -1223,6 +1234,7 @@ apm_attach(device_t dev)
sc->initialized = 1;
sc->suspending = 0;
+ sc->running = 0;
make_dev(&apm_cdevsw, 0, 0, 5, 0664, "apm");
make_dev(&apm_cdevsw, 8, 0, 5, 0660, "apmctl");
diff --git a/sys/i386/bios/apm.h b/sys/i386/bios/apm.h
index ce87c54..2b20e61 100644
--- a/sys/i386/bios/apm.h
+++ b/sys/i386/bios/apm.h
@@ -29,7 +29,10 @@ struct apm_softc {
bus_space_handle_t sc_ioh;
struct resource *sc_res;
#endif
- int initialized, active, bios_busy;
+ struct mtx mtx;
+ struct cv cv;
+ struct proc *event_thread;
+ int initialized, active, running, bios_busy;
int always_halt_cpu, slow_idle_cpu;
int disabled, disengaged;
int suspending;
OpenPOWER on IntegriCloud