Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!umcp-cs!chris From: chris@umcp-cs.UUCP (Chris Torek) Newsgroups: net.unix-wizards Subject: Re: DELAY Message-ID: <3744@umcp-cs.UUCP> Date: Wed, 8-Oct-86 02:46:09 EDT Article-I.D.: umcp-cs.3744 Posted: Wed Oct 8 02:46:09 1986 Date-Received: Wed, 8-Oct-86 20:13:21 EDT References: <4393@brl-smoke.ARPA> Reply-To: chris@umcp-cs.UUCP (Chris Torek) Organization: University of Maryland, Dept. of Computer Sci. Lines: 96 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@brl-smoke.ARPA> mike@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@umcp-cs ARPA: chris@mimsy.umd.edu