7

I would like to create my own softirq in linux kernel. Is it the right way to do that:

In the init of the module I would like to trigger the softirq from I'll add a call to:

394 void open_softirq(int nr, void (*action)(struct softirq_action *))
395 {
396         softirq_vec[nr].action = action;
397 }

And in the snippet I would like to raise the softirq I'll add a call to raise_softirq function:

379 void raise_softirq(unsigned int nr)
380 {
381         unsigned long flags;
382 
383         local_irq_save(flags);
384         raise_softirq_irqoff(nr);
385         local_irq_restore(flags);
386 }

And add my new softirq in:

411 /* PLEASE, avoid to allocate new softirqs, if you need not _really_ high
412    frequency threaded job scheduling. For almost all the purposes
413    tasklets are more than enough. F.e. all serial device BHs et
414    al. should be converted to tasklets, not to softirqs.
415  */
416 
417 enum
418 {
419         HI_SOFTIRQ=0,
420         TIMER_SOFTIRQ,
421         NET_TX_SOFTIRQ,
422         NET_RX_SOFTIRQ,
423         BLOCK_SOFTIRQ,
424         BLOCK_IOPOLL_SOFTIRQ,
425         TASKLET_SOFTIRQ,
426         SCHED_SOFTIRQ,
427         HRTIMER_SOFTIRQ,
428         RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */
429         MY_NEW_SOFTIRQ
430         NR_SOFTIRQS
431 };

And in here:

 60 char *softirq_to_name[NR_SOFTIRQS] = {
 61         "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL",
 62         "TASKLET", "SCHED", "HRTIMER", "RCU", "MY_NEW_SOFTIRQ"
 63 };

The questions:

  • Am I right or did I miss something?
  • Is it the right way to do that? any other options?
0x90
  • 39,472
  • 36
  • 165
  • 245
  • 2
    I've never added a new softirq, but it looks about right. Of course, you should read the comment around line 411 in your quoted code! – Mats Petersson Jan 13 '13 at 10:12
  • 3
    and you should probably read the comment on line 428 as well. – marko Jan 13 '13 at 10:30
  • 2
    beware, if your softirq number is larger than RCU_SOFTIRQ, meaning it will be soft-scheduled only after RCU_SOFTIRQ is scheduled, then it may possible you will never be scheduled, if RCU lockings happens frequently enough. – Peter Teoh Jan 14 '13 at 05:53
  • i don't think that is the right way to do it - as a kernel module. the softirq scheduler is all the time running, on different CPU concurrently. if u just suddently add in an additional softirq number, and replicate it through to all CPU - there are lots of work involved here: including stopping each CPU and modifying its softirq schedule queue. so the right way is to modify the kernel source and regenerate a new kernel image, NOT kernel module. – Peter Teoh Jan 14 '13 at 06:00

2 Answers2

1

If you want to patch the kernel and recompile it, you are doing probably right (except you should move it before RCU_SOFTIRQ).

Otherwise, IOW if you want to do it in a kernel module, you have to use tasklet, which is based on SoftIRQ, to do something in SoftIRQ context:

tasklet_init() is used to init your hook.

tasklet_schedule() to schedule the tasklet you register.

Cong Wang
  • 2,001
  • 12
  • 13
0

Declare Softirq statically

Statically declare your softirq(MY_NEW_SOFTIRQ) by adding it to the enum and
char *softirq_to_name[NR_SOFTIRQS]. Recompile the kernel.

Register Softirq on the fly

Once statically declared, Our own softirq should be registered during the run time in the kernel module using open_softirq(). Raise it in the interrupt handler's exit path via raise_softirq().

rstnsrrao
  • 43
  • 6