1. Tasklet的处理
在上一博客有关软中断的处理中,TASKLET_SOFTIRQ对应的处理函数 tasklet_action。
kernel/softirq.c
476 static void tasklet_action(struct softirq_action *a)
477 {
478 struct tasklet_struct *list;
479
480 local_irq_disable();
481 list = __this_cpu_read(tasklet_vec.head);
482 __this_cpu_write(tasklet_vec.head, NULL);
483 __this_cpu_write(tasklet_vec.tail, &__get_cpu_var(tasklet_vec).head);
484 local_irq_enable();
485
486 while (list) {
487 struct tasklet_struct *t = list;
488
489 list = list->next;
490
491 if (tasklet_trylock(t)) {
492 if (!atomic_read(&t->count)) {
493 if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
494 BUG();
495 mt_trace_tasklet_start(t->func);
496 t->func(t->data);
497 mt_trace_tasklet_end(t->func);
498 tasklet_unlock(t);
499 continue;
500 }
501 tasklet_unlock(t);
502 }
503
504 local_irq_disable();
505 t->next = NULL;
506 *__this_cpu_read(tasklet_vec.tail) = t;
507 __this_cpu_write(tasklet_vec.tail, &(t->next));
508 __raise_softirq_irqoff(TASKLET_SOFTIRQ);
509 local_irq_enable();
510 }
511 }
491 试图上锁,意味着同时只有一个tasklet在工作。
496 调用相应的处理函数。
504-509 上锁不成功,重新加入队列,触发TASKLET_SOFTIRQ软中断。
2. tasklet接口函数
549 void tasklet_init(struct tasklet_struct *t,
550 void (*func)(unsigned long), unsigned long data)
551 {
552 t->next = NULL;
553 t->state = 0;
554 atomic_set(&t->count, 0);
555 t->func = func;
556 t->data = data;
557 }
设置相应的成员
static inline void tasklet_schedule(struct tasklet_struct *t)
{
if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
__tasklet_schedule(t);
}
437 void __tasklet_schedule(struct tasklet_struct *t)
438 {
439 unsigned long flags;
440
441 local_irq_save(flags);
442 t->next = NULL;
443 *__this_cpu_read(tasklet_vec.tail) = t;
444 __this_cpu_write(tasklet_vec.tail, &(t->next));
445 raise_softirq_irqoff(TASKLET_SOFTIRQ);
446 local_irq_restore(flags);
447 }
加入tasklet列表,触发TASKLET_SOFTIRQ软中断。
561 void tasklet_kill(struct tasklet_struct *t)
562 {
563 if (in_interrupt())
564 printk("Attempt to kill tasklet from interrupt\n");
565
566 while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
567 do {
568 yield();
569 } while (test_bit(TASKLET_STATE_SCHED, &t->state));
570 }
571 tasklet_unlock_wait(t);
572 clear_bit(TASKLET_STATE_SCHED, &t->state);
573 }