CH8에서는 태스크를 다룰 코드를 작성한다.
태스크란 쉽게 말하면 동작하고 있는(혹은 대기하고 있는) 프로그램을 의미한다.
멀티쓰레드/멀티프로세스 운영체제는 여러 태스크를 concurrent하게 실행할 수 있어야 하고 이것을 멀티태스킹이라고 부른다.
여러 태스크를 다루기 위해서는 태스크도 추상화하여 하나의 자료구조로서 다뤄야 하고 자료구조에는 태스크를 전환(switch)해도 이전 상태로 복구할 수 있을만한 데이터를 가지고 있어야 한다.
task.h
typedef struct KernelTaskContex_t{
uint32_t spsr;
uint32_t r0_r12[13];
uint32_t pc;
}KernelTaskContext_t;
typedef struct KernelTcb_t{
uint32_t sp;
uint8_t* stack_base;
}KernelTcb_t;
task.c
void Kernel_task_init(){
sAllocated_tcb_index = 0;
for(uint32_t i=0; i<MAX_TASK_NUM; i++){
sTask_list[i].stack_base = (uint8_t*)(TASK_STACK_START + i*USR_TASK_STACK_SIZE);
sTask_list[i].sp =(uint32_t)sTask_list[i].stack_base + USR_TASK_STACK_SIZE;
sTask_list[i].sp-=sizeof(KernelTaskContext_t);
KernelTaskContext_t* ctx = (KernelTaskContext_t*)sTask_list[i].sp;
ctx->pc= 0;
ctx->spsr = ARM_MODE_BIT_SYS;
}
}
task.c에서는 추상화한 태스크를 초기화하는 Kernel_task_init()함수를 정의한다.
추상화 된 태스크 구조체를 보면 알 수 있듯이, 태스크정보는 하나의 스택으로 정의된다. 스택을 할당 받고, 스택의 top에 레지스터 정보를 저장하면 해당 태스크의 switch을 위한 정보 저장은 끝이다.
uint32_t Kernel_task_create(KernelTaskFunc_t startFunc){
KernelTcb_t* new_tcb = &sTask_list[sAllocated_tcb_index++];
if (sAllocated_tcb_index>MAX_TASK_NUM)
return NOT_ENOUGH_TASK_NUM;
KernelTaskContext_t* ctx = (KernelTaskContext_t*)new_tcb->sp;
ctx->pc =(uint32_t)startFunc;
return (sAllocated_tcb_index-1);
}
task.c에서 정의된 다른 함수인 Kernel_task_create()이다.
추상화 된 태스크의 리스트를 초기화 한 후에 각 태크스가 할 일을 알려주는 함수이다. 현재 사용중이지 않은 태스크의 pc필드에 실행 할 함수의 주소를 저장하고 return으로 몇 개의 태스크를 사용중인지 알려준다.
다음 포스팅에서 계속..