這部分程式已經提交到gitHub上
故不將所有程式碼貼在網誌上瞜~~
task 共有四種狀態,分別是 ready, running, block(類似在休息, 記憶體不會被釋放), close
目前無法真正的將cpu使用權切換給其他task使用
只能修改各task的狀態
等下次將context switch實作之後才會有作用
這部分程式主要就是在這些狀態中切換
所以需要
list_t ready_list[MAX_PRIO];
list_t blocked_list;
list_t termination_list;
這三種list紀錄某種狀態下有哪些task
然後用
u32int task_table[MAX_TASK_NUM];
來放所有task, 有task設為1其餘為0 (所以這個os只能run MAX_TASK_NUM 個 task)
最後還有一個
u8int prioExistFlag[MAX_PRIO];
這是為了取出priority最高的 ready_list 所建的table (array)。
task 的結構如下
struct task{
node_t node;
void *sp;
void *entry;
void *parameter;
void *stack_addr;
u16int stack_size;
u8int priority;
u32int init_tick;
u32int remaining_tick;
u32int task_id;
TASK_STATE state;
char name[NAME_MAXLENTH];
timer_t *timer;
};
比較特別的是 void *sp (stack point)這指向 task 的 stack
void *entry 這指向這task要做的事情的function
void *stack_addr 就是指向stack的開頭摟
總共要實作的function有這些
task_t *task_create( const char *name,
void (*entry)(void *parameter),
void *parameter,
u16int stackSize,
u8int priority,
u16int tick);
s8int task_start( task_t *task );
s8int task_delete( task_t *task );
void task_yield();
s8int task_sleep( u32int tick );
s8int task_suspend( task_t *task );
s8int task_resume( task_t *task );
void task_remove( task_t *task );
void task_addReady( task_t *task );
task_t *ready_task( u8int priority );
u8int get_top_prio();
u32int get_task_id();
static void task_timeout(void *parameter);
在task_create裡
task_t *task_create( const char *name,
void (*entry)(void *parameter),
void *parameter,
u16int stackSize,
u8int priority,
u16int tick){
task_t *task;
u32int *stackAddr;
u32int task_id;
task_id = get_task_id();
if( task_id < 0 ){
return NULL;
}
task = (task_t *)kmalloc(sizeof(task_t));
if(task == NULL)
return NULL;
stackAddr = (void *)kmalloc(stackSize);
if( stackAddr == NULL ){
kfree(task);
return NULL;
}
for( int temp=0; temp<NAME_MAXLENTH; temp++ ){
task->name[temp] = name[temp];
}
task->task_id = task_id;
task->entry = (void *)entry;
task->parameter = parameter;
task->stack_addr = stackAddr;
task->stack_size = stackSize;
task->node.next = NULL;
task->node.prev = NULL;
task->init_tick = tick;
task->remaining_tick = tick;
task->priority = priority;
task->sp = (void *)( (void *)stackAddr + stackSize -4 );
memset( (u8int *)task->stack_addr, '?', task->stack_size );
task->sp = (void *)init_stack(task->sp,
task->entry,
task->parameter);
task_table[task->task_id] = 1;
task->timer = timer_create(task->name,
task_timeout,
task,
0,
SET_ONESHOT);
return task;
}
首先會取得task_id
就是從task_table裡取出value是0的key
之後就是初始化的動作
其中的init_stack在下次context switch時再一併講解
其餘工具的演算法或流程也不難
從一個狀態切換到下個狀態主要是
從原本的list裡移除(critical region)再加入另一個狀態的list中
詳細程式碼請至gitHub下載或線上參考~~
https://github.com/herb123456/DIY_Kernel
============================================
後來想想,還是直接在這寫下 init_stack 吧XD
init_stack在 stack.c 裡實作
是每個 task 專屬的一塊記憶體
裡面放的東西長這樣:
之後context switch 時 會將程式狀態存在這塊stack裡
詳細流程會在下一篇在講~~
讚
回覆刪除