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