2017-01-11

文来自本人的旧博客: blog.163.com/awaken_ing/blog/static/12061319720158310574442/

<< Professional Linux Kernel Architecture >> page105标题为 Intricacies of switchto (intricacies:错综复杂的) , 絮絮叨叨着switchto.

下面看下arm linux的情况.

context_switch(struct rq *rq, struct task_struct *prev,
           struct task_struct *next)
{
...
switch_to(prev, next, prev);
barrier();
 /*
假定进程A被调出去, 进程B运行, 即switch_to(A, B, A)
那么, 这里是刚才被调度走的进程A 恢复运行后, 会执行这个地方, 
要验证的话, 可以看看进程A让出CPU前, 最后一条修改lr的指令.
*/
 finish_task_switch(this_rq(), prev);
}

进程A让出CPU前, 最后一条修改lr的指令:

(gdb) disass schedule
...
0xc02b997c <+648>:  bl  0xc02bb514 <__switch_to>
0xc02b9980 <+652>:  bl  0xc0043524 <finish_task_switch>
...

(gdb) disass __switch_to
...
0xc02bb51c <+8>:    stmia   r12!, {r4, r5, r6, r7, r8, r9, r10, r11, sp, lr}
...

最后一条修改lr的指令为bl, 之后_switchto()中的stmia指令将lr保存到struct threadinfo的成员struct cpucontextsave cpucontext中.

#define switch_to(prev,next,last) \
do {    \
    last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \
} while (0)

书中有上图, 进程A被调度出去后, 之后又准备投入运行, 也就是准备执行contextswitch()中的switchto(), 这时, 为何不是 next==B, prev==A, 而是prev==C.

(switchto()的返回值? 从汇编来看, 没有用到这个返回值.)
进程A恢复运行(进程C调用switch
to( , 进程A ,))后, prev这个进程栈内的变量变了, 是因为
switch_to中

linux-2.6.35.7/arch/arm/kernel/entry-armv.S

ENTRY(__switch_to)
...
 ARM(    stmia    ip!, {r4 - sl, fp, sp, lr} )    @ Store most regs on stack
…
 ARM(    ldmia    r4, {r4 - sl, fp, sp, pc}  )    @ Load all regs saved previously

可以看到并没有保存r0或r1.

switchto()的r0, 在 进程切换前后 进行传递, 用来告诉 切换后的进程 前面的struct taskstruct 信息.

附 进程的栈等信息是存储在哪?

不好意思, 内核换到linux-3.10.86了.

linux-3.10.86/arch/arm/kernel/entry-armv.S

ENTRY(__switch_to)
 add    ip, r1, #TI_CPU_SAVE
 ...
 ARM(    stmia    ip!, {r4 - sl, fp, sp, lr} )    @ Store most regs on stack

所以, 要看看r1和TICPUSAVE都是啥? 注释中有

  • r0 = previous taskstruct, r1 = previous threadinfo, r2 = next thread_info

linux-3.10.86/arch/arm/kernel/asm-offsets.c

DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));

所以, 是存储在 thread->cpu_context

linux-3.10.86/arch/arm/include/asm/thread_info.h

struct thread_info {

struct cpu_context_save    cpu_context;    /* cpu context */
}

本文地址: https://awakening-fong.github.io/posts/scheduler/scheduler_03_switch_to

转载请注明出处: https://awakening-fong.github.io


若无法评论, 请打开JavaScript, 并通过proxy.


blog comments powered by Disqus