2 Star 6 Fork 3

稀风/KOS

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
task3.c 4.53 KB
一键复制 编辑 原始数据 按行查看 历史
#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;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/thin-wind/KOS.git
git@gitee.com:thin-wind/KOS.git
thin-wind
KOS
KOS
main

搜索帮助