2. pthread_create(pthread_t *tid, const pthread_attr_t *attr, void * (*func)(void *), void
=> create_thread (struct pthread *pd, const struct pthread_attr
*attr,STACK_VARIABLES_PARMS)
3. create_thread (struct pthread *pd, const struct pthread_attr *attr,STACK_VARIABLES_PARMS)
* pd :
pthread_t *tid => ALLOCATE_STACK 分配并初始化
* attr:
default_attr
* STACK_VARIABLES_PARMS:
user thread stack (pd -1)
=> int res = do_clone (pd, attr, clone_flags, start_thread,STACK_VARIABLES_ARGS, 1);
4. static int do_clone (struct pthread *pd, const struct pthread_attr *attr,
int clone_flags, int (*fct) (void *), STACK_VARIABLES_PARMS, int stopped)
* clone_flags:
int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL
| CLONE_SETTLS | CLONE_PARENT_SETTID
| CLONE_CHILD_CLEARTID | CLONE_SYSVSEM
* fct :
start_thread => /* Run the code the user provided. */
THREAD_SETMEM (pd, result, pd->start_routine (pd->arg));
* stopped
* 其他同上
=> ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags,
pd, &pd->tid, TLS_VALUE, &pd->tid)
5. ENTRY(__clone) :
int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
pid_t *ptid, struct user_desc *tls, pid_t *ctid);
R0 => fct (start_thread ,function pointer)
R1 => STACK_VARIABLES_ARGS (user thread stack pointer)
R2 => clone_flags
R3 => pd (pthead pointer)
user sp => &pd->tid (ptid pointer)
user sp -4 => TLS_VALUE (pd+1, tls start addr)
user sp -8 => &pd->tid (ctid pointer)
R0 <= R2 (clone_flags)
R1 <= R1 STACK_VARIABLES_ARGS (user thread stack pointer)
R2 <= user sp (ptid pointer)
R3 <= user sp -4 (TLS_VALUE)
R4 <= user sp -8 (ctid pointer)
=> R7 <= sys_clone_wrapper (120)
swi 0
user :
-----------------------------------------------------------------------------------
kernel :
1. ENTRY(vector_swi)
* 开始构建 c 函数 sys_clone的栈:
High addr:
(FD 栈)
| ...... |
|--------------------|
上次user sp ---> | xxxx |
|--------------------|
ARM_ORIG_r0 ---> | R0 |<-------------------------------------------
|--------------------| A
ARM_cpsr ---> | spsr | swi 前的cpsr (user 下的) |
|--------------------| |
ARM_pc ---> | swi 指令下一条地址 | #S_FRAME_SIZE
ARM_lr ---> | LR_usermode | |
|--------------------| |
ARM_sp ---> | SP_usermode | |
|--------------------| |
ARM_ip ---> | R12 | R12-R1 |
| ... | |
| ... | |
ARM_r1 ---> | R1 | |
|--------------------| V
ARM_r0 ---> | R0 | <--- (pt_regs *)------------------------
|--------------------|
syscall参数6---> | R5 |
|--------------------|
syscall参数5---> | R4 | <---- 当前 svc sp
|--------------------|
Low addr
根据上面的栈
a. syscall 时kernel 栈上ARM_r0和ARM_ORIG_r0 看起来是一样的内容
其他异常不一样
b. syscall 最大参数 6个放到R0-R5,在具体call kernel 函数前,总认为
传了6个,所以按规则 参数1-4放 R0-R1, 参数5,6压栈
* 根据 scno (R7) 查表到sys_clone_wrapper跳转执行
cmp scno, #NR_syscalls @ check upper syscall limit
adr lr, ret_fast_syscall @ return address @ 注意返回到ret_fast_syscall
在执行完 sys_clone_wrapper后
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
2. sys_clone_wrapper
因为sys clone 没有6个参数,所以根据时间情况调整 上面的栈:
ARM_r0 ---> | 上面不变 | <--- (pt_regs *)------------
|--------------------|
syscall参数---> | pt_regs * | 从R5 改变为上面 pt_regs 所指地址
|--------------------|
syscall参数5---> | R4 | <---- 当前 svc sp
|--------------------|
3. 执行 c 函数 sys_clone:
int sys_clone(unsigned long clone_flags(R0), unsigned long newsp(R1),
int __user *parent_tidptr(R2), int tls_val(R3),
int __user *child_tidptr(svc sp), struct pt_regs *regs (svc sp-4))
4. sys_clone 返回 执行 ret_fast_syscall
如果没有发生调度,那么
恢复swi 前所有用户上下文,并获取 arm_pc (值为swi 0下面那句)
栈如下:
| ...... |
|--------------------|
上次user sp ---> | xxxx |
|--------------------|
下面的部分全部出栈了