Telling a thread to do something

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.