DELAY
Chris Torek
chris at umcp-cs.UUCP
Wed Oct 8 16:46:09 AEST 1986
I never saw the original article, but I can guess at the problem
being solved. Mike's advice is accurrate, but, I think, overcautious:
In article <4393 at brl-smoke.ARPA> mike at BRL.ARPA (Mike Muuss) writes:
>driver_close()
>{
> /* Shut down the DACs here */
> timeout( &driver_close, 2*HZ );
(That should be `close_timeout', not `&driver_close', and the routine
must be declared above.)
> s = spl6(); /* protect against races */
> dac_wait = 1;
> while( dac_wait )
> sleep( &dac_wait, PZERO );
> splx(s);
> /* Handle final cleanups */
>}
>
>close_timeout()
>{
> dac_wait = 0;
> wakeup( &dac_wait );
>}
>(Check the arguments to sleep() and timeout() carefully for the version
>of UNIX that you are using -- the above code is just to give you the
>"flavor" of this operation).
I might go so far as to say that every Unix will do them the same
way, but no doubt someone out there has made some incompatible
changes to its semantics *without* changing the name. . . .
>The sleep() routine causes this process to be de-selected, and a context
>switch to another process to occur. ... The loop around the sleep() is
>generally very important -- there are no guarantees that the sleep()
>will not return from some other cause (event) than the one you are
>expecting, so be certain to wait for the intended condition to happen.
There *are* some guarantees. The sleep() will return only when
someone does a wakeup() on the exact same value as the first argument
to sleep(), OR when a signal occurs, provided the second argument
was greater than PZERO. As Mike cautioned, though, your kernel
vendor just might have broken this.
>Note that when sleep() context switches, it drops the high spl.
>When the sleeping context is resumed by wakeup(), the high spl
>is restored for you at the right point in the context switch.
(`Drops the high ipl' sounds better. IPL stands for Interrupt
Priority Level; spl stands for `set priority level'. At least,
that is my best guess as to what it stands for . . . .)
Anyway, I would use---in fact, I have already used, in similar
cases---the following:
/* DAC driver */
struct dac_softc {
int sc_flags; /* e.g., exclusive use opens */
...
} dac_softc[NDAC];
...
#define DACPRI (PZERO - 1) /* adjust as appropriate */
extern int hz;
int wakeup();
#define dacunit(dev) minor(dev)
...
/*
* Close a DAC.
*/
/*ARGSUSED*/
dacclose(dev, flag)
dev_t dev;
{
register struct dacdevice *dac;
register struct dac_softc *sc;
dac = (struct dacdevice *) dacinfo[dacunit(dac)]->ui_addr;
sc = &dac_softc[dacunit(dac)];
sc->sc_flags |= SC_SHUTDOWN; /* mark shutdown in progress */
dac->dac_foo = DAC_SHUTDOWN; /* shut down DAC */
timeout(wakeup, (caddr_t) sc, hz * 2);
sleep((caddr_t) sc, DACPRI); /* wait two seconds */
dac->dac_foo = 0; /* then release it */
sc->sc_flags = 0; /* mark closed */
}
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP: seismo!umcp-cs!chris
CSNet: chris at umcp-cs ARPA: chris at mimsy.umd.edu
More information about the Comp.unix.wizards
mailing list