switch_to

来源:互联网 发布:网宿科技云计算收入 编辑:程序博客网 时间:2024/04/29 21:27

<!--@page { margin: 2cm }P { margin-bottom: 0.21cm }-->

理论部分请参考《深入理解Linux内核》第三章。

1switch_to宏:

#defineswitch_to(prev,next,last)/

do{/

last= __switch_to(prev,task_thread_info(prev), task_thread_info(next));/

}while (0)

 

2__switch_to的函数是现在entry-armv.S中:

/*

*Register switch for ARMv3 and ARMv4 processors

*r0 = previous task_struct, r1 = previous thread_info, r2 = nextthread_info

*previous and next are guaranteed not to be the same.

*/

ENTRY(__switch_to)

UNWIND(.fnstart)

UNWIND(.cantunwind)

addip,r1, #TI_CPU_SAVE

ldrr3,[r2, #TI_TP_VALUE]

ARM(stmiaip!,{r4 - sl, fp, sp, lr} )@ Store most regs on stack

THUMB(stmiaip!,{r4 - sl, fp} )@ Store most regs on stack

THUMB(strsp,[ip], #4 )

THUMB(strlr,[ip], #4 )

#ifdefCONFIG_MMU

ldrr6,[r2, #TI_CPU_DOMAIN]

#endif

#ifdefined(CONFIG_HAS_TLS_REG)

mcrp15,0, r3, c13, c0, 3@ set TLS register

#elif!defined(CONFIG_TLS_REG_EMUL)

movr4,#0xffff0fff

strr3,[r4, #-15]@ TLS val at 0xffff0ff0

#endif

#ifdefCONFIG_MMU

mcrp15,0, r6, c3, c0, 0@ Set domain register

#endif

movr5,r0

addr4,r2, #TI_CPU_SAVE

ldrr0,=thread_notify_head

movr1,#THREAD_NOTIFY_SWITCH

blatomic_notifier_call_chain

THUMB(movip,r4 )

movr0,r5

ARM(ldmiar4,{r4 - sl, fp, sp, pc} )@ Load all regs saved previously

THUMB(ldmiaip!,{r4 - sl, fp} )@ Load all regs saved previously

THUMB(ldrsp,[ip], #4 )

THUMB(ldrpc,[ip] )

UNWIND(.fnend)

ENDPROC(__switch_to)

 

为了便于分析,将上面的源代码用工具反汇编后得到下列的输出:

000004f0<__switch_to>:

r0= previous task_struct

r1= previous thread_info

r2= next thread_info

4f0: e281c01c add ip, r1, #28 ; 0x1c

ip的内容为previou进程的thread_info结构体中cpu_context成员的地址。

4f4: e5923060 ldr r3, [r2, #96]

取得next进程的tp_valuetp_value里保存了将要写到armTP寄存器中的值,由于是armv7新加功能,所以还没有看具体怎么用。

4f8: e8ac6ff0 stmia ip!, {r4, r5, r6, r7, r8, r9, sl, fp, sp,lr}

保存当且上下文到previou进程的thread_info结构体中cpu_context成员中。

4fc: e5926018 ldr r6, [r2, #24]

取得next进程的cpu_domain

500: ee0d3f70 mcr 15, 0, r3, cr13, cr0, {3}

504: ee036f10 mcr 15, 0, r6, cr3, cr0, {0}

next进程的tp_valuecpu_domain写入armTP和域寄存器。

注:记得原来的内核只支持3domain,谁知道现在已经支持4个了,这个有时间可以分析一下。

508: e1a05000 mov r5, r0

50c: e282401c add r4, r2, #28 ; 0x1c

510: e59f000c ldr r0, [pc, #12] ; 524 <__switch_to+0x34>

514: e3a01002 mov r1, #2 ; 0x2

518: ebfffffe bl 0 <atomic_notifier_call_chain>

向通知链上的子系统通知该事件。

51c: e1a00005 mov r0, r5

520: e894aff0 ldm r4, {r4, r5, r6, r7, r8, r9, sl, fp, sp,pc}

将新的进程(next进程)的上下文恢复,程序切换的新的进程执行。

注:根据ATPCSr0~r2用于传递参数,而r4~r11全部由子程序负责保存(这个和x86一人负责一部分的方式还不太一样)。所以r4中的值可以继续使用,而r0的值需暂时保存到r5中。