0

I write simple code to test the function of tasklet.

When I don't do tasklet_kill, the kernel will be hang after the insmod command is using. Since there is no log, I have no idea what happens.

The following is my code.

void work_fcn(unsigned long a)
{
    printk("this is tasklet work function\n");
}

void tasklet_test(void)
{
    struct tasklet_struct task;
    tasklet_init(&task, work_fcn, 0);
    tasklet_schedule(&task);
    //if I don't do the following line, then kernel hang
    tasklet_kill(&task); 
}

static int __init hello_init(void)
{
     tasklet_test();
     return 0;
}

module_init(hello_init);

Thanks.

Anakin Tung
  • 419
  • 5
  • 17
  • 1
    Tasklets are a little routines that are dedicated to run in bottom half (AKA soft IRQ mode) which you apparently don't have here. Better to read available documentation or even source code. Besides that you are using variables on a stack. Imagine what happens to them when you left function. – 0andriy Oct 11 '15 at 14:54
  • OK~ I'll check the related document. The stack variable is really a bug! thanks! I know that tasklet and softirq are running in bottom half. When we have a interrupt, the interrupt handler may use tasklet to defer some of work. So here I just do the same such thing, deferring the work, should't that valid? – Anakin Tung Oct 11 '15 at 15:05
  • That's valid, though preferred (by some of the maintainer / developers) is to use threaded IRQ handle mechanism. – 0andriy Oct 11 '15 at 16:07

1 Answers1

0
static void tasklet_action_common(struct softirq_action *a,
                  struct tasklet_head *tl_head,
                  unsigned int softirq_nr)
{
...

    while (list) {
        struct tasklet_struct *t = list;

        list = list->next;

        if (tasklet_trylock(t)) {
            if (!atomic_read(&t->count)) {
                if (!test_and_clear_bit(TASKLET_STATE_SCHED,
                            &t->state)) //<===========(1)
                    BUG();
                t->func(t->data);
                tasklet_unlock(t);
                continue;
            }
            tasklet_unlock(t);
        }

...
    }
}

In the comment (1), it checks if the tasklet status is TASKLET_STATE_SCHED, and if so, it will panic.

void tasklet_kill(struct tasklet_struct *t)
{
    if (in_interrupt())
        pr_notice("Attempt to kill tasklet from interrupt\n");

    while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
        do {
            yield();
        } while (test_bit(TASKLET_STATE_SCHED, &t->state));
    }
    tasklet_unlock_wait(t);
    clear_bit(TASKLET_STATE_SCHED, &t->state); //<=========(2)
}
EXPORT_SYMBOL(tasklet_kill);

In the comment (2)will clear TASKLET_STATE_SCHED bit,that will not panic.

Joeys
  • 21
  • 4