- 论坛徽章:
- 0
|
错~
如果是从异常返回的话。Cli禁止中断。(中断返回时,本地中断是禁止的)
1. 确定要返回到内核态还是用户态。
2. 如果是返回到内核态的话:
resume_kernel:
cli
cmpl $0, 0x14(%ebp) //检查是否可以抢占thread_info->preempt_count
jz need_resched
restore_all:
popl %ebx
popl %ecx
popl %edx
popl %esi
popl %edi
popl %ebp
popl %eax
popl %ds
popl %es
addl $4, %esp
iret //中断和异常退出的硬件处理过程
need_resched:
movl 0x8(%ebp), %ecx
testb $(1<<TIF_NEED_RESCHED), %cl
jz restore_all //如果falgs没有设置TIF_NEED_RESCHED,不需要抢占
testl $0x00000200,0x30(%esp)
jz restore_all //如果正在禁用本地CPU,不需要抢占
call preempt_schedule_irq //打开本地中断,调用preempt_schedule,进行抢占
jmp need_resched
3. 如果是返回到用户态的话:
resume_userspace:
cli
movl 0x8(%ebp), %ecx
andl $0x0000ff6e, %ecx //检查flags是否只设置了某些标志
je restore_all
jmp work_pending
work_pending:
testb $(1<<TIF_NEED_RESCHED), %cl
jz work_notifysig //如果falgs没有设置TIF_NEED_RESCHED,不需要调度
work_resched:
call schedule //进程调度
cli
jmp resume_userspace
work_notifysig: //处理挂起的信号,虚拟8086和单步执行
movl %esp, %eax
testl $0x00020000, 0x30(%esp)
je 1f
work_notifysig_v86:
pushl %ecx
call save_v86_state
popl %ecx
movl %eax, %esp
1:
xorl %edx, %edx
call do_notify_resume
jmp restore_all
restore_all:
popl %ebx
popl %ecx
popl %edx
popl %esi
popl %edi
popl %ebp
popl %eax
popl %ds
popl %es
addl $4, %esp
iret //中断和异常退出的硬件处理过程
注意:不管返回到内核态还是返回到用户态,都会试图进行进程调度。在返回内核态进行进程调度就叫做内核抢占。在返回用户态进行进程调度属于普通进程调度。它们都会检查current->thread_info->flags 的TIF_NEED_RESCHED标志是否需要进行进程调度。但是返回内核态的时候,额外的需要检查current->thread_info->preempt_count的内核抢占位确定是否可以进行内核抢占。
|
|