4.1.1. Asynchronous Requests

4.1.1.1. Example: Linux Tasklets

The interrupt handling code in the kernel is not reenterant. When an interrupt handler executes, additional interrupts are disabled and a statically allocated stack is used. This simplifies the code but also implies that interrupt handling must be short lest the ability of the kernel to respond to an interrupt promptly is affected. The kernel offers four related tools to postpone work done while servicing an interrupt, called soft irqs, tasklets, bottom half handlers and work queues.

Soft irqs are functions whose execution can be requested from within an interrupt handler. All pending soft irqs are executed by the kernel on return from an interrupt handler with additional interrupts enabled. Soft irqs that were raised again after return from an interrupt handler are executed by a kernel thread called ksoftirqd. A soft irq can execute simultaneously on multiple processors. The number of soft irqs is limited to 32, soft irqs are used within the kernel for example to update kernel timers and handle network traffic.

Two soft irqs are dedicated to executing low and high priority tasklets. Unlike a handler of a soft irq, a handler of a tasklet will only execute on one processor at a time. The number of tasklets is not limited, tasklets are the main tool to be used for scheduling access to resources within the kernel.

Finally, bottom half handlers are implemented using tasklets. To preserve backward compatibility with old kernels, only one bottom half handler will execute at a time. Bottom half handlers are deprecated.

When executed on return from an interrupt handler, soft irqs are not associated with any thread and therefore cannot use passive waiting. Since tasklets and bottom half handlers are implemented using soft irqs, the same constraint applies there as well. When passive waiting is required, work queues must be used instead. A work queue is similar to a tasklet but is always associated with a kernel thread, trading the ability to execute immediately after an interrupt handler for the ability to wait passively.

[ This information is current for kernel 2.6.23. ]

References. 

  1. Matthew Wilcox: I’ll Do It Later: Softirqs, Tasklets, Bottom Halves, Task Queues, Work Queues and Timers.

4.1.1.2. Example: Windows Deferred Procedure Calls

Windows kernel provides the option of postponing work done while servicing an interrupt through the deferred procedure call mechanism. The interrupt service routine can register a deferred procedure call, which gets executed later. The decision when to execute a deferred procedure call depends on the importance of the call, the depth of the queue and the rate of the interrupts.

// Registers DPC for a device
VOID IoInitializeDpcRequest (
  IN PDEVICE_OBJECT DeviceObject,
  IN PIO_DPC_ROUTINE DpcRoutine
);

// Schedules DPC for a device
VOID IoRequestDpc (
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  IN PVOID Context
);

// DPC
VOID DpcForIsr (
  IN PKDPC Dpc,
  IN struct _DEVICE_OBJECT *DeviceObject,
  IN struct _IRP *Irp,
  IN PVOID Context
);

4.1.1.3. Example: Solaris Pinned Threads

Solaris obsluhuje přerušení ve vyhrazených vláknech. Protože inicializace vlákna při přerušení by byla dlouhá, používají se interrupt threads jako omezená varianta kernel threads. Při přerušení se aktivní vlákno označí jako pinned thread, což znamená, že se uspí, ale že nemůže být naplánováno na jiný procesor, protože jeho kontext není úplně uschován. Spustí se interrupt thread, který obslouží přerušení, po jeho ukončení se vzbudí pinned thread. Pokud by interrupt thread zavolal funkci, která ho potřebuje uspat, systém ho automaticky konvertuje na kernel thread, ten uspí a vzbudí pinned thread.