linuxlinux-kernellinux-device-drivertasklet

Scheduling multiple tasklets in linux


I am new to tasklets in Linux. Here I am scheduling 3 tasklets in ISR. But what I observed is that only one tasklet in executed.

fill_buf->data=jiffies;
tasklet_schedule(fill_buf);
fill_buf->data=jiffies;
tasklet_schedule(fill_buf);
fill_buf->data=jiffies;
tasklet_schedule(fill_buf);

fill_buf is tasklet_struct and Linux version is 5.10.63.


Solution

  • You are scheduling the same tasklet three times in a row, but a tasklet can only be scheduled again if it has already run (or it is currently running).

    In fact, tasklet_schedule() checks the tasklet ->state and only schedules it if not already scheduled:

    static inline void tasklet_schedule(struct tasklet_struct *t)
    {
        if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
            __tasklet_schedule(t);
    }
    

    If you want to run the tasklet 3 times in a row, you can reschedule it from within itself:

    struct my_tasklet_data {
        unsigned n_runs;
        u64 jiffies;
    }
    
    void fill_buf(unsigned long data)
    {
        struct my_tasklet_data *td = (struct my_tasklet_data *)data;
    
        // Do what you need using td->jiffies ...
    
        // Reschedule for running if needed
        if (++td->n_runs < 3) {
            td->jiffies = get_jiffies_64();
            tasklet_schedule(fill_buf);
        }
    }
    
    /* Somewhere else in your code */
    
    struct my_tasklet_data data = {
        .jiffies = get_jiffies_64(),
        .n_runs = 0
    };
    
    fill_buf->data = (unsigned long)&data;
    tasklet_schedule(fill_buf);