schedule
__schedule
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);
for_each_class(class) class->pick_next_task(rq);
context_switch(rq, prev, next, &rf);
prepare_lock_switch(rq, next, rf);
rq_unpin_lock(rq, rf);
switch_to(prev, next, prev);
__switch_to(prev,task_thread_info(prev), task_thread_info(next));
ENTRY(__switch_to)
UNWIND(.fnstart )
UNWIND(.cantunwind )
add ip, r1, #TI_CPU_SAVE
ARM( stmia ip!, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack
ldr r4, [r2, #TI_TP_VALUE]
ldr r5, [r2, #TI_TP_VALUE + 4]
switch_tls r1, r4, r5, r3, r7
mov r5, r0
add r4, r2, #TI_CPU_SAVE
ldr r0, =thread_notify_head
mov r1, #THREAD_NOTIFY_SWITCH
bl atomic_notifier_call_chain
mov r0, r5
ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously
UNWIND(.fnend )
ENDPROC(__switch_to)
---
#define switch_tls switch_tls_v6k
.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
mcr p15, 0, \tpuser, c13, c0, 2 @ and the user r/w register
str \tmp2, [\base, #TI_TP_VALUE + 4] @ save it
.endm
问题 :
1.为什么 不保存 c13, c0, 3 (到 task_thread_info(prev) 中的 tp_value[0]) ???
2.TLS 是干什么的
---
atomic_notifier_call_chain
notifier_call_chain
nb->notifier_call(nb, val, v);
---
arch/arm/include/asm/thread_info.h
struct 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];
};
有 switch 就有 store
我们看 switch 之后,有哪些状态是跟当前进程密切相关的
cpu寄存器 :
r0 : current task_struct
r1 : 不重要
r2 : current task_struct
r3 : 不重要
r4 - r10 : 重要
r11 : fp
r12 : 不重要
r13 : sp
r14 : 不重要
r15 : pc
cp15 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 保存了
在哪一句切出:
ARM( ldmia r4, {r4 - sl, fp, sp, pc} )
切回的第一句:
context_switch->barrier
其他
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
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;
}