# 인터럽트 후반부 처리
softirq_vec 변수를 확인하면, __do_softirq() 에서 h->action로 호출되는 함수의 정체를 확인할 수 있습니다.
crash> p softirq_vec
softirq_vec = $2 =
{{
action = 0xc01289ac <tasklet_hi_action>
}, {
action = 0xc0180334 <run_timer_softirq>
}, {
action = 0xc0d55d7c <net_tx_action>
}, {
action = 0xc0d58238 <net_rx_action>
}, {
action = 0xc038123c <blk_done_softirq>
}, {
action = 0xc03817f8 <blk_iopoll_softirq>
}, {
action = 0xc0128a98 <tasklet_action>
}, {
action = 0xc015b198 <run_rebalance_domains>
}, {
action = 0xc0182c60 <run_hrtimer_softirq>
}, {
action = 0xc017a974 <rcu_process_callbacks>
}}
아래 패치를 추가하고, "echo 1 > /d/tracing/events/irq/enable" 설정으로 soft irq ftrace log를 확인하면 실제 실행되는 함수를 tracing할 수 있습니다.
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 0c998ef..5d6dfa3 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -241,6 +241,7 @@ asmlinkage __visible void __do_softirq(void)
__u32 pending;
int softirq_bit;
+ void *cb_func;
/*
* Mask out PF_MEMALLOC s current task context is borrowed for the
* softirq. A softirq handled such as network RX might set PF_MEMALLOC
@@ -274,6 +275,11 @@ restart:
kstat_incr_softirqs_this_cpu(vec_nr);
trace_softirq_entry(vec_nr);
+
+ cb_func = (void*)h->action;
+ trace_printk("[++][PompeiiGrace][%s][%s,%d]: caller: (%pS) h->action[%pF]\n",
+ current->comm, __func__,__LINE__, (void *)__builtin_return_address(0), cb_func);
+
h->action(h);
trace_softirq_exit(vec_nr);
if (unlikely(prev_count != preempt_count())) {
ftrace log를 해석해보죠.
[1]: irq=20 name=arch_mem_timer IRQ가 Trigger됩니다.
[2]: soft irq(run_timer_softirq/run_rebalance_domains/rcu_process_callbacks)를 raise합니다.
[3]: @__handle_domain_irq, irq=20 name=arch_mem_timer IRQ가 종료됩니다.
[4]: @__handle_domain_irq: irq_exit를 호출하여 softirq가 시작됩니다.
[5]: [action=TIMER] run_timer_softirq 수행합니다.
[6]: [action=SCHED] run_rebalance_domains 수행합니다.
[7]: [action=RCU] rcu_process_callbacks 수행합니다.
<idle>-0 [004] d.h2 107.990285: irq_handler_entry: irq=20 name=arch_mem_timer //<<--[1]
<idle>-0 [004] d.h3 107.990313: softirq_raise: vec=1 [action=TIMER] //<<--[2]
<idle>-0 [004] d.h3 107.990318: softirq_raise: vec=9 [action=RCU] //<<--[2]
<idle>-0 [004] d.h3 107.990327: softirq_raise: vec=7 [action=SCHED] //<<--[2]
<idle>-0 [004] d.h2 107.990345: irq_handler_exit: irq=20 ret=handled //<<--[3]
<idle>-0 [004] d.h1 107.990359: irq_exit: [+][Pompeii][swapper/4][irq_exit,398]: caller: (__handle_domain_irq+0x80/0xa0) //<<--[4]
<idle>-0 [004] ..s2 107.990363: softirq_entry: vec=1 [action=TIMER] //<<--[5]
<idle>-0 [004] ..s1 107.990367: __do_softirq: [++][PompeiiGrace][swapper/4][__do_softirq,281]: caller: (irq_exit+0xac/0x118) h->action[run_timer_softirq+0x0/0x5ac]
<idle>-0 [004] .ns2 107.990398: softirq_exit: vec=1 [action=TIMER]
<idle>-0 [004] .ns2 107.990400: softirq_entry: vec=7 [action=SCHED] //<<--[6]
<idle>-0 [004] .ns1 107.990403: __do_softirq: [++][PompeiiGrace][swapper/4][__do_softirq,281]: caller: (irq_exit+0xac/0x118) h->action[run_rebalance_domains+0x0/0x1d8]
<idle>-0 [004] .ns2 107.990426: softirq_exit: vec=7 [action=SCHED]
<idle>-0 [004] .ns2 107.990428: softirq_entry: vec=9 [action=RCU] //<<--[7]
<idle>-0 [004] .ns1 107.990431: __do_softirq: [++][PompeiiGrace][swapper/4][__do_softirq,281]: caller: (irq_exit+0xac/0x118) h->action[rcu_process_callbacks+0x0/0x644]
<idle>-0 [004] .ns2 107.990438: softirq_exit: vec=9 [action=RCU]
이후 raise_softirq-> raise_softirq_irqoff 순서로 API 호출이 이루어집니다.
void raise_softirq(unsigned int nr)
{
unsigned long flags;
local_irq_save(flags);
raise_softirq_irqoff(nr); //<<--
local_irq_restore(flags);
}
inline void raise_softirq_irqoff(unsigned int nr)
{
__raise_softirq_irqoff(nr); //<<--
if (!in_interrupt())
wakeup_softirqd();
}
void __raise_softirq_irqoff(unsigned int nr)
{
trace_softirq_raise(nr);
or_softirq_pending(1UL << nr); //<<--
}
최근 덧글