Switch_to调用机制及调用过程
在/kernel/sched/core.c中有内核调度的核心函数:__schedule,在调度函数中通过调用context_switch进行进程上下文的切换。
context_switch对函数的调用见上图所示,主要完成的工作是mm的切换和硬件上下文的切换,我们主要讨论硬件上下文切换过程。
整体的调用过程如下图:
在arch/arm/include/asm/switch_to.h中有对switch_to的定义:
在源码中可以发现,switch_to(prev,next,last)是个宏定义,真正的操作在do{}中。
根据do{}的内容可知:
首先执行了__complete_pending_tlbi()函数,根据其定义的解释便知其作用是:在armV7架构中,运行的是抢占式内核,因此在TLB维护操作时需要进行抢占,因此为了能够在转移至另一个CPU工作前将维护工作完成,需要执行dsb(ish)来进行保证。因此说,__complete_pending_tlbi()只在armV7架构中其作用。
所以switch_to的重头戏便是:
last = __switch_to(prev,task_thread_info(prev),task_thread_info(next));
真正传递参数的为prev的task_struct、prev的task_thread_info以及next的task_thread_info,返回值为last。因此下边一节进入__switch_to的汇编进行此过程的详细分析。
通过源码的查找,在两个.S文件中发现了__switch_to的定义:arch/arm/kernel/entry-armv.S以及arch/arm/kernel/entry-v7m.S,这两个汇编文件中的__switch_to函数分别对应于ARMv3/4处理器和ARMv7处理器,首先对entry-armv.S进行分析。
ARMv3/4架构Switch_to汇编代码:
首先是函数注释,通过注释我们发现对应的处理器是ARMv3和ARMv4,并且传入的三个参数为:r0 = previous task_struct,r1 = previous thread_info, r2 = next thread_info。
ENTRY、ENDPROC分别是对函数头尾的声明,.fnstart是函数开始执行的标志,这些我们在这里不讨论。主要分析被上述两块包含的内容。
通过对代码的大致分析,姑且先将其分为4部分进行分块分析:
1、Store mostregs on previous thread_info