/* $OpenBSD: kern_sensors.c,v 1.19 2007/06/04 18:42:05 deraadt Exp $ */
/*
+ * (MPSAFE)
+ *
* Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
* Copyright (c) 2006 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru>
*
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/time.h>
+#include <sys/spinlock.h>
+#include <sys/spinlock2.h>
#include <sys/lock.h>
#include <sys/sysctl.h>
#include <sys/mplock2.h>
+static int sensor_task_lock_inited = 0;
+static struct lock sensor_task_lock;
+static struct spinlock sensor_dev_lock = SPINLOCK_INITIALIZER(sensor_dev_lock);
+
int sensordev_count = 0;
SLIST_HEAD(, ksensordev) sensordev_list = SLIST_HEAD_INITIALIZER(sensordev_list);
struct ksensordev *v, *nv;
/* mtx_lock(&Giant); */
+ spin_lock_wr(&sensor_dev_lock);
if (sensordev_count == 0) {
sensdev->num = 0;
SLIST_INSERT_HEAD(&sensordev_list, sensdev, list);
#ifndef NOSYSCTL8HACK
sensor_sysctl8magic_install(sensdev);
#endif
+ spin_unlock_wr(&sensor_dev_lock);
}
void
int i;
/* mtx_lock(&Giant); */
+ spin_lock_wr(&sensor_dev_lock);
sh = &sensdev->sensors_list;
if (sensdev->sensors_count == 0) {
for (i = 0; i < SENSOR_MAX_TYPES; i++)
if (sensdev->maxnumt[sens->type] == sens->numt)
sensdev->maxnumt[sens->type]++;
sensdev->sensors_count++;
+ spin_unlock_wr(&sensor_dev_lock);
/* mtx_unlock(&Giant); */
}
sensordev_deinstall(struct ksensordev *sensdev)
{
/* mtx_lock(&Giant); */
+ spin_lock_wr(&sensor_dev_lock);
sensordev_count--;
SLIST_REMOVE(&sensordev_list, sensdev, ksensordev, list);
/* mtx_unlock(&Giant); */
#ifndef NOSYSCTL8HACK
sensor_sysctl8magic_deinstall(sensdev);
#endif
+ spin_unlock_wr(&sensor_dev_lock);
}
void
{
struct ksensordev *sd;
+ spin_lock_wr(&sensor_dev_lock);
SLIST_FOREACH(sd, &sensordev_list, list)
- if (sd->num == num)
+ if (sd->num == num) {
+ spin_unlock_wr(&sensor_dev_lock);
return (sd);
+ }
+ spin_unlock_wr(&sensor_dev_lock);
return (NULL);
}
struct ksensor *s;
struct ksensors_head *sh;
+ spin_lock_wr(&sensor_dev_lock);
sh = &sensdev->sensors_list;
- SLIST_FOREACH(s, sh, list)
- if (s->type == type && s->numt == numt)
+ SLIST_FOREACH(s, sh, list) {
+ if (s->type == type && s->numt == numt) {
+ spin_unlock_wr(&sensor_dev_lock);
return (s);
+ }
+ }
+ spin_unlock_wr(&sensor_dev_lock);
return (NULL);
}
if (st == NULL)
return (1);
+ if (atomic_cmpset_int(&sensor_task_lock_inited, 0, 1)) {
+ lockinit(&sensor_task_lock, "ksensor_task", 0, LK_CANRECURSE);
+ }
+
+ lockmgr(&sensor_task_lock, LK_EXCLUSIVE);
st->arg = arg;
st->func = func;
st->period = period;
wakeup(&tasklist);
+ lockmgr(&sensor_task_lock, LK_RELEASE);
return (0);
}
{
struct sensor_task *st;
+ lockmgr(&sensor_task_lock, LK_EXCLUSIVE);
TAILQ_FOREACH(st, &tasklist, entry)
if (st->arg == arg)
st->running = 0;
+ lockmgr(&sensor_task_lock, LK_RELEASE);
}
void
struct sensor_task *st, *nst;
time_t now;
- get_mplock();
+ lockmgr(&sensor_task_lock, LK_EXCLUSIVE);
while (!TAILQ_EMPTY(&tasklist)) {
while ((nst = TAILQ_FIRST(&tasklist))->nextrun >
(now = time_second))
- tsleep(&tasklist, 0, "timeout",
+ lksleep(&tasklist, &sensor_task_lock, 0, "timeout",
(nst->nextrun - now) * hz);
while ((st = nst) != NULL) {
}
}
- rel_mplock();
+ lockmgr(&sensor_task_lock, LK_RELEASE);
}
void
{
struct sensor_task *cst;
+ lockmgr(&sensor_task_lock, LK_EXCLUSIVE);
st->nextrun = time_second + st->period;
TAILQ_FOREACH(cst, &tasklist, entry) {
if (cst->nextrun > st->nextrun) {
TAILQ_INSERT_BEFORE(cst, st, entry);
+ lockmgr(&sensor_task_lock, LK_RELEASE);
return;
}
}
/* must be an empty list, or at the end of the list */
TAILQ_INSERT_TAIL(&tasklist, st, entry);
+ lockmgr(&sensor_task_lock, LK_RELEASE);
}
/*