Subject: Re: Kernel threads
To: Bharani Chadalavada <bharani.chadalavada@nexsi.com>
From: Wayne Knowles <wdk@NetBSD.ORG>
List: tech-kern
Date: 04/02/2001 22:39:09
On Sun, 1 Apr 2001, Bharani Chadalavada wrote:

> 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)).

Bharani,

That is a strange hardware bug.  Care to share more details??
Do we have the wrong edge or level triggering the interrupt??

> 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.

You might want to try using soft interrupts instead of the sleep/wakeup
mechanism - it has lower overheads and a faster service time.

In the interrupt handler replace the wakeup call with setsoftserial 
(or softintr_schedule if the platform supports generic software interrupts
such as the alpha) - perhaps set a flag in the softc structure to say a
transmit buffer interrupt is pending.

In the soft interrupt handler you can test for the transmit buffer
condition and call write_bytes.  If you are worried about transmit
interrupts re-occuring you can feed it from a loop:

in comintr:
	...
	sc->sc_tbe_pending = 1;
	setsoftserial();  /* see dev/ic/com.c for this part */ 
	...

in comsoft:
	...
	while (sc->sc_tbe_pending) {
		sc->sc_tbe_pending = 0;
		write_bytes();
	}
	...

> 
> I was wondering if anyone encountered some problem like this. And if
> there are some synchronisation mechanisms between threads. Basically
> I need to wake up the thread only if it is not sleeping. And if it is
> already executing I need to wait till it sleeps and then wake it up.
> 
> Is something like this doable??

This can be done using a flag or semaphore to signal the state between
the two parts of the code, but you need an atomic update at splhigh() or
the highest processor level that updates the flag which may be splserial()
in order to avoid race conditions/lost inetrrupts....

Personally I would have a crack at the softintr solution first.

Wayne.