Subject: Re: Kernel threads
To: None <bharani.chadalavada@nexsi.com, tech-kern@netbsd.org>
From: Ben Harris <bjh21@netbsd.org>
List: tech-kern
Date: 04/02/2001 12:33:03
In article <3AC7E31A.A023716D@nexsi.com> you write:
>I am trying to port thr serial port to one of our custom chips. However
>due to some hardware bugs I cannot do a transmit to the serial port with
>interrupts disabled (like is done in comintr (/src/sys/dev/ic/com.c)).
>So, I was using kernel thread which executes out of interrupt context to
>write the actual bytes to the serial port. But I am running to a
>dead-lock problem. Basically the thread code looks like this...
>
>while(1)
>{
>    tsleep(&sync, ....);
>     write_bytes();
>    sync = 1;
>}
>
>And this thread gets woken up by comintr on transmit complete interrupt.
>
>wakeup(&sync);
>
>But hardware is so fast that I get the transmit complete interrupt
>before the thread executes sleep. So, I am losing interrupts.

The usual simple way around this would be to disable serial interrupts
before the call to write_bytes(), but you seem to say that's impossible.

How about something like this:

while (1) {
	flag = 0;
	write_bytes();
	s = splhigh();
	while (flag == 0)
		tsleep(&flag, ...);
	splx(s);
}

and in the interrupt routine:

flag = 1;
wakeup(&flag);

If the interrupt gets in between the write_bytes() and the splhigh(), it'll
just set the flag, which will cause the sleep not to happen.  Of course, you
can (and should) replace splhigh() with the right level to disable the
serial interrupts.

-- 
Ben Harris                                                   <bjh21@netbsd.org>
Portmaster, NetBSD/arm26               <URL:http://www.netbsd.org/Ports/arm26/>