Safe functions

When the ISR is servicing the interrupt, it can't make any kernel calls (except for the few that we'll talk about shortly). This means that you need to be careful about the library functions that you call in an ISR, because their underlying implementation may use kernel calls.

Note: For a list of the functions that you can call from an ISR, see the Full Safety Information appendix in the C Library Reference.

Here are the only kernel calls that the ISR can use:

You'll also find these functions (which aren't kernel calls) useful in an ISR:

Let's look at these functions.

To prevent a thread and ISR from interfering with each other, you'll need to tell the kernel to disable interrupts. On a single-processor system, you can simply disable interrupts using the processor's “disable interrupts” opcode. But on an SMP system, disabling interrupts on one processor doesn't disable them on another processor.

The function InterruptDisable() (and the reverse, InterruptEnable()) performs this operation on a single-processor system. The function InterruptLock() (and the reverse, InterruptUnlock()) performs this operation on an SMP system, but combines it with a spin lock to synchronize across cores as well.

Note: We recommend that you always use the SMP versions of these functions—this makes your code portable to SMP systems, with a negligible amount of overhead.

The InterruptMask() and InterruptUnmask() functions disable and enable the PIC's recognition of a particular hardware IRQ line. These calls are useful if your interrupt handler ISR is provided by the kernel via InterruptAttachEvent() or if you can't clear the cause of the interrupt in a level-sensitive environment quickly. (This would typically be the case if clearing the source of the interrupt is time-consuming—you don't want to spend a lot of time in the interrupt handler.) In this case, the ISR would call InterruptMask() and schedule a thread to do the actual work. The thread would call InterruptUnmask() when it had cleared the source of the interrupt.

Note that these two functions are counting; InterruptUnmask() must be called the same number of times as InterruptMask() in order to have the interrupt source considered enabled again.

The TraceEvent() function traces kernel events; you can call it, with some restrictions, in an interrupt handler. For more information, see the System Analysis Toolkit User's Guide.