2 Star 6 Fork 3

稀风/KOS

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
task7.c 7.69 KB
一键复制 编辑 原始数据 按行查看 历史
#include <task.h>
#include <desc.h>
#include <share.h>
#include <8259A.h>
volatile TASK* current_task = NULL; // 当前任务指针,永远指向当前任务
volatile U32 current_reg; // 当前任务的上下文起始位置
QUEUE TASK_FREE_QUEUE; // 空闲任务队列
QUEUE TASK_READY_QUEUE; // 就绪任务队列
QUEUE TASK_RUNNING_QUEUE; // 执行任务队列
QUEUE TASK_WAIT_QUEUE; // 等待任务队列
TASK_QUEUE_NODE taskIdleQueueNode; // 空闲任务队列节点
/******************************************************************************
* 函数名称: 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
:
);
}
/******************************************************************************
* 函数名称: static void TaskEntry(void)
* 功能说明: 任务入口
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
#include <print.h>
static void TaskEntry(void)
{
if(current_task)
{
current_task->task_entry();
}
printk("%s end!!!\n", current_task->name); // 调试
// 任务销毁工作
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)
* 功能说明: 创建任务
* 输入参数: 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;
}
/******************************************************************************
* 函数名称: static void TaskIdleFunc(void)
* 功能说明: 空闲任务
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
static TASK taskIdle = {0}; // 任务对象
#define IDLE_STACK_SIZE 512
static U08 taskIdle_stack[IDLE_STACK_SIZE]; // 任务私有栈
#include <print.h>
static void TaskIdleFunc(void) // 任务执行函数
{
static U32 count = 0;
while(1)
{
if(count++ % 100000 == 0)
{
static U32 j = 0;
asm volatile("cli");
SetCursorPos(0, 14);
printk("TASK Idle: %d\n", j++);
asm volatile("sti");
}
}
}
/******************************************************************************
* 函数名称: void TaskStart(void)
* 功能说明: 启动任务
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 想要启动所有任务,只要启动第一个任务就可以了,其它任务将由任务调度启动
******************************************************************************/
void TaskStart(void)
{
current_task = &taskIdle; // 当前任务指针指向空闲任务
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 号时钟中断
asm volatile("sti"); // 执行任务前必须开中断
SWITCH_TO(current_task); // 切换到空闲任务 taskIdle 执行
}
/******************************************************************************
* 函数名称: void TaskInit(void)
* 功能说明: 任务初始化
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
void TaskInit(void)
{
QueueInit(&TASK_FREE_QUEUE); // 空闲任务队列初始化
QueueInit(&TASK_READY_QUEUE); // 就绪任务队列初始化
QueueInit(&TASK_RUNNING_QUEUE); // 执行任务队列初始化
QueueInit(&TASK_WAIT_QUEUE); // 等待任务队列初始化
TaskCreat(&taskIdle, TaskIdleFunc, taskIdle_stack, IDLE_STACK_SIZE, "Idle"); // 创建第一个任务(空闲任务)
taskIdleQueueNode.task = &taskIdle;
QueueAdd(&TASK_RUNNING_QUEUE, (QUEUE_NODE *)&taskIdleQueueNode); // 将空闲任务节点添加到执行任务队列中
}
/******************************************************************************
* 函数名称: void TaskDestory(void)
* 功能说明: 销毁当前任务
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
E_RET TaskDestory(void)
{
QUEUE_NODE* node = NULL;
// 把当前任务节点从执行任务队列中取出,当前任务节点在队列尾
node = QueueTailRemove(&TASK_RUNNING_QUEUE);
if(NULL == node)
return E_ERR;
return E_OK;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/thin-wind/KOS.git
git@gitee.com:thin-wind/KOS.git
thin-wind
KOS
KOS
main

搜索帮助