博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OK6410A 开发板 (八) 21 linux-5.11 OK6410A schedule 的 __switch_to 部分
阅读量:4284 次
发布时间:2019-05-27

本文共 5348 字,大约阅读时间需要 17 分钟。

  • schedule
schedule 																			// kernel/sched/core.c	__schedule 																		// kernel/sched/core.c		struct rq_flags rf;		int cpu = smp_processor_id();		struct rq *rq = cpu_rq(cpu);		struct task_struct *prev = rq->curr;		rq_lock(rq, &rf);				deactivate_task(rq, prev, DEQUEUE_SLEEP | DEQUEUE_NOCLOCK);				struct task_struct *next = pick_next_task(rq, prev, &rf); 					// kernel/sched/core.c			for_each_class(class) class->pick_next_task(rq);					context_switch(rq, prev, next, &rf); 										// kernel/sched/core.c			prepare_lock_switch(rq, next, rf);				rq_unpin_lock(rq, rf);			switch_to(prev, next, prev); 											// arch/arm/include/asm/switch_to.h				__switch_to(prev,task_thread_info(prev), task_thread_info(next)); 	// arch/arm/kernel/entry-armv.S
  • __switch_to
// arch/arm/kernel/entry-armv.S/* * Register switch for ARMv3 and ARMv4 processors * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info * previous and next are guaranteed not to be the same. */ENTRY(__switch_to) UNWIND(.fnstart	) UNWIND(.cantunwind	)	add	ip, r1, #TI_CPU_SAVE // 24 cpu_context	// 保存 r4-r10	// 保存 r11	// 保存 r13	// 保存 r14 ARM(	stmia	ip!, {
r4 - sl, fp, sp, lr} ) @ Store most regs on stack // 保存到 task_thread_info(prev)->cpu_context (类型为struct cpu_context_save)中的成员中 // 此时已经开始 switch // switch_tls ldr r4, [r2, #TI_TP_VALUE] // 92 // tp_value // thread local Storage // c13,c0,3 ldr r5, [r2, #TI_TP_VALUE + 4] // 96 // user register // c13,c0,2 switch_tls r1, r4, r5, r3, r7 mov r5, r0 add r4, r2, #TI_CPU_SAVE // 24 cpu_context // atomic_notifier_call_chain ldr r0, =thread_notify_head mov r1, #THREAD_NOTIFY_SWITCH bl atomic_notifier_call_chain mov r0, r5 // r0 current task_struct // r4 task_thread_info(next)->cpu_context ARM( ldmia r4, {
r4 - sl, fp, sp, pc} ) @ Load all regs saved previously // 将 task_thread_info(next)->cpu_context 中的成员 加载到 对应的寄存器中 // r4-r10 r11 r13 r14 r15 // switch 完毕 UNWIND(.fnend )ENDPROC(__switch_to)---#define switch_tls switch_tls_v6k // arch/arm/include/asm/tls.h // arm1176jzfs trm 手册 P262 // 读写这些 寄存器 除了存储不会产生其他效果 .macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2 mrc p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register mcr p15, 0, \tp, c13, c0, 3 @ set TLS register // 将 task_thread_info(next) 中的 tp_value[0] 放到 c13,c0,3 (TLS register) mcr p15, 0, \tpuser, c13, c0, 2 @ and the user r/w register // 将 task_thread_info(next) 中的 tp_value[1] 放到 c13,c0,2 (user r/w register) str \tmp2, [\base, #TI_TP_VALUE + 4] @ save it // 存储到 task_thread_info(prev) 中的 tp_value[1]; .endm 问题 : 1.为什么 不保存 c13, c0, 3 (到 task_thread_info(prev) 中的 tp_value[0]) ??? 2.TLS 是干什么的---atomic_notifier_call_chain // kernel/notifier.c notifier_call_chain nb->notifier_call(nb, val, v); // contextidr_notifier // 本配置不会调用 任何 notifier_call---arch/arm/include/asm/thread_info.hstruct cpu_context_save {
__u32 r4; __u32 r5; __u32 r6; __u32 r7; __u32 r8; __u32 r9; __u32 sl; __u32 fp; __u32 sp; __u32 pc; __u32 extra[2]; /* Xscale 'acc' register, etc */ };
有 switch 就有 store我们看 switch 之后,有哪些状态是跟当前进程密切相关的cpu寄存器 : 	r0 : current task_struct	r1 : 不重要	r2 : current task_struct	r3 : 不重要	r4 - r10 : 重要	r11 : fp	r12 : 不重要	r13 : sp	r14 : 不重要	r15 : pccp15 c13 寄存器	c13,c0,2 : thread_info 中的 user register	c13,c0,3 : thread_info 中的 tp_value	看起来上面的状态在 switch 之前都得 被 保存起来	r0/r1/r2/r3/r12/r15 没保存	r4 - r11/r13/r14 保存了 (pc是用的lr)	c13,c0,2 保存了
  • 进程切出的最后一句,切回的第一句
在哪一句切出: // 重点看 现在更改的 pc	ARM(	ldmia	r4, {
r4 - sl, fp, sp, pc} )切回的第一句: // 重点看 之前保存的 lr context_switch->barrier // ???

其他

// g++ thread_local.c  -o thread_local -std=c++11 -pthread// file thread_local.c// 对于关键字 thread_local 定义的 变量 range, 每创建一个 thread,就会新增一份 range 的实体#include 
#include
#include
pthread_t pthid1,pthid2;sem_t sem;thread_local int range = 1;static void * fun1(void *arg){
sem_wait(&sem); printf("second,range:%d\n",range); return NULL;}static void * fun2(void *arg){
range = 2222; printf("fist,range:%d\n",range); sem_post(&sem); return NULL;}int main(int argc, const char *argv[]){
range = 3333; sem_init(&sem, 0, 0); if(0 != pthread_create(&pthid1,NULL,fun1,NULL)){
perror("pthid1"); return -1; } if(0 != pthread_create(&pthid2,NULL,fun2,NULL)){
perror("pthid2"); return -1; } pthread_join(pthid1,NULL); pthread_join(pthid2,NULL); printf("third,range:%d\n",range); return 0;}/*fist,range:2222second,range:1third,range:3333*/

转载地址:http://ncigi.baihongyu.com/

你可能感兴趣的文章
关于坛友的一个布局问题的解答
查看>>
网页抓取:PHP实现网页爬虫方式小结
查看>>
国民岳父的“屁民理论”
查看>>
我为什么要写博客?
查看>>
博客测试:博客系统i94web beta1.0 请求测试
查看>>
XAMPP:访问phpmyadmin出错的解决方案
查看>>
怎么用PHP在HTML中生成PDF文件
查看>>
PHP中我经常容易混淆的三组函数
查看>>
DOM笔记(一):HTMLDocument接口
查看>>
DOM笔记(二):Node接口
查看>>
DOM笔记(三):Element接口和HTMLElement接口
查看>>
DOM笔记(四):HTML 5 DOM复杂数据类型
查看>>
DOM笔记(五):JavaScript的常见事件和Ajax小结
查看>>
DOM笔记(六):怎么进行JQuery扩展?
查看>>
搜索和网页排名的数学原理
查看>>
DOM笔记(八):JavaScript执行环境和垃圾收集
查看>>
响应式下的下拉菜单
查看>>
DOM笔记(九):引用类型、基本包装类型和单体内置对象
查看>>
也谈学习
查看>>
DOM笔记(十):JavaScript正则表达式
查看>>