softirq 処理はいつ行われるのか

イベント・呼び出し処理が行われる所
呼び出し元irq 処理の最後ksoftirqd
割り込み発生
(irq_exit())
×[*1][*1]
do_softirq()×: in_interrupt()[*2]
○: (!in_interrupt())
××: in_interrupt()[*2]
○: (!in_interrupt())
raise_softirq()
raise_softirq_irqoff()
××× in_interrupt()[*2]
○ (!in_interrupt())

○: 処理する。×: 処理しない。

[*1] CONFIG_IRQ_FORCED_THREADING が定義されて構築された kernel に起動パラメータ threadirqs が付加されている場合は、ksoftirqd で softirq 処理が行われます。CONFIG_IRQ_FORCED_THREADING が定義されていないか、定義されて構築された kernel に起動パラメータ threadirqs が付加されていない場合は、softirq 処理に時間が掛かった場合、処理しきれない分を ksoftirqd にて処理する。

[*2] 割り込み処理中なので、いずれ割り込みの処理の終わりになります。そして softirq は処理されます。

ksoftirqd はいつ働く

softirq 処理のために ksoftirqd thread が用意されています。ksoftirqd, softirq_threads 変数で状態を保持しています。ps uaxww コマンドでプロセスリストを表示すると ksoftirqd/0, ksoftirqd/1, ... のような名前で CPU の数と同じ数だけ並ぶ kernel thread です。

fileOpenGrok(linux-4.1.27/kernel/softirq.c:747)
Expand allFold all
747
748
749
750
751
752
-
|
|
|
|
!
static struct smp_hotplug_thread softirq_threads = {
        .store                  = &ksoftirqd,
        .thread_should_run      = ksoftirqd_should_run,
        .thread_fn              = run_ksoftirqd,
        .thread_comm            = "ksoftirqd/%u",
};

softirq 処理が ksoftirqd で行われるのは threadirqs kernel parameter 未指定で低負荷状態では稀です。ksoftirqd が使われる条件は __do_softirq() に実装されています。

fileOpenGrok(linux-4.1.27/kernel/softirq.c:253)
Expand allFold all
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
 
 
 
 
 
 
 
 
-
|
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
!
|
|
!
 
 
 
 
 
-
|
|
|
|
|
!
restart:
        /* Reset the pending bitmask before enabling irqs */
        set_softirq_pending(0);
 
        local_irq_enable();
 
        h = softirq_vec;
 
        while ((softirq_bit = ffs(pending))) {
                unsigned int vec_nr;
                int prev_count;
 
                h += softirq_bit - 1;
 
                vec_nr = h - softirq_vec;
                prev_count = preempt_count();
 
                kstat_incr_softirqs_this_cpu(vec_nr);
 
                trace_softirq_entry(vec_nr);
                h->action(h);
                trace_softirq_exit(vec_nr);
                if (unlikely(prev_count != preempt_count())) {
                        pr_err("huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?\n",
                               vec_nr, softirq_to_name[vec_nr], h->action,
                               prev_count, preempt_count());
                        preempt_count_set(prev_count);
                }
                h++;
                pending >>= softirq_bit;
        }
 
        rcu_bh_qs();
        local_irq_disable();
 
        pending = local_softirq_pending();
        if (pending) {
                if (time_before(jiffies, end) && !need_resched() &&
                    --max_restart)
                        goto restart;
 
                wakeup_softirqd();
        }

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS