linux kernel进程切换(寄存器保存与恢复)
在threadA執行時,被調度了執行了threadB, 那么在threadB執行完之后是如何恢復threadA進程能夠繼續執行的呢?
我們從代碼中去尋找答案, 系統調度是schedule()函數,那么我們就從schedule()函數看起
schedule() --> __schedule(true) --> context_switch(rq, prev,next) --> switch_to(prev, next, prev) --> __switch_to((prev), (next))
1、通用寄存器的保存
schedule() --> __schedule(true) --> context_switch(rq, prev,next) --> switch_to(prev, next, prev) --> __switch_to((prev), (next)) --> cpu_switch_to(prev, next)
根據ARM標準文檔描述<IHI0056C_beta_aaelf64.pdf>, x19~x28是屬于
callee-saved registers,需要保存,此外sp,lr,pc也需要保存
THREAD_CPU_CONTEXT為thread.cpu_context在struct task_struct結構體中的偏移
DEFINE(THREAD_CPU_CONTEXT, offsetof(struct task_struct, thread.cpu_context)); struct task_struct {......struct thread_struct thread;}; struct thread_struct {struct cpu_context cpu_context; /* cpu context */unsigned long tp_value; /* TLS register */ #ifdef CONFIG_COMPATunsigned long tp2_value; #endifstruct fpsimd_state fpsimd_state;unsigned long fault_address; /* fault info */unsigned long fault_code; /* ESR_EL1 value */struct debug_info debug; /* debugging */ } struct cpu_context {unsigned long x19;unsigned long x20;unsigned long x21;unsigned long x22;unsigned long x23;unsigned long x24;unsigned long x25;unsigned long x26;unsigned long x27;unsigned long x28;unsigned long fp;unsigned long sp;unsigned long pc; };問與答:
關于前面的一段匯編,上面stp的一段是壓棧,將前一個進程的寄存器保存起來。
后面ldp的一段是出棧,將后一個進程的寄存器恢復出來。
關于棧,不都是先進后出嗎? 為何這里是先進先出、后進后出?
在arm32上,是PUSH,POP等指令,是先進后出
到了arm64上,沒有了PUSH POP指令,取而代之的是STP LDP,這個指令其實就是讀寄存器,沒有"先進/后進/先出/后出"等概念了,你想怎么進就怎么進,想怎么出就怎么出
總結
以上是生活随笔為你收集整理的linux kernel进程切换(寄存器保存与恢复)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux kernel的spin_lo
- 下一篇: linux kernel的virtual