How does an ISR tell the kernel that it should now schedule a thread to do some work? (And conversely, how does it tell the kernel that it shouldn't do that?)
Here's some pseudo-code for a typical ISR:
FUNCTION ISR BEGIN determine source of interrupt clear source of interrupt IF thread required to do some work THEN RETURN (event); ELSE RETURN (NULL); ENDIF END
The trick is to return an event (of type struct sigevent, which we talked about in the Clocks, Timers, and Getting a Kick Every So Often chapter) instead of NULL. Note that the event that you return must be persistent after the stack frame of the ISR has been destroyed. This means that the event must be declared outside of the ISR, or be passed in from a persistent data area using the area parameter to the ISR, or declared as a static within the ISR itself. Your choice. If you return an event, the kernel delivers it to a thread when your ISR returns. Because the event alerts a thread (via a pulse, as we talked about in the Message Passing chapter, or via a signal), this can cause the kernel to reschedule the thread that gets the CPU next. If you return NULL from the ISR, then the kernel knows that nothing special needs to be done at thread time, so it won't reschedule any threads—the thread that was running at the time that the ISR preempted it resumes running.