Re: Event handlers

From: Andy Valencia <vandys_at_nospam.org>
Date: Sun Dec 17 2000 - 16:25:49 PST

[Eric Jacobs <eaj@ricochet.net> writes:]

>I've been thinking about trying to get the Linux drivers to run
>as a user process. To simulate hardware interrupts, an obvious
>approach is to use notify, but in event.c:
>
> * A process has two distinct incoming streams
> * of events--a process-generated one and a system-generated one.
> * The system events take precedence. For process events, a sender
> * will sleep until the target process has accepted a current event and
> * (if he has a handler registered) returned from the handler.
>
>If the sender blocks, we'd have to use multiple threads to
>simulate re-entrant interrupts, which could be kind of clumsy.

You should use a thread to accept the ISR message. From there, I'd suggest
just running the ISR code directly from that thread. There's no reason to
suspend executing the ISR code to service the same ISR.

If there's something long enough that you feel you need to get back to
waiting for front-line ISR's, you should use mutex_thread() to kick awake a
background thread to do the rest of the work.

>But I don't see any code to actually make it do this. It looks as
>though the sender doesn't block at all and the receiver just
>picks up the event the next time it enters the kernel.

See signal_thread(), for the EGAIN case right near the top of the routine.

>Actually, having it asynchronous like that would be more suitable
>for simulating interrupts. I'm thinking of a scenario where we have
>N shepherd threads that all block on msg_receive(), synchronize with
>the global lock and then jump into the driver. When an interrupt
>message is received, we can notify the currently running thread
>(which itself may be in an interrupt.) The interrupted thread would
>be "wasted" for the duration of that interrupt handler, of course,
>but I see no reason why the interruptor thread should be similarly
>held up (it could go back for more interrupts, or at least get the
>next request set up.) Am I on the right track here?

Usually a single driver will handle a single ISR source. If this comes to a
unique port (see how mach/rs232 does this) you avoid priority inversions
with the clients of the driver. But so long as you you use a single thread,
you're implicitly serialized for interrupt handling, and thus don't have to
weigh down your design with lots of locks.

When the ISR code is done with its part and wants to kick some work to the
"top half" of the driver, it does it by way of mutex_thread() (rather than
just sending a message to the main message queue, again to avoid priority
inversion with other work the top half code may be executing at any given
time). The thread waiting for this wakeup can either handle the work, or
*it* turns it into a message to the main queue (which is what the RS-232
driver does), because it's OK for this slave to get blocked on the main
message queue--it's just the ISR code we don't want to have hung.

You really, really don't want to try and run a single process which
represents all of the Linux drivers collectively. Each individual driver
should be linked into an emulation environment which runs as its own
distinct process. Then you're generally looking at one ISR source, and if
you map it to one thread, things simplify nicely.

Andy Valencia
Received on Sun Dec 17 16:16:50 2000

This archive was generated by hypermail 2.1.8 : Thu Sep 22 2005 - 15:12:57 PDT