ãLinuxã«ã¼ãã«2.6解èªå®¤ãï¼ä»¥éãæ§çï¼åºçå¾ãLinuxã«ã¯å¤ãã®æ©è½ã追å ãããã¨ã³ã¿ã¼ãã©ã¤ãºé åãã¯ããã¨ããæ§ã ãªå ´æã§ä½¿ãããããã«ãªãã¾ããã ããã«ä¼´ãã³ã¼ããè¥å¤§ãã¤è¤éåããå¤ãã®ã¨ã³ã¸ãã¢ã«ã¨ã£ã¦è§£èªä¸è½ãªãã©ãã¯ããã¯ã¹ã¨ãªã£ã¦ãã¾ãã ä¸çä¸ã®ãããã¨ã³ã¸ãã¢éã®åä½ã§ããLinuxã«ã¼ãã«ã«ã¡ã¹ãå ¥ãããã©ãã¯ããã¯ã¹ãããéãã¦ãæã«å¥½å¥å¿ã®èµ´ãã¾ã¾ã«ã«ã¼ãã«ã®ä¸çã解èªãããæ°Linuxã«ã¼ãã«è§£èªå®¤ãããã¸ã§ã¯ãã
æ¬ç¨¿ã§ã¯ãæ§ç1ç« ã§è§£èª¬ããã¦ãããããã»ã¹ã¹ã±ã¸ã¥ã¼ãªã³ã°ãã®å
ãããã»ã¹ãã£ã¹ãããã£(ã¿ã¹ã¯ã®åãæ¿ãå¦ç)ã«ã¤ãã¦ãã«ã¼ãã«v6.8/x86_64ã®ã³ã¼ãããã¼ã¹ã«è§£èª¬ãã¾ãã
- 1. åæç¥è
- 2. å ¨ä½ã®æµã
- 3. ã¬ã¸ã¹ã¿ã®åãæ¿ã
- 4. åå¾å¦ç
- 5. æå¾ã«
- åèè³æ
å·çè : 西æã大å©
â» ãæ°Linuxã«ã¼ãã«è§£èªå®¤ãé£è¼è¨äºä¸è¦§ã¯ãã¡ã
1. åæç¥è
æ¬ç« ã§ã¯ããã»ã¹ãã£ã¹ãããã£ã解説ããã«ãããå¿ è¦ã¨ãªãåæç¥èã¨ãã¦ã(ã¹ã¿ãã¯ã«é¢ãã)ããã»ããµã®æåãtask_structæ§é ä½(å«ããé¢é£ãããã¼ã¿æ§é )ãã«ã¤ãã¦ã¾ã¨ãã¾ãã
1.1 ã¹ã¿ãã¯
æ¬ç¯ã§ã¯ãx86_64ã¢ã¼ããã¯ãã£ã«ããããã¹ã¿ãã¯ã«ã¤ãã¦è§£èª¬ãã¾ãã
詳細ã¯å¾è¿°ãã¾ãããã¤ã¡ã¼ã¸ã¨ãã¦ã¯ä¸å³ã®ããã«ãªãã¾ã*1ã
1.1.1 æ¦è¦
ããã»ããµã¯ã¹ã¿ãã¯ã¨å¼ã°ããé£ç¶ããã¡ã¢ãªé åãä½æ¥é åã¨ãã¦å¦çãè¡ãã¾ããã¹ã¿ãã¯ã®å
·ä½çãªç¨éã¯ã¢ã¼ããã¯ãã£ã¯ãã¡ããå¦çç³»ã«ãä¾åãã¾ãããå®è¡ä¸ã®é¢æ°ã®ãã¼ã«ã«å¤æ°ããé¢æ°å¼ã³åºãæã®å¼æ°ãé¢æ° ãå¼ã³åºããæã®Instruction Pointer(RIPã¬ã¸ã¹ã¿)ãä¿åãã¦ãã(å¼ã³åºãå
ã«æ»ãæã«åç
§ãã)ãªã©æ§ã
ã§ãã
ã¹ã¿ãã¯ã¯ä¸ä½ã¢ãã¬ã¹ããä¸ä½ã¢ãã¬ã¹ã«åãã¦æ¡å¼µãã¦ããã¾ããã¾ããã¹ã¿ãã¯ãã¬ã¼ã ã¨å¼ã°ããé åã«åå²ããã¦ãããBase Pointer(RBPã¬ã¸ã¹ã¿)ãããã¹ã¿ãã¯ã®å
é ã表ãStack Pointer(RSPã¬ã¸ã¹ã¿)ã®éããå®è¡æç¹ã®ã¹ã¿ãã¯ãã¬ã¼ã (å®è¡ä¸ã®é¢æ°ã使ç¨ããã¹ã¿ãã¯ãã¬ã¼ã )ã¨ãªã£ã¦ãã¾ãã
1.1.2 PUSH/POPå½ä»¤
ã¹ã¿ãã¯ã¸ã®ãã¼ã¿ã®ä¿åãåã³ãã¼ã¿ã®åãåºãã«ã¯ãããããPUSH/POPå½ä»¤ã使ç¨ãã¾ã*2ã
PUSHå½ä»¤ãå®è¡ããã¨ããªãã©ã³ã(ã¬ã¸ã¹ã¿ç)ã®ãã¼ã¿ãã¹ã¿ãã¯ã®å
é ã«ç©ãã§ãStack Pointer(RSPã¬ã¸ã¹ã¿)ããã®åã ãé²ãã¾ã(æ¸ç®ãã¾ã)ã
POPå½ä»¤ãå®è¡ããã¨ãã¹ã¿ãã¯ã®å
é ã®ãã¼ã¿ããªãã©ã³ã(ã¬ã¸ã¹ã¿ç)ã«åãåºãã¦ãStack Pointer(RSPã¬ã¸ã¹ã¿)ããã®åã ãæ»ãã¾ã(å ç®ãã¾ã)ã
1.1.3 CALL/RETå½ä»¤
é¢æ°ã®å¼ã³åºãã«ã¯CALLå½ä»¤ã使ç¨ããã¾ãããCALLå½ä»¤ãå®è¡ããã¨ãã®æã®Instruction Pointer(RIPã¬ã¸ã¹ã¿)ãã¹ã¿ãã¯ã«ä¿å(PUSH)ããã¦ãå¼ã³åºãããé¢æ°ã«å¶å¾¡ã移ãã¾ã(Instruction Pointer(RIPã¬ã¸ã¹ã¿)ãå½è©²é¢æ°ã®å
é ã¢ãã¬ã¹ã«ãªãã¾ã)ã
å¼ã³åºãããé¢æ°ã¯ãé常ãæåã«Base Pointer(RBPã¬ã¸ã¹ã¿)ãä¿å(PUSH)ããä¸ã§ãBase Pointer(RBPã¬ã¸ã¹ã¿)ãStack Pointer(RSPã¬ã¸ã¹ã¿)ã®å¤ã§æ´æ°ããã®ã§ãBase Pointer(RBPã¬ã¸ã¹ã¿)ã®æãã¦ããã¹ã¿ãã¯ãã¬ã¼ã ã®æä¸ä½ã¢ãã¬ã¹ã«ã¯å¼ã³åºãå
é¢æ°ã®Base Pointer(RBPã¬ã¸ã¹ã¿)ãããã®1ã¤åã«ã¯å¼ã³åºãå
ã®Instruction Pointer(RIPã¬ã¸ã¹ã¿)ãä¿åããã¦ããç¶æ
ã¨ãªã£ã¦ãã¾ãã
ããã¦é¢æ°ã®å¦çãçµããéã«ã¯RETå½ä»¤ã使ç¨ããã¾ãããRETå½ä»¤ã¯ãã®æã®ã¹ã¿ãã¯ãããã¼ã¿ãPOPãã¦Instruction Pointer(RIPã¬ã¸ã¹ã¿)ã«è¨å®ãã¾ãããªã®ã§ãã¹ã¿ãã¯ãã¬ã¼ã ããBase Pointer(RBPã¬ã¸ã¹ã¿)ã復å
(POP)ãã¦ã¦ãã(ãã®æç¹ã§ã¹ã¿ãã¯ã®å
é ã¯CALLå®è¡æã®Instruction Pointer(RIPã¬ã¸ã¹ã¿))RETå½ä»¤ãå®è¡ããäºã§ãå¼ã³åºãå
é¢æ°ã«å¶å¾¡ãæ»ããé¢æ°ãå¼ã³åºããå¾ã®å¦çãç¶ç¶ãããäºã«ãªãã¾ãã
1.2 task_structæ§é ä½
Linuxã§ã¯ãã¿ã¹ã¯*3æ¯ã«task_structæ§é ä½ããããã¿ã¹ã¯ç®¡çã«å¿
è¦ãªæ
å ±ãä¿æãã¦ãã¾ãã
task_structæ§é ä½ã¯é常ã«å¤ãã®ã¡ã³ããæã£ã¦ãã¾ãããæ¬ç¯ã§ã¯ãããã»ã¹ãã£ã¹ãããã£ã®å®è£
ã«é¢é£ããé¨åã«çµã£ã¦è§£èª¬ãã¾ãã
1.2.1 ã«ã¼ãã«ã¹ã¿ãã¯
ã¿ã¹ã¯ãã·ã¹ãã ã³ã¼ã«ãå²ãè¾¼ã¿çã®ããã«ã«ã¼ãã«ã¢ã¼ãã§åä½ããæã«ä½¿ç¨ããã¹ã¿ãã¯ãã«ã¼ãã«ã¹ã¿ãã¯ã¨å¼ã³ã¾ãã
ã«ã¼ãã«ã¹ã¿ãã¯ã¯ãtask_structæ§é ä½ã®stack
ãæãã¢ãã¬ã¹ããTHREAD_SIZE
(configã«ãä¾ãã¾ããx86_64ã§ã¯4ãªãã8ãã¼ã¸)åã®é åãå²ãå½ã¦ããã¦ãã¾ã(åè:alloc_thread_stack_node()
)ãã«ã¼ãã«ã¹ã¿ãã¯ã®æä¸ä½ã¢ãã¬ã¹ã«ã¯ãã¦ã¼ã¶ã¢ã¼ãããã«ã¼ãã«ã¢ã¼ãã«ç§»è¡ããéã«ããã®æã®å種ã¬ã¸ã¹ã¿ã®å¤ãéé¿ãã¦ãã¾ã(pt_regsæ§é ä½ã¨ãã¦åç
§ããã¾ã)ã
1.2.2 thread_structæ§é ä½
ä¸è¨ã®å³ã«ãããã¾ãããtask_structæ§é ä½ã¯ãã¡ã³ãã¨ãã¦thread_structæ§é ä½ãä¿æãã¦ãã¾ã*4ã
thread_structæ§é ä½ã®å®ç¾©ã¯ã¢ã¼ããã¯ãã£æ¯ã«åããã¦ãã¾ããããã¿ã¹ ã¯ãåãæ¿ããéã«ãã¿ã¹ã¯ã®å®è¡ç¶æ
(åã¬ã¸ã¹ã¿å¤ç)ãä¿åã»å¾©æ§ããã®ã«ä½¿ç¨ããã¾ããä¾ãã°ãx86_64 ã®å ´åãsp
ã«ã¯ãã®åã®éãã¹ã¿ãã¯ãã¤ã³ã¿(RSPã¬ã¸ã¹ã¿)ã®å¤ã®ä¿åã»å¾©æ§ã«ä½¿ç¨ããã¾ã(詳細ã¯å¾è¿°ãã¾ã)ã
2. å ¨ä½ã®æµã
ã¿ã¹ã¯ã®åãæ¿ãã®ä¸å¿ã¯ã__schedule()
ã®ä¸ã®context_switch()
ã«ããè¡ããã¾ããcontext_switch()
ãæç²ããã¨ä»¥ä¸ã®ããã«ãªã£ã¦ããã
(kernel/sched/core.c)
5340 /* 5341 * context_switch - switch to the new MM and the new thread's register state. 5342 */ 5343 static __always_inline struct rq * 5344 context_switch(struct rq *rq, struct task_struct *prev, 5345 struct task_struct *next, struct rq_flags *rf) 5346 { 5347 prepare_task_switch(rq, prev, next); 5348 ... 5366 if (!next->mm) { // to kernel 5367 enter_lazy_tlb(prev->active_mm, next); 5368 5369 next->active_mm = prev->active_mm; 5370 if (prev->mm) // from user 5371 mmgrab_lazy_tlb(prev->active_mm); 5372 else 5373 prev->active_mm = NULL; 5374 } else { // to user 5375 membarrier_switch_mm(rq, prev->active_mm, next->mm); ... 5384 switch_mm_irqs_off(prev->active_mm, next->mm, next); 5385 lru_gen_use_mm(next->mm); 5386 5387 if (!prev->mm) { // from kernel 5388 /* will mmdrop_lazy_tlb() in finish_task_switch(). */ 5389 rq->prev_mm = prev->active_mm; 5390 prev->active_mm = NULL; 5391 } 5392 } ... 5399 /* Here we just switch the register state and the stack. */ 5400 switch_to(prev, next, prev); 5401 barrier(); 5402 5403 return finish_task_switch(prev); 5404 }
大ã¾ããªæµãã¨ãã¦ã¯ã
- åå¦ç(L5347)
- ã¡ã¢ãªç©ºéã®åãæ¿ã(L5366-L5392)
- ã¬ã¸ã¹ã¿ã®åãæ¿ã(L5400)
- å¾å¦ç(L5403)
ã®ããã«ãªã£ã¦ãã¾ãã
以éã®ç« ã§ãã¬ã¸ã¹ã¿ã®åãæ¿ãã¨åå¾å¦çã«ã¤ãã¦ã¾ã¨ãããã¨æãã¾ããå°ã説æãã¹ãäºãå¤ããªãã®ã§ãæ¬ç¨¿ã§ã¯ã¿ã¹ã¯ã®ã¡ã¢ãªç©ºéã«ã¤ãã¦ã¯è§¦ãã¾ããã
3. ã¬ã¸ã¹ã¿ã®åãæ¿ã
3.1 é常ã®ã¿ã¹ã¯åãæ¿ã
åè¿°ã®éããã¬ã¸ã¹ã¿ã®åãæ¿ãã¯switch_to()
ã«ããè¡ããã¾ããã以ä¸ã®ããã«å®ç¾©ããã¦ããã
(arch/x86/include/asm/switch_to.h)
49 #define switch_to(prev, next, last) \ 50 do { \ 51 ((last) = __switch_to_asm((prev), (next))); \ 52 } while (0)
ãã®å®ä½ã¯ã__switch_to_asm()
ã¨ããã¢ã»ã³ãã©ã§è¨è¿°ããã¦ãã¾ãã
171 /* 172 * %rdi: prev task 173 * %rsi: next task 174 */ 175 .pushsection .text, "ax" 176 SYM_FUNC_START(__switch_to_asm) 177 /* 178 * Save callee-saved registers 179 * This must match the order in inactive_task_frame 180 */ 181 pushq %rbp 182 pushq %rbx 183 pushq %r12 184 pushq %r13 185 pushq %r14 186 pushq %r15 187 188 /* switch stack */ 189 movq %rsp, TASK_threadsp(%rdi) 190 movq TASK_threadsp(%rsi), %rsp ... 206 /* restore callee-saved registers */ 207 popq %r15 208 popq %r14 209 popq %r13 210 popq %r12 211 popq %rbx 212 popq %rbp 213 214 jmp __switch_to 215 SYM_FUNC_END(__switch_to_asm)
__switch_to_asm()
ã¯ä¸è¨ã®éãã
- åãæ¿ãåã¿ã¹ã¯(
prev
)ã®ã¬ã¸ã¹ã¿ãã«ã¼ãã«ã¹ã¿ãã¯ã«PUSH(L181-L186)ã - ãã®æç¹ã®ã¹ã¿ãã¯ãã¤ã³ã¿(RSPã¬ã¸ã¹ã¿)ããåãæ¿ãåã¿ã¹ã¯(
prev
)ã®thread_struct.spã«ä¿åã(L189)ã - åãæ¿ãå¾ã¿ã¹ã¯(
next
)ã®thread_struct.spãã¹ã¿ãã¯ãã¤ã³ã¿(RSPã¬ã¸ã¹ã¿)ã«å¾©æ§(L190ããã®æç¹ã§ãã¹ã¿ãã¯ã¯åãæ¿ãå¾ã¿ã¹ã¯(next
)ã®ã«ã¼ãã«ã¹ã¿ãã¯ã«ãªã)ã - ã«ã¼ãã«ã¹ã¿ãã¯ã«ä¿åãã¦ããå種ã¬ã¸ã¹ã¿ãPOPãã¦(L207-L212)ã
__switch_to()
ã«ã¸ã£ã³ããã(L214)ã
ã¨ããæµãã«ãªã£ã¦ãã¾ãã
ä¸è¨ã§è¨ãã¨ããæä½éã®ã¬ã¸ã¹ã¿ã®éé¿ã»å¾©æ§ã¨ã«ã¼ãã«ã¹ã¿ãã¯ã®åãæ¿ããè¡ãã__switch_to()
ã«ã¸ã£ã³ããããã¨ããäºã«ãªãã¾ããã3ç¹è£è¶³ãã¦ããã¾ãã
1ç¹ç®ã§ããããªãéé¿ã»å¾©æ§ãè¡ãã®ãRBPãRBXãR12-R15ã§ãããã¨ããç¹ã§ãã
ã¾ãããã以å¤ã®ã¬ã¸ã¹ã¿(FPUç)ã®éé¿ã»å¾©æ§ã¯ã__switch_to()
ã«ããè¡ãããããã__switch_to_asm()
ã§ã¯è¡ãå¿
è¦ãããã¾ãããéã«ããããã®ã¬ã¸ã¹ã¿ã¯ããã§éé¿ã»å¾©æ§ããããã«ããªãã¨ã__switch_to()
ã«ããæ´æ°ããã¦ãã¾ãå¯è½æ§ããããæ£ããç¶æ
ã復å
ã§ããªããªãã¾ãã
次ã«2ç¹ç®ã§ãããCALLå½ä»¤ã§ã¯ãªãJMP(ã¸ã£ã³ã)å½ä»¤ã§__switch_to()
ãå®è¡ãããäºã§ããå
ç¨ãCALLå½ä»¤ã§ã¯ãå®è¡ããæã®Instruction Pointer(RIPã¬ã¸ã¹ã¿)ãCALLå½ä»¤èªèº«ãã¹ã¿ãã¯ã®å
é ã«ç©ãã§ãå¼ã³åºããé¢æ°ã«å¶å¾¡ã移ããå¼ã³åºãããé¢æ°ãå®è¡ããRETå½ä»¤ã«ãããã®ã¹ã¿ãã¯ã®å
é ã«ç©ã¾ãã¦ããã¢ãã¬ã¹ãInstruction Pointer(RIPã¬ã¸ã¹ã¿)ã«å¾©æ§ããå¶å¾¡ãå¼ã³åºãå
ã«æ»ããã¨ãã話ããã¾ããããããã§ã¯æ¢ã«CALLæã®Instruction Pointer(RIPã¬ã¸ã¹ã¿)ãã¹ã¿ãã¯ã«ç©ã¾ããç¶æ
ã§ã¸ã£ã³ãããã®ã§ã__switch_to()
ãreturn(RETå½ä»¤)ããã¨ãcontext_switch()
ã«å¶å¾¡ãæ»ãäºã«ãªãã¾ãã
æå¾ã«3ç¹ç®ã§ããã(å½ç¶ã¨è¨ãã°å½ç¶ãªã®ã§ãã)åãæ¿ãå¾ã¿ã¹ã¯(next
)èªèº«ãå
ã«CPUãå¥ã¿ã¹ã¯ã«æã渡ãéã«ãåãã³ã¼ããå®è¡ãã¦ãã(ãªã®ã§ãã«ã¼ãã«ã¹ã¿ãã¯ã«RBPãRBXãR12-R15ã®å¤ããthread_struct.spã«ã¹ã¿ãã¯ãã¤ã³ã¿ãä¿åããã¦ãã¦å¾©æ§ã§ãã)ã¨ããäºã§ãããã ãããã®æ(åè¿°ã®ãå
ã«CPUãå¥ã¿ã¹ã¯ã«æã渡ãéã)ã®prev
ã¯(ä»ã®)next
èªèº«ãªã®ã§(ã¹ã¿ãã¯ã«ã¯ãã¡ãã®æ
å ±ãæ®ã£ã¦ãã)ããã®ã¾ã¾ã§ã¯ä»CPUãæã渡ããã¨ãã¦ããprev
ãä½ãªã®ãããããªããªã£ã¦ãã¾ãã¾ã(ããã ã¨å¾è¿°ãããå¾å¦çãããã¾ããããªã)ã ãããªããªãããã«ããããã__switch_to()
ã§ã¯æå¾ã«prev
ãè¿ãããããã(å°ã話ãé¡ãã¾ãã)switch_to()
ã®last
ã¨ãã¦å¼ã³åºãå
ã®context_switch()
ã«æ¸¡ãããäºã§ãæ£ããå¾å¦çãè¡ãããäºã«ãªãã¾ã(ããããswitch_to()
ã«last
å¼æ°ã3ã¤ããçç±ã§ã)ã
3.2 çæãããã°ããã®ã¿ã¹ã¯ã¸ã®åãæ¿ã
å
ç¨ããå
ã«CPUãå¥ã¿ã¹ã¯ã«æã渡ãéã«ãåãã³ã¼ããå®è¡ãã¦ãã(ãªã®ã§ãã«ã¼ãã«ã¹ã¿ãã¯ã«RBPãRBXãR12-R15ã®å¤ããthread_struct.spã«ã¹ã¿ãã¯ãã¤ã³ã¿ãä¿åããã¦ãã¦å¾©æ§ã§ãã)ãã¨æ¸ãã¾ãããã1ã¤ã ãä¾å¤ãããã¾ããããã¯ãfork(2)çã«ãã£ã¦çæãããã°ããã®ã¿ã¹ã¯ã§ã(çæãããã°ãããªã®ã§ãå½ç¶èªåã§ä¿åãªã©ã¯ãã¦ããªã)ã
ãã®ã±ã¼ã¹ã«ã¤ãã¦ã¯å¾ç·¨ã§è©³ç´°ã«è§£èª¬ããäºå®ã§ãã
3.3 FPUã®åãæ¿ã
FPUã®éé¿ã»å¾©æ§ãè¡ãã__switch_to()
ã®å¦çã«ã¤ãã¦ãã詳細ã¯å¾ç·¨ã«ã¦è§£èª¬ããäºå®ã§ãã
4. åå¾å¦ç
æ¬ç« ã§ã¯ãcontext_switch()
ããå¼ã°ãããprepare_task_switch()
ãåã³finish_task_switch()
ã§è¡ããããåå¾å¦çã«ã¤ãã¦ç°¡åã«èª¬æãã¾ãã
åå¾å¦çã§è¡ãããã®ã¯ãä¸è¨ã§è¨ãã°ãã¿ã¹ã¯ã«çµã³ã¤ãæ
å ±ã管çãã¦ãããã«ã¼ãã«å
ã®æ§ã
ãªãµãã·ã¹ãã ã«ã¤ãã¦ããã®åãæ¿ããè¡ããäºã«ããã¾ããããã§ã¯ãããã¤ãã®ãµãã·ã¹ãã ã«ã¤ãã¦ä¾ãæããªãã解説ã ã¾ãã
4.1 schedstat
Linuxã§ã¯/proc/<PID>/schedstat
ããå½è©²ã¿ã¹ã¯ã®å®è¡æéçã®çµ±è¨æ
å ±ã確èªããäºãã§ãã¾ãã
å®è¡æéãéè¨ãããããã¿ã¹ã¯ã®åãæ¿ããè¡ãããéã«ã¯ãåãæ¿ãåã®ã¿ã¹ã¯ã®éè¨ãæ¢ãã¦åãæ¿ãå¾ã®ã¿ã¹ã¯ã®éè¨ãéå§ããå¿
è¦ãããã¾ããããããè¡ã£ã¦ããã®ãprepare_task_switch()
ããå¼ã°ããsched_info_switch()
ã§ãã
4.2 perf
ããã©ã¼ãã³ã¹åæã«ä½¿ãããperfãã¿ã¹ã¯æ¯ã®æ§è½æ
å ±ã管çãããããåå¾å¦çã§åãæ¿ãå¦çãè¡ããã¾ã*5ã
å
·ä½çã«ã¯ãprepare_task_switch()
ããå¼ã°ããperf_event_task_sched_out()
ã¨finish_task_switch()
ããå¼ã°ããperf_event_task_sched_in()
ã«ããåãæ¿ãå¦çãè¡ããã¾ãã
4.3 notifier
å2ç¯ã§ã¯ãæ¢ã«ã½ã¼ã¹ã¬ãã«ã§çµã¿è¾¼ã¾ãã¦ãããç¹å®ã®ãµãã·ã¹ãã ã«ãããåãæ¿ãå¦çã«ã¤ãã¦è¦ã¦ã¿ã¾ããããã¿ã¹ã¯åãæ¿ãæã«å®è¡ãããå¦çãåçã«è¿½å ããæ©è½ãæºåããã¦ãã¾ãã
å
·ä½çã«ã¯ãpreempt_notifier_register()
ã¨ããé¢æ°ã§notifierãç»é²ããã°ãprepare_task_switch()
ããå¼ã°ããfire_sched_out_preempt_notifiers()
ãåã³finish_task_switch()
ããå¼ã°ããfire_sched_in_preempt_notifiers()
ãçµç±ãã¦ãç»é²ããnotifierã®ã³ã¼ã«ããã¯é¢æ°ãå®è¡ããã¾ãã
5. æå¾ã«
æ¬ç¨¿ã§ã¯ãé§ã足ã§ã¯ããã¾ãããããã»ã¹ãã£ã¹ãããã£(ã¿ã¹ã¯ã®åãæ¿ãå¦ç)ã®åºæ¬çãªé¨åã«ã¤ãã¦ã¾ã¨ãã¦ã¿ã¾ããã
å¾ç·¨ã§ã¯ãæ¬ç¨¿ã§ã¯æ¸ããããªãã£ããçæãããã°ããã®ã¿ã¹ã¯ã¸ã®åãæ¿ããFPUã®åãæ¿ãã®è©±ã«ã¤ãã¦èª¬æããäºå®ã§ãã
åèè³æ
*1:æ¬é ã§ã¯ã¡ã¢ãªãå³ç¤ºããéãä¸ä½ã¢ãã¬ã¹ãä¸ã«(ä¸ä½ã¢ãã¬ã¹ãä¸ã«)å³ç¤ºãã¾ãã
*2:MOVå½ä»¤ã§ããã¼ã¿ä¿åã»åãåºãã¯ã§ãã¾ããããã®å ´åStack Pointer(RSPã¬ã¸ã¹ã¿)ã¯å¢æ¸ããã¾ããã
*3:æ¬ç¨¿ã§ã¯ããã»ã¹ãã¹ã¬ããã¨ãã£ããOSã«ãããå®è¡åä½ã®äºããã¿ã¹ã¯ãã¨å¼ç§°ãã¾ãã
*4:å®è£ ã®é½åä¸ãå¿ ãæå¾ã®ã¡ã³ãã¨ãªã£ã¦ãã¾ãã
*5:perfã®ä»çµã¿ãå®è£ ã«ã¤ãã¦ã¯ãæªå®ã§ãããå¥éãè¨äºåã§ããã°ã¨æãã¾ã