任务切换涉及到当前任务CPU运行环境保存和新任务环境恢复两个步骤。下面用x86的GNU汇编语言分别列出了CPU环境保存和恢复的功能实现。
CPU 环境寄存器结构。
typedef struct {
register_t Edi;
register_t Esi;
register_t Ebp;
register_t Esp;
register_t Ebx;
register_t Edx;
register_t Ecx;
register_t Eax;
register_t EFlags;
register_t Eip;
} CONTEXT_t;
偏移量定义:
#define FRAME_OFFSET_PC 0
#define FRAME_OFFSET_PARAM0 4
#define FRAME_OFFSET_PARAM1 8
// offset for registers of context
#define CONTEXT_OFFSET_EDI 0
#define CONTEXT_OFFSET_ESI 4
#define CONTEXT_OFFSET_EBP 8
#define CONTEXT_OFFSET_ESP 12
#define CONTEXT_OFFSET_EBX 16
#define CONTEXT_OFFSET_EDX 20
#define CONTEXT_OFFSET_ECX 24
#define CONTEXT_OFFSET_EAX 28
#define CONTEXT_OFFSET_EFLAG 32
#define CONTEXT_OFFSET_EIP 36
当前任务上下文保存:
.globl_context_save
.globlcontext_save
.align4
_context_save:
context_save:
// get _p_context of context_save () for saving
movl FRAME_OFFSET_PARAM0(%esp), %edx
// save local variable registers into _p_context
movl %ebx, (CONTEXT_OFFSET_EBX)(%edx)
movl %esi, (CONTEXT_OFFSET_ESI)(%edx)
movl %edi, (CONTEXT_OFFSET_EDI)(%edx)
// save stack corresponding registers into _p_context
leal FRAME_OFFSET_PARAM0(%esp), %ecx
movl %ecx, (CONTEXT_OFFSET_ESP)(%edx)
movl %ebp, (CONTEXT_OFFSET_EBP)(%edx)
// save PC into _p_context
movl FRAME_OFFSET_PC(%esp), %ecx
movl %ecx, (CONTEXT_OFFSET_EIP)(%edx)
//return 0 to indicate a return from context_save ()
xorl %eax, %eax
ret
新任务恢复:
.globl_context_restore
.globlcontext_restore
.align4
_context_restore:
context_restore:
//get _p_context of context_restore ()
movlFRAME_OFFSET_PARAM0(%esp), %ecx
//take 2nd parameter of context_restore () as return value of context_save ()
movlFRAME_OFFSET_PARAM1(%esp), %eax
//restore registers from context
movl(CONTEXT_OFFSET_EIP)(%ecx), %edx
movl(CONTEXT_OFFSET_EBX)(%ecx), %ebx
movl(CONTEXT_OFFSET_ESI)(%ecx), %esi
movl(CONTEXT_OFFSET_EDI)(%ecx), %edi
movl(CONTEXT_OFFSET_EBP)(%ecx), %ebp
movl(CONTEXT_OFFSET_ESP)(%ecx), %esp
//jump to context_save ()
jmp *%edx
任务切换函数:
voidcontext_switch (CONTEXT_t *_p_current, CONTEXT_t *_p_next)
{
if (0 == _context_save (_p_current)) {
_context_restore (_p_next, 1);
}
}
X86任务切换机制
于 2014-10-29 10:18:07 首次发布