ãLinuxã«ã¼ãã«2.6解èªå®¤ãï¼ä»¥éãæ§çï¼åºçå¾ãLinuxã«ã¯å¤ãã®æ©è½ã追å ãããã¨ã³ã¿ã¼ãã©ã¤ãºé åãã¯ããã¨ããæ§ã ãªå ´æã§ä½¿ãããããã«ãªãã¾ããã ããã«ä¼´ãã³ã¼ããè¥å¤§ãã¤è¤éåããå¤ãã®ã¨ã³ã¸ãã¢ã«ã¨ã£ã¦è§£èªä¸è½ãªãã©ãã¯ããã¯ã¹ã¨ãªã£ã¦ãã¾ãã ä¸çä¸ã®ãããã¨ã³ã¸ãã¢éã®åä½ã§ããLinuxã«ã¼ãã«ã«ã¡ã¹ãå ¥ãããã©ãã¯ããã¯ã¹ãããéãã¦ãæã«å¥½å¥å¿ã®èµ´ãã¾ã¾ã«ã«ã¼ãã«ã®ä¸çã解èªãããæ°Linuxã«ã¼ãã«è§£èªå®¤ãããã¸ã§ã¯ãã
æ¬ç¨¿ã§ã¯ãæ§ç第3ç« ã§è§£èª¬ããã¦ããã½ããå²ãè¾¼ã¿å¦çã«ã¤ãã¦ãã«ã¼ãã«v6.8/arm64ã®ã³ã¼ãããã¼ã¹ã«è§£èª¬ãã¾ãã
- ã¯ããã«
- å²ãè¾¼ã¿ç¦æ¢åºéã¨å¿çæ§ã«ã¤ãã¦
- ã½ããå²ãè¾¼ã¿å¦ç
å·çè : é«å é¼
â» ãæ°Linuxã«ã¼ãã«è§£èªå®¤ãé£è¼è¨äºä¸è¦§ã¯ãã¡ã
ã¯ããã«
æ¬ç¨¿ã§ã¯ããã¼ãå²ãè¾¼ã¿ãçºçãã¦ããã½ããå²ãè¾¼ã¿å¦çãå®è¡ãããã¾ã§ã®æµãããå®è¡ã³ã³ããã¹ãã®åãæ¿ããã追ããããªããç´¹ä»ãã¾ãã
解説ã«ãããåæã¨ããå®è¡ã³ã³ããã¹ãã¯ä»¥ä¸ã¨ãªãã¾ã*1ã
ããã»ã¹ã³ã³ããã¹ã
- ã¦ã¼ã¶ã¼ããã»ã¹
- ã«ã¼ãã«ã¹ã¬ãã
å²ãè¾¼ã¿ã³ã³ããã¹ã
- ã½ããå²ãè¾¼ã¿ã³ã³ããã¹ã
- ãã¼ãå²ãè¾¼ã¿ã³ã³ããã¹ã
- NMIã³ã³ããã¹ã
å®è¡ã³ã³ããã¹ãã¯ãã¹ã±ã¸ã¥ã¼ã©ã«ãã£ã¦ç®¡çãããããã»ã¹ã³ã³ããã¹ãã¨HWã®ã¤ãã³ãã«å¿ãã¦ã¹ã±ã¸ã¥ã¼ã©ã«é¢ãããå®è¡ãããå²ãè¾¼ã¿ã³ã³ããã¹ãã«åãããã¾ãã
ããã»ã¹ã³ã³ããã¹ãä¸ã§å®è¡ãããå¦çã¯ãã¹ã±ã¸ã¥ã¼ã©ã§ç®¡çããã¦ãããããåªå
度ãè¨å®ãããã¨ã§å®è¡æéãåªå
çã«ç¢ºä¿ãããªã©ã®èª¿æ´ãã§ãã¾ããã«ã¼ãã«ã¹ã¬ããã¯ãã¦ã¼ã¶ã¼ãåªå
度ãè¨å®ããããã»ã¹ãã§ããéãè¨å®éãã®åªå
度ã§åä½ããããã«ãä¸é¨ãé¤ãã¦é«ãåªå
度ã§åä½ããªãããè¨è¨ããã¦ãã¾ãã
ä¸æ¹ã§ãå²ãè¾¼ã¿ã³ã³ããã¹ãã§åä½ããå¦çã¯ãã¹ã±ã¸ã¥ã¼ã©ãä»ããã«å²ãè¾¼ã¿ãçºçããã¿ã¤ãã³ã°ã§å®è¡ããã¾ããããããå®è¡ã³ã³ããã¹ãã«ãã£ã¦ã¯ãç¹å®ã®å²ãè¾¼ã¿ã³ã³ããã¹ãã§ã®å®è¡ãç¦æ¢ããã¦ãããå²ãè¾¼ã¿ãçºçããã¿ã¤ãã³ã°ã¨å²ãè¾¼ã¿å¦çãå®è¡ãããã¿ã¤ãã³ã°ãç°ãªãå ´åãããã¾ãã以ä¸ã¯ãããããã®å®è¡ã³ã³ããã¹ãã«ããã¦ã許å¯ããã¦ããå¦ç (â) ã¨ç¦æ¢ããã¦ããå¦ç(Ã) ãä¸è¦§ã«ãããã®ã§ããç¦æ¢ããã¦ããå¦çã¯ãå®è¡ä¸ã®å²ãè¾¼ã¿å¦çãçµãã£ãå¾ã«å®è¡ããã¾ãã
ããã»ã¹ã³ã³ããã¹ã | ã«ã¼ãã«ã¹ã¬ãã | ã½ããå²ãè¾¼ã¿ã³ã³ããã¹ã | ãã¼ãå²ãè¾¼ã¿ã³ã³ããã¹ã | NMIã³ã³ããã¹ã | |
---|---|---|---|---|---|
ã½ããå²ãè¾¼ã¿(SoftIRQ) | â | â | à | à | à |
ãã¼ãå²ãè¾¼ã¿(IRQ) | â | â | â | à | à |
NMI | â | â | â | â | Ã |
以ä¸ã¯ãããããã®å®è¡ã³ã³ããã¹ãã«å¯¾ãã¦å²ãè¾¼ã¿å¦çãè¡ã£ãå ´åã®ã¤ã¡ã¼ã¸å³ã«ãªãã¾ãã
å®ç·ã®å·¦å´ã«è¨è¼ããã¦ããé¢æ°ã¯ãå²ãè¾¼ã¿ãçºçããéã«å®è¡ã³ã³ããã¹ãã®åãæ¿ããè¡ã£ã¦ãã¾ããå®ç·ã®å³å´ã«è¨è¼ããã¦ããé¢æ°ã«ã¤ãã¦ã¯ãã½ããå²ãè¾¼ã¿å®è¡ã«é¢ãã主è¦ãªé¢æ°ã¨ãªãã¾ãããããããå¼ã°ããå®è¡ã³ã³ããã¹ããç°ãªãã¾ãã(ã½ããå²ãè¾¼ã¿ã³ã³ããã¹ã: èç°è²ããã¼ãå²ãè¾¼ã¿ã³ã³ããã¹ã: èç´«ãNMIã³ã³ããã¹ã: ç°è²)
ããããã®é¢æ°ã¯å¾è¿°ããã½ããå²ãè¾¼ã¿å¦çã®è¦æã§ç»å ´ããã®ã§ã以ä¸ã®å³ãåèã«ããªããèªãã§ã¿ã¦ãã ããã
å²ãè¾¼ã¿ç¦æ¢åºéã¨å¿çæ§ã«ã¤ãã¦
話ãå§ããã«ããã£ã¦ãã¾ãå²ãè¾¼ã¿ç¦æ¢åºéã¨å¿çæ§ã®é¢ä¿ã«ã¤ãã¦å ·ä½ä¾ã交ãã¦ç´¹ä»ãããã¨æãã¾ãã å ·ä½ä¾ã¨ãã¦ãperfã®ãµã³ããªã³ã°ã«ç¨ããããNMIãç´¹ä»ãã¾ãã
perfã«ãããNMIå²ãè¾¼ã¿ããè¦ãå¿çæ§
perfããµã³ããªã³ã°å¨æãæå®ãã¦å®è¡ããå ´åãPerformance Monitoring Unit(PMU)ããæå®ãããµã³ããªã³ã°å¨æã§å²ãè¾¼ã¿ãçºçãã¾ãããã®éã«çºçããå²ãè¾¼ã¿ã«ã¯NMIãå©ç¨ãã¦ãã¾ãã
perfã«NMIã使ç¨ããçç±ã¨ãã¦ããµã³ããªã³ã°å¯¾è±¡ã®å¦çãå²ãè¾¼ã¿ç¦æ¢ãå®è¡ãã¦ããå ´åã§ãå²ãè¾¼ãã§ãµã³ããªã³ã°ãè¡ãããããåå¾ã§ãããµã³ãã«ã®ç²¾åº¦ãä¸ããç¹ãæãããã¾ãã
ããããã©ã®ãããªå®è¡ã³ã³ããã¹ãã«ãå²ãè¾¼ããNMIãperfã«ä½¿ããã¨ã«ã¯ã以ä¸ã®ãã¡ãªããããã¬ã¼ããªãã¨ãã¦æãããã¾ãã
- å²ãè¾¼ã¾ããå¦çã®å®äºãé ãã
- NMIã³ã³ããã¹ãä¸ã®perfå¦çä¸ã¯ããããã®å®è¡ã³ã³ããã¹ãã®å¦çãè¡ããªã
1ç¹ç®ã«ã¤ãã¦ã¯ãå²ãè¾¼ã¾ããå¦çã®å®äºããperfã®ãµã³ããªã³ã°å¦çå®è¡æéåã ãé
ãã¾ãã2ç¹ç®ã«ã¤ãã¦ã¯ãããperfå¦çä¸ã«ãã£ã¨éè¦ãªå¦çã«ãããããã¼ãå²ãè¾¼ã¿ãå
¥ã£ãã¨ãã¦ããperfã®ãµã³ããªã³ã°å¦çã®å®äºãå¾
ã¤å¿
è¦ãããã¾ãã
ãããã®å ´åã«ããã¦ããã·ã¹ãã ã®å¿çæ§ãperfã«ãã£ã¦è½ã¨ããªãããã«ã¯ãperfã®ãµã³ããªã³ã°å¦çãNMIã³ã³ããã¹ãã«ããæéãã§ããéãçããããã¨ã課é¡ã¨ãªãã¾ãã
å®éã«perfã¯ãNMIã³ã³ããã¹ãã«ããããµã³ããªã³ã°å¦çæéãæãããããå¿ è¦æå°éã®ãµã³ããªã³ã°å¦çãçµããå¾ã¯ãæ®å¦çããã¼ãå²ãè¾¼ã¿ã³ã³ããã¹ãã«ä»»ããã¨ããä»çµã¿ã¨ãªã£ã¦ãã¾ã*2ã
ã½ããå²ãè¾¼ã¿å¦ç
ã½ããå²ãè¾¼ã¿å¦çã®èãæ¹
perfã®ä¾ã®ããã«ãå¦çãé©åãªå®è¡ã³ã³ããã¹ãã§è¡ãããªãå ´åã«ã¯ãã·ã¹ãã ã®å¿çæ§ãä¸ããåå ã¨ãªãã¾ãã
ããä¸è¬çãªãã¼ãå²ãè¾¼ã¿ã«ã¤ãã¦ã課é¡ã¯åãã§ããå¿çæ§ãç¶æããããã®ä»çµã¿ããNMIã³ã³ããã¹ãã«ãããperfå¦çã¨åæ§ã«ããã¼ãå²ãè¾¼ã¿ã³ã³ããã¹ãã«ãããå¦çã¯æå°éã«æãã¦ãä»ã³ã³ããã¹ãã«æ®å¦çãä»»ããã¨ããã¢ããã¼ãã«ãªãã¾ãããã®ãã¼ãå²ãè¾¼ã¿ã³ã³ããã¹ãã®æ®å¦çãä»ã³ã³ããã¹ãã«å¼ã渡ãä»çµã¿ãã½ããå²ãè¾¼ã¿å¦çã¨ãªãã¾ãã
æ¬ç¯ã§ã¯ãã¾ããã¼ãå²ãè¾¼ã¿ããã½ããå²ãè¾¼ã¿å¦çãå®è¡ãããã¾ã§ã®æµããã¹ã¿ãã¯ãã確èªãã¾ãããã®å¾ãã½ããå²ãè¾¼ã¿å¦çãå®è¡ãããã¾ã§ã«ç»å ´ãã主ãªé¢æ°ãç´¹ä»ãã¦ããã¾ãã
ã½ããå²ãè¾¼ã¿å®è¡ã¾ã§ã®æµã
ç¾å¨ã®Linuxã«ã¯ã10種é¡ã®ã½ããå²ãè¾¼ã¿ç¨®å¥ãç¨æããã¦ãã¾ãã種å¥ã¯ç¨éã«å¿ãã¦ç¨æããã¦ããããã¼ãå²ãè¾¼ã¿å¦çãã対å¿ãã種å¥ãæå®ãã¦ã½ããå²ãè¾¼ã¿è¦æ±ãè¡ããã¨ã§ã種å¥ãã¨ã«äºåã«ç»é²ãã¦ãããã³ãã©ãã½ããå²ãè¾¼ã¿ã³ã³ããã¹ãã§å®è¡ããã¾ãã以ä¸ã®è¡¨ã¯ãã½ããå²ãè¾¼ã¿å¦çãå®è¡ããããã®ä¸»ãªé¢æ°ã¨ç¨®å¥ãã¨ã«å®è¡ãããå¦çã®å 容ã¨ãªãã¾ãã
é¢æ°å | 説æ |
---|---|
open_softirq | 種å¥ãã¨ã«ãã³ãã©ãç»é² |
raise_softirq | ã½ããå²ãè¾¼ã¿ã種å¥ãã¨ã«è¦æ± |
__do_softirq | ã½ããå²ãè¾¼ã¿å¦çã®å®è¡ |
ã½ããå²ãè¾¼ã¿ç¨®å¥ | 説æ |
---|---|
HI_SOFTIRQ | taskletãå®è¡ |
TIMER_SOFTIRQ | ã¿ã¤ãã¼ã®å®è¡ |
NET_TX_SOFTIRQ | ãããã¯ã¼ã¯éä¿¡å®äºå¦çãå®è¡ |
NET_RX_SOFTIRQ | ãããã¯ã¼ã¯åä¿¡å¦çãå®è¡ |
BLOCK_SOFTIRQ | ãããã¯I/Oå¦çãå®è¡ |
IRQ_POLL_SOFTIRQ | ãã¼ãªã³ã°ã¢ã¼ãã§ã®ãããã¯I/Oå¦çãå®è¡ |
TASKLET_SOFTIRQ | taskletãå®è¡ |
SCHED_SOFTIRQ | ã¹ã±ã¸ã¥ã¼ã©ã®è² è·ãã©ã³ã¹å¦çãå®è¡ |
HRTIMER_SOFTIRQ | ãã¤ã¬ã¾ã¿ã¤ãã¼ã®å®è¡ |
RCU_SOFTIRQ | RCUã®å¾å¦çãè¡ãªãã³ã¼ã«ããã¯å®è¡ |
以ä¸ã§åãæããã¹ã¿ãã¯ã¯ãHI_SOFTIRQã«å¯¾ãã¦ã®è¦æ±ããã£ãå ´åã®ãã®ã¨ãªãã¾ãããªããã¹ã¿ãã¯ã¯ãarm64ç°å¢ã§SysRqã使ã£ã¦åå¾ãã¾ããã
ã¾ããå²ãè¾¼ã¿ãã¨ã«ç»é²ããã¦ãããã¼ãå²ãè¾¼ã¿å¦çãel1h_64_irq_handler()
ã§å®è¡(#25)ããã¾ããã½ããå²ãè¾¼ã¿è¦æ±ããã®ãã¼ãå²ãè¾¼ã¿å¦çä¸ã«è¡ããã¨ã§ããã¼ãå²ãè¾¼ã¿å¦ççµäºå¾ã«ã½ããå²ãè¾¼ã¿å¦çãå®è¡(#18)ããã¾ãã以ä¸ã®ã¹ã¿ãã¯ã®å ´åããã¼ãå²ãè¾¼ã¿å¦çä¸ã«HI_SOFTIRQã«å¯¾ããã½ããå²ãè¾¼ã¿è¦æ±ããã£ããã¨(#17)ããããã¾ããå®éã«ãã¼ãå²ãè¾¼ã¿ããã½ããå²ãè¾¼ã¿è¦æ±ãè¡ãããã¾ã§ã®æµãã«ã¤ãã¦ã¯ãRCU_SOFTIRQãå
·ä½ä¾ã«å¾è¿°ãã¾ãã
#16 [ffffffc008003ed0] tasklet_action_common at ffffffd83cc94098 #17 [ffffffc008003f10] tasklet_hi_action at ffffffd83cc9415c // ã½ããå²ãè¾¼ã¿ç¨®å¥ãã¨ã®ãã³ãã© #18 [ffffffc008003f30] __do_softirq at ffffffd83cc104e4 // ã½ããå²ãè¾¼ã¿å¦ç #19 [ffffffc008003ff0] ____do_softirq at ffffffd83cc16f74 --- <IRQ stack> --- #20 [ffffffd83df93b70] call_on_irq_stack at ffffffd83cc16f2c #21 [ffffffd83df93b80] do_softirq_own_stack at ffffffd83cc16fa4 #22 [ffffffd83df93b90] __irq_exit_rcu at ffffffd83cc939e8 // ã½ããå²ãè¾¼ã¿è¦æ±ã®æç¡ãå¤å® #23 [ffffffd83df93bb0] irq_exit_rcu at ffffffd83cc93d84 #24 [ffffffd83df93bc0] el1_interrupt at ffffffd83d7ab124 #25 [ffffffd83df93be0] el1h_64_irq_handler at ffffffd83d7ab938 // å²ãè¾¼ã¿ãã³ãã©å¦çã»ã½ããå²ãè¾¼ã¿è¦æ± #26 [ffffffd83df93d20] el1h_64_irq at ffffffd83cc11ae4 #27 [ffffffd83df93d40] arch_cpu_idle at ffffffd83d7ac468 #28 [ffffffd83df93d50] default_idle_call at ffffffd83d7b74d0 #29 [ffffffd83df93d80] do_idle at ffffffd83cce2f24 #30 [ffffffd83df93de0] cpu_startup_entry at ffffffd83cce3178 #31 [ffffffd83df93e00] rest_init at ffffffd83d7ad0f4 #32 [ffffffd83df93e20] arch_call_rest_init at ffffffd83db80888 #33 [ffffffd83df93e50] start_kernel at ffffffd83db80fe4
ãªããã½ããå²ãè¾¼ã¿å¦ç(#18)ã¯ã½ããå²ãè¾¼ã¿è¦æ±ãããå ´åã«å®è¡ããã¾ãããã½ããå²ãè¾¼ã¿è¦æ±ããã£ããã©ããã®ç¢ºèªãè¡ãããã®ããã¼ãå²ãè¾¼ã¿å¦ççµäºå¾ã«å¼ã°ãã__irq_exit_rcu()
(#23)ã¨ãªãã¾ãã
__irq_exit_rcu()
ã¯ãã½ããå²ãè¾¼ã¿è¦æ±ããããã©ããã®ç¢ºèªã«å ãã¦ãå®è¡ã³ã³ããã¹ãã®åãæ¿ããè¡ã£ã¦ãã¾ããå®è¡ã³ã³ããã¹ãã®åãæ¿ãã¯L.630ã§è¡ããã¦ãããL.630以éã®å®è¡ã³ã³ããã¹ãã¯å²ãè¾¼ã¾ããå¦çã®å®è¡ã³ã³ããã¹ãã«æ»ãã¾ãã
ãã®ãããã½ããå²ãè¾¼ã¿å¦çãå®è¡ãããã®ã¯ãå²ãè¾¼ã¾ããå¦çã®å®è¡ã³ã³ããã¹ããããã»ã¹ã³ã³ããã¹ãã§ãããã¨ã«å ãã¦ãã½ããå²ãè¾¼ã¿è¦æ±ããã£ãå ´å(L.631)ã¨ãªãã¾ãã
622 static inline void __irq_exit_rcu(void) 623 { 624 #ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED 625 local_irq_disable(); 626 #else 627 lockdep_assert_irqs_disabled(); 628 #endif 629 account_hardirq_exit(current); 630 preempt_count_sub(HARDIRQ_OFFSET); 631 if (!in_interrupt() && local_softirq_pending()) 632 invoke_softirq(); 633 634 tick_irq_exit(); 635 }
ã½ããå²ãè¾¼ã¿è¦æ±ï¼RCU_SOFTIRQã®å ´åï¼
ãã¼ãå²ãè¾¼ã¿ããã½ããå²ãè¾¼ã¿è¦æ±ãè¡ãããã¾ã§ã®æµããRCU_SOFTIRQãä¾ã«ç¢ºèªãã¾ãããªãã説æãåç´åããããã«Tiny RCUã®å ´åã«ã¤ãã¦ç´¹ä»ãã¾ãã
RCUã§ã¯ãåæã®å®äºã確èªã§ããã¨ä¿è·ããã¦ãããã¼ã¿ãåé¤ããããã®ã³ã¼ã«ããã¯ãå®è¡ããã¾ãããåæãå®äºãã¦ãããã©ããã®å¤å®ã«ã¯ãã¼ãå²ãè¾¼ã¿(ã¿ã¤ãã¼å²ãè¾¼ã¿)ãå©ç¨ãã¦ãã¾ãã
åæãå®äºãã¦ããå ´å(L.73)ã«å¼ã°ããã³ã¼ã«ããã¯ã¯ãã¿ã¤ãã¼å²ãè¾¼ã¿å¦çã®å®è¡æéã延ã³ã¦å¿çæ§ãæªããªããã¨ãé²ããããã¿ã¤ãã¼å²ãè¾¼ã¿å¦çä¸ã«ã¯ã½ããå²ãè¾¼ã¿è¦æ±ã ãè¡ã(L.59)ãå®éã®ã³ã¼ã«ããã¯ã®å®è¡ã¯ã¿ã¤ãã¼å²ãè¾¼ã¿å¦çå¾ã®ã½ããå²ãè¾¼ã¿ã³ã³ããã¹ãã§è¡ããã¦ãã¾ã*3ã
71 void rcu_sched_clock_irq(int user) 72 { 73 if (user) { 74 rcu_qs(); 75 } else if (rcu_ctrlblk.donetail != rcu_ctrlblk.curtail) { 76 set_tsk_need_resched(current); 77 set_preempt_need_resched(); 78 } 79 }
52 void rcu_qs(void) 53 { 54 unsigned long flags; 55 56 local_irq_save(flags); 57 if (rcu_ctrlblk.donetail != rcu_ctrlblk.curtail) { 58 rcu_ctrlblk.donetail = rcu_ctrlblk.curtail; 59 raise_softirq_irqoff(RCU_SOFTIRQ); 60 } 61 WRITE_ONCE(rcu_ctrlblk.gp_seq, rcu_ctrlblk.gp_seq + 2); 62 local_irq_restore(flags); 63 }
ã½ããå²ãè¾¼ã¿å¦çã®å®è¡ã³ã³ããã¹ã
ã½ããå²ãè¾¼ã¿å¦çã¯invoke_softirq()
ãå¥æ©ã«å®è¡ããã¾ãããã½ããå²ãè¾¼ã¿å¦çãå®è¡ãããã³ã³ããã¹ãã¯ãã«ã¼ãã«ã®ã³ã³ãã£ã°ã¬ã¼ã·ã§ã³ããã¼ããã©ã¡ã¼ã¿ã«ãã£ã¦ç°ãªãã¾ãã
æ¬ç¯ã§ã¯ãã½ããå²ãè¾¼ã¿å¦çãå®è¡ãããã³ã³ããã¹ãããinvoke_softirq()
ã®å®è£
ãã確èªãã¾ãã
é常ã®ã«ã¼ãã«ã®å ´åãinvoke_softirq()
ã®å®è£
ã¯L.418ã¨ãªã£ã¦ãã¾ããã½ããå²ãè¾¼ã¿å¦çã¯ãæ示çãªè¨å®ãããªããã°ãã½ããå²ãè¾¼ã¿ã³ã³ããã¹ãã§è¡ããã¾ã(L.420)ãã½ããå²ãè¾¼ã¿å¦çãã«ã¼ãã«ã¹ã¬ããã§å®è¡ãããå ´å(L.436)ã«ã¯ãCONFIG_IRQ_FORCED_THREADINGãæå¹åããã«ã¼ãã«ã«threadirqsããã¼ããã©ã¡ã¼ã¿ã¨ãã¦æ¸¡ãã¦ããããã¨ã§ãã½ããå²ãè¾¼ã¿å¦çãã«ã¼ãã«ã¹ã¬ããã§å®è¡ãããããã«ãªãã¾ãã
ãªãããããã®å®è¡ã³ã³ããã¹ãã«ããã¦ããæçµçã«å¼ã³åºãããã®ã¯ã½ããã¦ã§ã¢å²ãè¾¼ã¿å¦çã®æ¬ä½ã§ãã__do_softirq()
ã¨ãªãã¾ãã
418 static inline void invoke_softirq(void) 419 { 420 if (!force_irqthreads() || !__this_cpu_read(ksoftirqd)) { 421 #ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK 422 /* 423 * We can safely execute softirq on the current stack if 424 * it is the irq stack, because it should be near empty 425 * at this stage. 426 */ 427 __do_softirq(); 428 #else 429 /* 430 * Otherwise, irq_exit() is called on the task stack that can 431 * be potentially deep already. So call softirq in its own stack 432 * to prevent from any overrun. 433 */ 434 do_softirq_own_stack(); 435 #endif 436 } else { 437 wakeup_softirqd(); 438 } 439 }
ã¡ãªã¿ã«ãå¿çæ§ãéè¦ããCONFIG_PREEMPT_RTãæå¹ã«ããå ´å(RTã«ã¼ãã«)ã ã¨*4ãã½ããå²ãè¾¼ã¿å¦çã¯å
¨ã¦ã«ã¼ãã«ã¹ã¬ããã§å®è¡ããã¾ãã
/kernel/softirq.c
276 static inline void invoke_softirq(void) 277 { 278 if (should_wake_ksoftirqd()) 279 wakeup_softirqd(); 280 }
ã½ããå²ãè¾¼ã¿å¦çã®å®è¡
ã½ããå²ãè¾¼ã¿å¦çãã½ããå²ãè¾¼ã¿ã³ã³ããã¹ããããã¯ã«ã¼ãã«ã¹ã¬ããã§å®è¡ããããã¨ãinvoke_softirq()
ã§ç¢ºèªãã¾ããããã½ããå²ãè¾¼ã¿å¦çèªä½ã¯__do_softirq()
ã§å®è¡ããã¾ãã
æ¬ç¯ã§ã¯ã__do_softirq()
å
ã«ãããå®è¡ã³ã³ããã¹ãã®åãæ¿ããã確èªãã¾ãã
510 asmlinkage __visible void __softirq_entry __do_softirq(void) 511 { 512 unsigned long end = jiffies + MAX_SOFTIRQ_TIME; 513 unsigned long old_flags = current->flags; 514 int max_restart = MAX_SOFTIRQ_RESTART; 515 struct softirq_action *h; 516 bool in_hardirq; 517 __u32 pending; 518 int softirq_bit; 519 520 /* 521 * Mask out PF_MEMALLOC as the current task context is borrowed for the 522 * softirq. A softirq handled, such as network RX, might set PF_MEMALLOC 523 * again if the socket is related to swapping. 524 */ 525 current->flags &= ~PF_MEMALLOC; 526 527 pending = local_softirq_pending(); 528 529 softirq_handle_begin(); 530 in_hardirq = lockdep_softirq_start(); 531 account_softirq_enter(current); 532 533 restart: 534 /* Reset the pending bitmask before enabling irqs */ 535 set_softirq_pending(0); 536 537 local_irq_enable(); 538 539 h = softirq_vec; 540 541 while ((softirq_bit = ffs(pending))) { 542 unsigned int vec_nr; 543 int prev_count; 544 545 h += softirq_bit - 1; 546 547 vec_nr = h - softirq_vec; 548 prev_count = preempt_count(); 549 550 kstat_incr_softirqs_this_cpu(vec_nr); 551 552 trace_softirq_entry(vec_nr); 553 h->action(h); 554 trace_softirq_exit(vec_nr); 555 if (unlikely(prev_count != preempt_count())) { 556 pr_err("huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?\n", 557 vec_nr, softirq_to_name[vec_nr], h->action, 558 prev_count, preempt_count()); 559 preempt_count_set(prev_count); 560 } 561 h++; 562 pending >>= softirq_bit; 563 } 564 565 if (!IS_ENABLED(CONFIG_PREEMPT_RT) && 566 __this_cpu_read(ksoftirqd) == current) 567 rcu_softirq_qs(); 568 569 local_irq_disable(); 570 571 pending = local_softirq_pending(); 572 if (pending) { 573 if (time_before(jiffies, end) && !need_resched() && 574 --max_restart) 575 goto restart; 576 577 wakeup_softirqd(); 578 } 579 580 account_softirq_exit(current); 581 lockdep_softirq_end(in_hardirq); 582 softirq_handle_end(); 583 current_restore_flags(old_flags, PF_MEMALLOC); 584 }
ã½ããå²ãè¾¼ã¿å¦çå ¥å£
åç¯ã§ç¢ºèªããããã«ãã½ããå²ãè¾¼ã¿å¦çã®å®è¡ã³ã³ããã¹ãã¯ãã½ããå²ãè¾¼ã¿ã³ã³ããã¹ããããã¯ã«ã¼ãã«ã¹ã¬ããã¨ãªã£ã¦ãããã½ããå²ãè¾¼ã¿å¦çä¸ããã¼ãå²ãè¾¼ã¿ãåãä»ãã¦ãã¾ããããããã½ããå²ãè¾¼ã¿ã®å
¥ãå£åºé(~L.537)ã«ã¤ãã¦ã¯ããã¼ãå²ãè¾¼ã¿ãç¦æ¢ããã¦ãã¾ã*5ã
__do_softirq()
ã§ã¯ã__do_softirq()
ãå¼ã°ããã¾ã§ã«è¦æ±(pendingç¶æ
)ããã£ãã½ããå²ãè¾¼ã¿ç¨®å¥ã®ãã³ãã©ãå®è¡(L.553)ãã¾ãããå®è¡å¯¾è±¡ã¨ãªãã½ããå²ãè¾¼ã¿ç¨®å¥ã®åå¾ã¯L.527ã§è¡ããã¾ããã½ããå²ãè¾¼ã¿ç¨®å¥ãã¨ã®pendingç¶æ
ã«ã¤ãã¦ã¯ãã½ããå²ãè¾¼ã¿ç¨®å¥ã®ãã³ãã©ãå®è¡ããåã«ãªã»ããããã¾ã(L.535)ããå®è¡å¯¾è±¡ã¨ãªãã®ã¯L.527ã§åå¾ããã½ããå²ãè¾¼ã¿ç¨®å¥ã®ã¿ã§ãã
ãã®ããããã¼ãå²ãè¾¼ã¿ç¦æ¢ã¯ãpendingç¶æ
ã«ããã½ããå²ãè¾¼ã¿ç¨®å¥ã®åå¾ãããªã»ããã¾ã§ã®åºé(L.527~L.535)ã«æ°ããªã½ããå²ãè¾¼ã¿è¦æ±ãè¡ãããå ´åã®åããã¼ãé²ãããã«è¨ãããã¦ãã¾ãããªããpendingç¶æ
ã«ããã½ããå²ãè¾¼ã¿ç¨®å¥ã®ç¢ºèªã¯ã½ããå²ãè¾¼ã¿ç¨®å¥ã®ãã³ãã©ãå®è¡å¾ã«ãè¡ãã(L.571)ãã½ããå²ãè¾¼ã¿å¦çä¸ã«ã½ããå²ãè¾¼ã¿è¦æ±ããã£ãå ´åã«ãåæ§ã«ãpendingç¶æ
ã®åå¾ãããªã»ããã¾ã§ã®åºé(L.571~L.535)ããã¼ãå²ãè¾¼ã¿ç¦æ¢ã¨ãªã£ã¦ãã¾ãã
ã½ããå²ãè¾¼ã¿ã³ã³ããã¹ãåºéï¼softirq_handle_begin/endï¼
__irq_exit_rcu()
ã«ããã¦ããã¼ãå²ãè¾¼ã¿å¦çããå¼ã³åºãããinvoke_softirq()
ã¯ãå²ãè¾¼ã¾ããå¦çã®å®è¡ã³ã³ããã¹ããããã»ã¹ã³ã³ããã¹ãã ã£ãå ´åã§ãããã¨ã確èªãã¾ãããå®è¡ã³ã³ããã¹ãã®ç¢ºèªã«ç¨ãããã¦ããin_interrupt()
ã¯ãå²ãè¾¼ã¿ã³ã³ããã¹ãã«ãããã©ããã®å¤å®ãè¡ãããã«ç¨ãããã¾ãããå¤å®ã®å¯¾è±¡ã¨ãªãå²ãè¾¼ã¿ã³ã³ããã¹ãã¯ãã¼ãã»ã½ããã»NMIå²ãè¾¼ã¿ã¨ãªã£ã¦ãã¾ãããã®ããããã¼ãå²ãè¾¼ã¿å¦çããinvoke_softirq()
ãå¼ã°ããã¿ã¤ãã³ã°ã§ã¯ããã¼ãå²ãè¾¼ã¿ã³ã³ããã¹ããçµäºããã ãã®ç¶æ
ã§ãããã½ããå²ãè¾¼ã¿ã³ã³ããã¹ãã«ã¯åãæ¿ãã£ã¦ãã¾ããã
softirq_handle_begin()
ã¯ãå®éã«ã½ããå²ãè¾¼ã¿ã³ã³ããã¹ãã¸ã®åãæ¿ãããè¡ã£ã¦ããé¢æ°ã¨ãªãã¾ãããã®ãããå®è¡ã³ã³ããã¹ãã¨ãã¦ã®ã½ããå²ãè¾¼ã¿å¦çã¯ãsoftirq_handle_begin()
ããsoftirq_handle_end()
ã¾ã§ã®åºé(L.529~L.582)ã¨ãªãã¾ãã
RTã«ã¼ãã«ã«ãããsoftirq_handle_begin/endï¼ä½è«ï¼
invoke_softirq()
ã®å®è£
ã§ç¢ºèªããã¨ãããRTã«ã¼ãã«ã«ããã¦ã½ããå²ãè¾¼ã¿å¦çã¯ãã½ããå²ãè¾¼ã¿ã³ã³ããã¹ãã§ã¯ãªãã«ã¼ãã«ã¹ã¬ããã§è¡ããã¾ãããã®å®è¡ã³ã³ããã¹ãã®éããããé常ã®ã«ã¼ãã«ã¨RTã«ã¼ãã«ã§ã¯softirq_handle_begin/end()
ã®å®è£
ãç°ãªãã¾ãã
é常ã®ã«ã¼ãã«ã®å ´å
/kernel/softirq.c
392 static inline void softirq_handle_begin(void) 393 { 394 __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET); 395 } 396 397 static inline void softirq_handle_end(void) 398 { 399 __local_bh_enable(SOFTIRQ_OFFSET); 400 WARN_ON_ONCE(in_interrupt()); 401 }
RTã«ã¼ãã«ã®å ´å
/kernel/softirq.c
268 static inline void softirq_handle_begin(void) { } 269 static inline void softirq_handle_end(void) { }
ãããããæ¯è¼ãã¦ãããéããRTã«ã¼ãã«ã®å ´åã«ã¯softirq_handle_begin/end()
ã§è¡ãããå¦çã¯ããã¾ããã
ããã¯ãRTã«ã¼ãã«ã§ã¯ãã½ããå²ãè¾¼ã¿å¦çã常ã«ã¹ã±ã¸ã¥ã¼ã©ãä»ããã«ã¼ãã«ã¹ã¬ããã§è¡ããããããã½ããå²ãè¾¼ã¿å¦çä¸ã«ã½ããå²ãè¾¼ã¿ã³ã³ããã¹ãã®ã½ããå²ãè¾¼ã¿å¦çããã¹ããã¦å®è¡ããããã¨ãèæ
®ããå¿
è¦ããªãããã§ããé常ã®ã«ã¼ãã«ã§ã¯ãlocal_bh_disable/enable()
ãã½ããå²ãè¾¼ã¿ç¦æ¢ã®åºéãè¨å®ãããã¨ã§ãã½ããå²ãè¾¼ã¿å¦çããã¹ããã¦å®è¡ããããã¨ãé²ãã§ãã¾ãã
æ¬ç¨¿ã§ã¯ãå®è¡ã³ã³ããã¹ãã®æµãã«ã¤ãã¦ã®ã¿ç´¹ä»ãããããå®è¡ã³ã³ããã¹ãã管çãã¦ãããã¼ã¿æ§é ãé¢æ°ã®å®è£
ã«ã¤ãã¦ã¯è§¦ãã¾ããã§ããã次稿ã§ã¯ãæ¬ç¨¿ã§è§¦ããªãã£ããããå®è¡ã³ã³ããã¹ãã«é¢ããä»çµã¿ã«ã¤ãã¦ç´¹ä»ãããã§ãã
*1:preempt_countã§ç®¡çãããå®è¡ã³ã³ããã¹ãã¨ãªãã¾ãããã®ãããæ¬ç¨¿ã§åãä¸ããå®è¡ã³ã³ããã¹ãã®å¤å®ãåãæ¿ãã¯ãpreempt_countã®ç¶æ ã«å¯¾ããæä½ã§ãããã ããå²ãè¾¼ã¿ç¦æ¢åºéã«ã¤ãã¦ã¯ãpreempt_countã®ç¶æ ã«åºã¥ããã®ã§ã¯ãªãHWã§å®ç¾ãã¦ãã¾ãã
*2:NMIãããã¼ãå²ãè¾¼ã¿ã³ã³ããã¹ãã¸ã®é 延å¦çã®ä»çµã¿ã§ããirq_workã使ã£ã¦ãã¾ã
*3:RCUã®ä»çµã¿ã®è©³ç´°ã¯ãå¥éããã°è¨äºã«ããã®ã§ãå¾ ã¡ãã ãã
*4:RTã«ã¼ãã«ã§ã¯ãå¿çæ§ãä¸ããããã«ãæ¬ç¨¿ã§è§¦ããå²ãè¾¼ã¿å¦ç以å¤ã§ãæ§ã ãªå·¥å¤«ãããã¦ãã¾ãããããã«ã¤ãã¦ãå¥ç¨¿ã§ç´¹ä»ããæ©ä¼ããããã¨æãã¾ã
*5:arm64ã§ã¯ãå²ãè¾¼ã¿ã®çºçã¨åæã«HWã«ããå²ãè¾¼ã¿ãç¦æ¢ããã¾ã