代码拉取完成,页面将自动刷新
#include <task.h>
#include <desc.h>
#include <share.h>
#include <8259A.h>
volatile TASK* current_task = NULL; // 当前任务指针,永远指向当前任务
volatile U32 current_reg; // 当前任务的上下文起始位置
LIST TASK_LIST; // 任务链表头
/******************************************************************************
* 函数名称: SwitchTo(TASK* task)
* 功能说明: 切换到任务 task 执行
* 输入参数: TASK* task --任务指针
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET SwitchTo(TASK* task)
{
// 取任务上下文(寄存器)基址
U32* reg_base = (U32*)(&task->reg);
// 检查参数合法性
if(NULL == task || NULL == reg_base)
return E_ERR;
// 恢复上下文
asm volatile(
"movl %0, %%esp\n" // 先将栈顶指针 esp 指向任务上下文 reg 的起始位置
"popl %%gs\n"
"popl %%fs\n"
"popl %%es\n"
"popl %%ds\n"
"popal\n" // popal(gcc) = popad(nasm)
// "popl %%edi\n"
// "popl %%esi\n"
// "popl %%ebp\n"
// "addl $4, %%esp\n" // 跳过 esp 寄存器本身的恢复
// "popl %%ebx\n"
// "popl %%edx\n"
// "popl %%ecx\n"
// "popl %%eax\n"
"iret\n"
:
: "r"(reg_base) // %0 替换成 reg_base
:
);
}
#include <print.h>
static void TaskEntry(void)
{
if(current_task)
{
current_task->task_entry();
}
printk("%s end!!!\n", current_task->name); // 调试
// 任务销毁工作
while(1);
}
/******************************************************************************
* 函数名称: E_RET TaskCreat(TASK* task, TASK_FUNC pFunc, U08 stackAddr, U16 stackSize, U08* name)
* 功能说明: 创建任务
* 输入参数: TASK_FUNC pFunc --任务函数
U08* stackAddr --任务栈基址
U16 stackSize --任务栈大小
U08* name --任务名称
* 输出参数: TASK* task --任务指针
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET TaskCreat(TASK* task, TASK_FUNC pFunc, U08* stackAddr, U16 stackSize, U08* name)
{
// 检查参数合法性
if(NULL == task || NULL == pFunc || NULL == stackAddr || 0 == stackSize)
return E_ERR;
task->name = name;
task->stack_addr = stackAddr;
task->stack_size = stackSize;
task->reg.cs = LDT_CODE32_SEL;
task->reg.gs = LDT_VIDEO_SEL;
task->reg.ds = LDT_DATA32_SEL;
task->reg.es = LDT_DATA32_SEL;
task->reg.fs = LDT_DATA32_SEL;
task->reg.ss = LDT_DATA32_SEL;
task->reg.esp = (U32)task->stack_addr + task->stack_size; // 栈顶
task->reg.eip = (U32)TaskEntry;
task->reg.eflags = 0x3202; // IOPL=3: 允许任务(特权级 3)进行 /O 操作; IF=1: 允许外部中断
task->task_entry = pFunc;
return E_OK;
}
/******************************************************************************
* 函数名称: TaskStart(TASK* task)
* 功能说明: 启动第一个任务
* 输入参数: TASK* task0 --任务指针
* 输出参数: 无
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 想要启动所有任务,只要启动第一个任务就可以了,其它任务将由任务调度启动
******************************************************************************/
E_RET TaskStart(TASK* task0)
{
// 检查参数合法性
if(NULL == task0)
return E_ERR;
current_task = task0; // 当前任务指针指向 task0
TSS* tss = (TSS*)(*(U32*)TSS_ENTRY_ADDR); // 找到 TSS
tss->esp0 = (U32)(&task0->reg) + sizeof(task0->reg); // TSS.esp0 指向 task0 的上下文数据结构 reg 的末尾
current_reg = (U32)&task0->reg; // current_reg 指向任务上下文数据结构 reg 的起始位置
enable_int0x20(); // 取消屏蔽 0x20 号时钟中断
asm volatile("sti"); // 开中断
SWITCH_TO(task0); // 切换到 TASK A 执行
return E_OK;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。