The device close routine is called when _last_ descriptor to the

device file is closed, rather on every descriptor close. Instead of
getting the exclusive lock on open and releasing on close, get
the lock only when needed in sysmonioctl_envsys().
Fixes kern/14368 by Anthony Mallet. Okayed by Jason Thorpe.

While here, also inline sysmon_envsys_init() to sysmonopen_envsys(),
and g/c sysmonioctl_wdog() prototype.
This commit is contained in:
jdolecek 2002-01-03 22:35:53 +00:00
parent f854b2521f
commit 57b53bc9a8

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysmon_envsys.c,v 1.2 2001/11/13 06:28:55 lukem Exp $ */
/* $NetBSD: sysmon_envsys.c,v 1.3 2002/01/03 22:35:53 jdolecek Exp $ */
/*-
* Copyright (c) 2000 Zembu Labs, Inc.
@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.2 2001/11/13 06:28:55 lukem Exp $");
__KERNEL_RCSID(0, "$NetBSD: sysmon_envsys.c,v 1.3 2002/01/03 22:35:53 jdolecek Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@ -69,27 +69,17 @@ u_int sysmon_envsys_next_sensor_index;
int sysmon_envsys_initialized;
struct simplelock sysmon_envsys_initialized_slock = SIMPLELOCK_INITIALIZER;
void sysmon_envsys_init(void);
#define SYSMON_ENVSYS_LOCK() \
lockmgr(&sysmon_envsys_lock, LK_EXCLUSIVE, NULL)
#define SYSMON_ENVSYS_UNLOCK() \
lockmgr(&sysmon_envsys_lock, LK_RELEASE, NULL)
int sysmonioctl_envsys(dev_t, u_long, caddr_t, int, struct proc *);
int sysmonioctl_wdog(dev_t, u_long, caddr_t, int, struct proc *);
struct sysmon_envsys *sysmon_envsys_find(u_int);
void sysmon_envsys_release(struct sysmon_envsys *);
/*
* sysmon_envsys_init:
*
* Initialize the system monitor.
*/
void
sysmon_envsys_init(void)
{
lockinit(&sysmon_envsys_lock, PWAIT|PCATCH, "smenv", 0, 0);
sysmon_envsys_initialized = 1;
}
/*
* sysmonopen_envsys:
*
@ -98,18 +88,14 @@ sysmon_envsys_init(void)
int
sysmonopen_envsys(dev_t dev, int flag, int mode, struct proc *p)
{
int error = 0;
simple_lock(&sysmon_envsys_initialized_slock);
if (sysmon_envsys_initialized == 0)
sysmon_envsys_init();
if (sysmon_envsys_initialized == 0) {
lockinit(&sysmon_envsys_lock, PWAIT|PCATCH, "smenv", 0, 0);
sysmon_envsys_initialized = 1;
}
simple_unlock(&sysmon_envsys_initialized_slock);
error = lockmgr(&sysmon_envsys_lock,
LK_EXCLUSIVE | LK_INTERLOCK |
((flag & O_NONBLOCK) ? LK_NOWAIT : 0),
&sysmon_envsys_initialized_slock);
return (error);
return (0);
}
/*
@ -121,7 +107,7 @@ int
sysmonclose_envsys(dev_t dev, int flag, int mode, struct proc *p)
{
(void) lockmgr(&sysmon_envsys_lock, LK_RELEASE, NULL);
/* Nothing to do */
return (0);
}
@ -181,8 +167,11 @@ sysmonioctl_envsys(dev_t dev, u_long cmd, caddr_t data, int flag,
break;
oidx = tred->sensor;
tred->sensor = SME_SENSOR_IDX(sme, tred->sensor);
if (tred->sensor < sme->sme_nsensors)
if (tred->sensor < sme->sme_nsensors) {
SYSMON_ENVSYS_LOCK();
error = (*sme->sme_gtredata)(sme, tred);
SYSMON_ENVSYS_UNLOCK();
}
tred->sensor = oidx;
sysmon_envsys_release(sme);
break;
@ -199,9 +188,11 @@ sysmonioctl_envsys(dev_t dev, u_long cmd, caddr_t data, int flag,
}
oidx = binfo->sensor;
binfo->sensor = SME_SENSOR_IDX(sme, binfo->sensor);
if (binfo->sensor < sme->sme_nsensors)
if (binfo->sensor < sme->sme_nsensors) {
SYSMON_ENVSYS_LOCK();
error = (*sme->sme_streinfo)(sme, binfo);
else
SYSMON_ENVSYS_UNLOCK();
} else
binfo->validflags = 0;
binfo->sensor = oidx;
sysmon_envsys_release(sme);