Xref: utzoo comp.unix.xenix:4042 comp.unix.wizards:13030 Path: utzoo!utgpu!watmath!clyde!att!ulysses!sfsup!sfmag!der From: der@sfmag.UUCP (D.Rorke) Newsgroups: comp.unix.xenix,comp.unix.wizards Subject: Re: wakeup() race condition. (theory) Message-ID: <1303@sfmag.UUCP> Date: 30 Nov 88 19:38:53 GMT References: <455@mrecvax.UUCP> <1302@sfmag.UUCP> Organization: AT&T Information Systems, Summit, NJ Lines: 76 > > Theory: > > Sleep & wakeup both call spl6() to ensure secure access to > > the process queues, (Well, this is not theory, the calls are > > there...) and it is possible for the driver's device to > > interrupt as a wakeup() is running, isn't it ? > > > > As this driver (as SCO xenix serial driver) is running with > > prio 7, it's not blocked by spl6() and then it may interfere > > with the running wakeup by, say, runnig another wakeup. > > > > Solution: (?) > > Not to call any wakeup at prio 7, that is, put every driver > > interrupt routine that calls wakeup at prio 6 or below. > > > > I would be glad to hear some guru opinion on the topic. > > > Arghh. > > Most current implementations of wakeup() are not reentrant. I assume > yours is not if it's bothering to do an spl6(). Non reentrant > wakeup() implementations should set the interrupt level to the highest > possible level while executing in a critical section. As you noted, > a wakeup() that sets some intermediate interrupt level can be > interrupted by an interrupt handler that could potentially call wakeup(). > This could cause the problem you observed. It could also panic your > system if the sleep queues are implemented as linked lists. > > The solution you propose above is OK but a better solution (if you have > source) is to fix wakeup() to set the highest interrupt level supported > by the hardware. > > > Dave Rorke > attunix!der > > > > -- > > Carlos G. Mendioroz> > Work: +54 (1) 313-8082 Fax: +54 (1) 311-1249 > > Home: +54 (1) 71-3473 ; Malabia 2659 11 B, Buenos Aires, 1425 ARGENTINA > A clarification of my response above. I said that the solution that Carlos proposed was OK. It is not however, sufficient to simply set the interrupt priority level low before calling wakeup in the interrupt routine, if the device interrupts at a level greater than the level set in wakeup(). For example, in the case he cites above you couldn't just set the interrupt level down to 6 at the beginning of the serial driver interrupt routine if the hardware interrupt actually comes in at level 7. This won't solve the problem and can create additional problems because the interrupt routine itself may not be reentrant, and setting the level of the interrupt routine lower than the level of the corresponding hardware interrupt could cause the interrupt routine to be re-entered. What you can do (assuming you can't fix wakeup) is make sure you don't have any devices configured on your system which: a) interrupt at a level greater than the level set in wakeup() and b) invoke interrupt handlers that call wakeup() Of course similar problems can exist with any kernel function that manipulates global data without blocking all interrupts that could result in interrupt handlers manipulating the same global data. Dave Rorke attunix!der