2 Star 6 Fork 3

稀风/KOS

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
task14.c 8.89 KB
一键复制 编辑 原始数据 按行查看 历史
稀风 提交于 2023-02-14 20:40 . 内核数据安全:验证页异常中断
#include <task.h>
#include <desc.h>
#include <share.h>
#include <8259A.h>
#include <app.h>
volatile TASK* current_task = NULL; // 当前任务指针,永远指向当前任务
volatile U32 current_reg; // 当前任务的上下文起始位置
QUEUE TASK_READY_QUEUE; // 就绪任务队列
QUEUE TASK_WAIT_QUEUE; // 等待任务队列
static TASK_OOP taskOop[MAX_TASK_NUM] = {0}; // 普通任务对象数组
static TASK_OOP taskIdle = {0}; // 空闲任务对象
/******************************************************************************
* 函数名称: 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)
"addl $4, %%esp\n" // 跳过 err_code
"iret\n"
:
: "r"(reg_base) // %0 替换成 reg_base
:
);
}
/******************************************************************************
* 函数名称: static void TaskEntry(void)
* 功能说明: 任务入口
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
static void TaskEntry(void)
{
if(current_task)
{
current_task->task_entry();
}
// 任务销毁工作
asm volatile(
"movl $0, %%eax\n"
"int $0x80\n"
: : : "eax" // 告诉 gcc 编译器,eax 寄存器被内嵌汇编使用,需要 gcc 自动添加保护和恢复操作(入栈和出栈)
);
while(1);
}
/******************************************************************************
* 函数名称: E_RET TaskCreat(TASK* task, TASK_FUNC pFunc, U08* stackAddr, U16 stackSize, U08* name, E_TASK_PRI priority)
* 功能说明: 创建任务
* 输入参数: TASK_FUNC pFunc --任务函数
    U08* stackAddr --任务栈基址
    U16 stackSize --任务栈大小
    U08* name --任务名称
    E_TASK_PRI priority --任务优先级
* 输出参数: TASK* task --任务指针
* 函数返回: E_OK:成功; E_ERR:失败
* 其它说明: 无
******************************************************************************/
E_RET TaskCreat(TASK* task, TASK_FUNC pFunc, U08* stackAddr, U16 stackSize, U08* name, E_TASK_PRI priority)
{
// 检查参数合法性
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;
task->priority = priority;
task->total = 256 - priority;
current_task->current = 0;
return E_OK;
}
/******************************************************************************
* 函数名称: void TaskStart(void)
* 功能说明: 启动任务
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 想要启动所有任务,只要启动第一个任务就可以了,其它任务将由任务调度启动
******************************************************************************/
void TaskStart(void)
{
current_task = &taskIdle.task; // 当前任务指针指向空闲任务
TSS* tss = (TSS*)(*(U32*)TSS_ENTRY_ADDR); // 找到 TSS
tss->esp0 = (U32)&current_task->reg + sizeof(current_task->reg); // TSS.esp0 指向空闲任务 taskIdle 的上下文数据结构 reg 的末尾
current_reg = (U32)&current_task->reg; // current_reg 指向空闲任务 taskIdle 上下文数据结构 reg 的起始位置
enable_int0x20(); // 取消屏蔽 0x20 号时钟中断
// 寄存器 cr0 的 PG 位置 1,启动内存分页机制
asm volatile(
"movl %%cr0, %%eax\n"
"or $0x80000000, %%eax\n"
"movl %%eax, %%cr0\n"
:
:
: "eax"
);
asm volatile("sti"); // 执行任务前必须开中断
SWITCH_TO(current_task); // 切换到空闲任务 taskIdle 执行
}
/******************************************************************************
* 函数名称: void TaskInit(void)
* 功能说明: 任务初始化
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
void TaskInit(void)
{
U16 index = 0;
U16 taskNum = 0;
APP_INFO* pAppInfo = (APP_INFO *)(*(U32 *)APP_INFO_ADDR);
U32 appNum = *((U32*)(APP_NUM_ADDR));
U08* IdleTaskStackAddr = (U08 *)(*(U32 *)IDLE_TASK_STACK_ADDR);
U16 IdleTaskStackSize = (U16)(*((U32*)(IDLE_TASK_STACK_SIZE)));
TASK_FUNC pIdleTaskFunc = (TASK_FUNC)(*(U32 *)IDLE_TASK_FUNC_ADDR);
QueueInit(&TASK_READY_QUEUE); // 就绪任务队列初始化
QueueInit(&TASK_WAIT_QUEUE); // 等待任务队列初始化
// 创建第一个任务(空闲任务)
// TaskCreat(&taskIdle.task, TaskIdleFunc, taskIdle_stack, IDLE_STACK_SIZE, "Idle", E_TASK_PRI15);
TaskCreat(&taskIdle.task, pIdleTaskFunc, IdleTaskStackAddr, IdleTaskStackSize, "Idle", E_TASK_PRI15);
// 将空闲任务节点添加到就绪任务队列中
QueueAdd(&TASK_READY_QUEUE, (QUEUE_NODE *)&taskIdle);
for(index = 0; index < MAX_TASK_NUM && taskNum < appNum; index++)
{
if(0 == taskOop[index].active)
{
taskOop[index].active = 1;
taskOop[index].task.name = pAppInfo[taskNum].name;
taskOop[index].task.stack_addr = pAppInfo[taskNum].stackAddr;
taskOop[index].task.stack_size = pAppInfo[taskNum].stackSize;
taskOop[index].task.task_entry = pAppInfo[taskNum].pfunc;
taskOop[index].task.priority = pAppInfo[taskNum].priority;
TaskCreat(&taskOop[index].task, taskOop[index].task.task_entry, taskOop[index].task.stack_addr, taskOop[index].task.stack_size, taskOop[index].task.name, taskOop[index].task.priority);
QueueAdd(&TASK_READY_QUEUE, (QUEUE_NODE *)&taskOop[index]);
taskNum++;
}
}
}
/******************************************************************************
* 函数名称: void TaskDestory(void)
* 功能说明: 销毁当前任务
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
E_RET TaskDestory(void)
{
QUEUE_NODE* node = NULL;
// 把当前任务节点从就绪任务队列中取出,当前任务节点在队列尾
node = QueueTailRemove(&TASK_READY_QUEUE);
if(NULL == node)
return E_ERR;
((TASK_OOP *)QUEUE_NODE(node, TASK_OOP, QueueNode))->active = 0;
// 从就绪任务队列中取出一个任务节点并执行该任务,再将该任务节点重新添加到就绪任务队列中
node = QueueRemove(&TASK_READY_QUEUE);
current_task = (volatile TASK *)&(((TASK_OOP *)QUEUE_NODE(node, TASK_OOP, QueueNode))->task);
QueueAdd(&TASK_READY_QUEUE, node);
TSS* tss = (TSS*)(*(U32*)TSS_ENTRY_ADDR); // 找到 TSS
tss->esp0 = (U32)(&current_task->reg) + sizeof(current_task->reg); // TSS.esp0 指向任务上下文数据结构 reg 的末尾
current_reg = (U32)(&current_task->reg); // current_reg 指向任务上下文数据结构 reg 的起始位置
SWITCH_TO(current_task);
return E_OK;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/thin-wind/KOS.git
git@gitee.com:thin-wind/KOS.git
thin-wind
KOS
KOS
main

搜索帮助