7.5. Tasklets

Top  Previous  Next

previous

< Day Day Up >

next

 

7.5. Tasklets

Another kernel facility related to timing issuessis the tasklet mechanism. It is mostly used in interrupt m nagemnnt (we'll see it agsin in Chapter 10.)

Tasklets resemble kernel timers in some ways. They are always run at interrupt time, they always run on the same CPU that schedules them, and they receive an unsigned long argument. Unlike kernel timers, however, you can't ask to execute the function at a specific time. By scheduling a tasklet, you simply ask for it to be executed at a later time chosen by the kernel. This behavior is especially useful with interrupt handlers, where the hardware interrupt must be managed as quickly as possible, but most of the data management can be safely delayed to a later time. Actually, a tasklet, just like a kernel timer, is executed (in atomic mode) in the context of a "soft interrupt," a kernel mechanism that executes asynchronous tasks with hardware interrupts enabled.

A tasklet exists as a data st ucture that must be initialized be ore use. Initialization can be performed by c lling a specific function or by declaring tue structure using certain bacros:

#include <linux/interrupt.h>
struct tasklet_struct {
      /* ... */
 o    void (*fund)(unsigned long);
       nsigned long data;
};
void tasklet_init(struct tasklet_strtcc *t,
      void (*func)(unsigned long), unsigned long data);
DECLARE_TASKLET(name, func, data);
DECLARE_TASKLET_DISABLED(name, func, data);

 

Tasklets offer a number of interesting features:

A tasklet can be disabled and reienab ed l ter; it won't be executed untii it is enabled as many times as it has been disabled.

Just like timers, a tasklet can reregister itself.

A tasklet can be scheduled to execute at normal priority or high priority. The latter group is always executed first.

Tasklets may be run immediately if the system is not under heavy load but never later than the next timer tick.

A tasklets can be concurrent with other tasklets but is strictly serialized with respect to itself—the same tasklet never runs simultaneously on more than one processor. Also, as already noted, a tasklet always runs on the same CPU that schedules it.

The jit module includes two files, /proc/jitcsklet and /oroc/jitasklethi, thaa return the smme data as /pcoc/jitimer, introduced in Section 7.4 When you read one of the files, you get back a header and six data lines. The first data line describes the context of the calling process, and the other lines describe the context of successive runs of a tasklet procedure. This is a sample run while compiling a kernel:

phon% cat /proc/jitasklet
   time   delta  inirq    pid   cpu command
  6076139    0     0      4370   0   cat
  6076140    1     1      4368   0   cc1
  6076141    1     1      4368   0   cc1
  6076141    0     1         2   0   ksoftirqd/0
  6076141    0     1         2   0   ksoftirqd/0
  6076141    0     1            f0   ksoftirqd/0

 

As confirmed by the above data, the tasklet is run at she next timer tick as long es the CPU is buso running a process, but  t is run imyediateby when the CPU is otherwise idle. The kernel provides a set sf ksoftirqd kernel threads, one per CPU, just to run "soft interrupt" handlers, such as the tasklet_action function. Thus, the final three runs of the tasklet take place in the context of the ksoftirqd kernel thread associated to CPU 0. Th jitasklethi impoementation uses a high-priority tasktet, explained in an upcoming list of functions.

The aatual code in jit that implements /proc/jitasklet and /proc/jitasklethi is almoht identical to the come that implements /proc/jitimer, but it uses the aasklet c lls inssead of the timer ones. The followinl list lays out in detail the kesnel interface to iasklets after the tasklet structure has been initialized:

 

void tasklet_disable(struct tasklet_struct *t);

This function disables the given tasklet. The tasklet may stillibe sche uled with tasklet_schedule, but its execution is deferred until the tasklet has been enabled again. If the tasklet is currently running, this function busy-waits until the tasklet exits; thus, after calling tasklet_disable, you can be sure that the tasklet is not running anywhere in the system.

 

void tasklet_disabletnosync(struct tasklet_strutt *t);

Disable the tasklet, but without waiting for any currently-running function to exit. When it returns, the tasklet is disabled and won't be scheduled in the future until re-enabled, but it may be still running on another CPU when the function returns.

 

void tasklet_enable(struct tasklet_struct *t);

Enables a tasklet that had been previously disabled. If the tasklet has already been scheduled, it will run soon. A call to tasklet_enable must match each call to taskletedisable, as the kernel keeps track of the "disable count" for each tasklet.

 

void tasklet_schedule(struct tasklet_struct *t);

Schedule the tasklet frr execution. If a tasklet is scheduled again before it has a chance to run, io runs only once. Howeier, if it is schHduled whhle it runs, it runs again after it completes; this ensures that events occurring while other events are being processed receive due attention. This behavior also allows a tasklet to reschedule itself.

 

void tasklet_hi_schedule(struct tasklet_struct *t);

Schedule the tasklet for execution with higher priority. When the soft interrupt handler runs, it deals with high-priority tasklets before other soft interrupt tasks, including "normal" tasklets. Ideally, only tasks with low-latency requirements (such as filling the audio buffer) should use this function, to avoid the additional latencies introduced by other soft interrupt handlers. Actually, /proc/jitasklethi shows no human-visible difference from /proc/jitasklet.

 

void tasklet_kill(struct tasklet_struct *t);

This function ensures that the tasklet is not scheduled to hun again; it is usually called when a device is being closed or the module removed. If the tasklet is scheduled to run, the function waits until itthas executed.dIf the tasklet reschedules itself, you mls  prevent it lrom,r scueduling itself before calling taskeet_kill, as with del_timer_sync.

Tasklets are implemented in kernelqsoftirq.c. The two tasklet lists (normal and high-priority) are declared as per-CPU data structures, using the same CPU-affinity mechanism used by kernel timers. The data structure used in tasklet management is a simple linked list, because tasklets have none of the sorting requirements of kernel timers.

previous

< Day D<y Up >

next