이제는 스케줄링을 담당하는 소스를 살펴 보겠다.
우선 내가 만든 프로그램에서 스케줄링을 담당하는 큐는 대략
WAIT 와 SUSPEND 그리고 FREE 큐로 나누어 질 수 있다.
WAIT은 실행 가능하지만 멈춰 진 태스크를 위한 큐
SUSPEND는 인터럽트를 대기하던가? 아님 뭔가를 기다리기 위해 실행이 중지된 상태? 자원이겠찌?
그리고 FREE 큐는 메모리상에 존재하지만 죽은 태스크를 담아 놓은 큐.....쯔쯔쯔 불쌍도 해라.
음..이렇게 나누어지고 WAIT큐의 0번째 태스크가 지금 실행 중인 태스크를 지칭한다.
음..여하튼 이렇게 말했으니 그럼 소스를 설명해 볼까?
~cpp
#if !defined(LIB_SCHE_CPP)
#define LIB_SCHE_CPP
/* Init The Scheduler List
*/
이 함수는 스케쥴링을 위한 준비 과정 TCB들을 다 초기화 해 준다.. 겁이 많아서 그냥 다 초기화 해줬다.
그리고 나서 지금의 가장 높은 태스크를 스타트 TCB로 지칭해 준다.초기화 끝
~cpp
void LIB_Init_Schedu(){
for (int count = 0;count<LIB_MAX_HEAP;count++) {
pSuspend_heap[count] = NULL;
pReady_heap[count] = NULL;
pFreeTCB[count] = &TCB[count];
TCB[count].priority = NULL;
TCB[count].StackSeg = NULL;
TCB[count].StackOff = NULL;
TCB[count].NextEvent = NULL;
}
LIB_INT_COUNT = 0;
High_Task = &START_TCB;
ready_tcb_ptr = 0;
suspend_tcb_ptr = 0;
free_tcb_ptr = LIB_MAX_HEAP;
}
여기서는 FREE 큐중에서 쓸 수 있는 큐가 있나 알아본다?? 이건 왜 했찌???
~cpp
/* Get Free TCB
*/
LIB_TCB* LIB_free_TCB() {
LIB_TCB *Temp;
free_tcb_ptr--;
Temp = pFreeTCB[free_tcb_ptr];
pFreeTCB[free_tcb_ptr] = NULL;
return Temp;
}
여기서는 MAIN에서 본 듯 태스크를 만들어 주는 함수
~cpp
/* Create The Task
*/
void LIB_create_task (char *task_name,int priority,void (*task)(void),INT16U * Stack)
{
// Init The Stack
LIB_STACK_INIT(task,Stack); <-------- 스택을 초기화 해준다.....
if ( priority < LIB_MIN_PRIORITY || priority > LIB_MAX_PRIORITY ) return; <--------- 우선순위가 지랄 같으면 그냥 끝낸다.
// Insert Prio Queue;
pReady_heap[ready_tcb_ptr] = LIB_free_TCB();
// Init the TCB by argument <----- 함수에서 얻은 변수들로... 초기화...ok???
pReady_heap[ready_tcb_ptr]->Task_Name = task_name;
pReady_heap[ready_tcb_ptr]->delay = 0;
pReady_heap[ready_tcb_ptr]->priority = priority;
pReady_heap[ready_tcb_ptr]->StackSeg = (INT16U)FP_SEG(Stack);
pReady_heap[ready_tcb_ptr]->StackOff = INT16U(Stack) - 28;
pReady_heap[ready_tcb_ptr]->Stack = Stack;
/// 여기서 부터는 우선순위 큐를 쓴다.... 열라 간단했는 데...
<----- 사실상 우선순위 큐가 몇백번 돈 뒤에도 그 큐의 상태를 유지하는 것이 좀 어려웠다..
쉽게 말해 손으로 태스팅 할 때 큐에 태스크를 넣었다 빼면 되는 거 같지만 컴퓨터가 컨텍스트 스위칭을 위해
몇백번 큐에 넣었다 뺐따 할때는 크크 갑자기 뻗는 상황이 재현....
------->
int temp_count = ready_tcb_ptr;
LIB_TCB *Temp_TCB;
ready_tcb_ptr++;
while (1) {
if ( pReady_heap[temp_count]->priority > pReady_heap[tree_parent(temp_count)]->priority ){
Temp_TCB = pReady_heap[temp_count];
pReady_heap[temp_count] = pReady_heap[tree_parent(temp_count)];
pReady_heap[tree_parent(temp_count)] = Temp_TCB;
temp_count = tree_parent(temp_count);
}
else {
break;
}
}
}
SUSPEND 된 TASK 들을 다시 살려주는 고마운 펑션
~cpp
/* Resume task
*/
void LIB_resume_task(INT16U priority ){
if ( priority == 0 ) return;
LIB_ENTER_CRITICAL();
int temp;
for ( int i = 0; i<= suspend_tcb_ptr ; i++ ) {
if ( pSuspend_heap[i]->priority == priority ) {
pReady_heap[ready_tcb_ptr] = pSuspend_heap[i];
pSuspend_heap[i] = pSuspend_heap[suspend_tcb_ptr];
pSuspend_heap[suspend_tcb_ptr] = NULL;
suspend_tcb_ptr--;
temp = ready_tcb_ptr;
goto EX_LOOP1;
}
}
LIB_VRAM_STRING(0,15,"CAUTION !!!",0x07);
return;
EX_LOOP1:
LIB_TCB *temp_tcb;
while (1) {
if ( pReady_heap[temp]->priority > pReady_heap[tree_parent(temp)]->priority ) {
temp_tcb = pReady_heap[tree_parent(temp)];
pReady_heap[tree_parent(temp)] = pReady_heap[temp];
pReady_heap[temp] = temp_tcb;
temp = tree_parent(temp);
}
else break;
}
ready_tcb_ptr++;
LIB_EXIT_CRITICAL();
LIB_context_sw();
}
/// 태스크 서스팬드 하기......넌 이제 좀 쉬어라...
SUSPEND 큐에 넣어주고
WAIT 큐에서 빼준다...... 쯔쯔쯔
~cpp
/* Wait task
*/
void LIB_suspend_task(INT16U priority){
LIB_ENTER_CRITICAL();
int temp;
for(int i = 0 ; i <= ready_tcb_ptr ; i++ ) {
if ( pReady_heap[i]->priority == priority ){
// ready -> suspend
pSuspend_heap[++suspend_tcb_ptr] = pReady_heap[i];
// ready queue sort
pReady_heap[i] = pReady_heap[ready_tcb_ptr-1];
pReady_heap[ready_tcb_ptr-1] = NULL;
temp = i;
ready_tcb_ptr--;
goto EX_LOOP;
}
}
LIB_VRAM_STRING(0,15,"CAUTION !!!",0x07);
return;
EX_LOOP:
LIB_TCB *temp_tcb;
while (1) {
if ( pReady_heap[tree_left(temp)]->priority > pReady_heap[temp]->priority ) {
temp_tcb = pReady_heap[tree_left(temp)];
pReady_heap[tree_left(temp)] = pReady_heap[temp];
pReady_heap[temp] = temp_tcb;
temp = tree_left(temp);
}
else if ( pReady_heap[tree_right(temp)]->priority > pReady_heap[temp]->priority ) {
temp_tcb = pReady_heap[tree_right(temp)];
pReady_heap[tree_right(temp)] = pReady_heap[temp];
pReady_heap[temp] = temp_tcb;
temp = tree_right(temp);
}
else break;
}
LIB_EXIT_CRITICAL();
LIB_context_sw();
}
죽은 태스크들은 FREE큐로 가거라...왜냐 죽었잖아...
실행을 중지시키기 위해서는 FREE큐에 태스크를 넣어준다.....
~cpp
/* Delete the Task
*/
int LIB_del_task(LIB_TCB *task){
int temp_count;
LIB_TCB *Temp_TCB;
for ( int i = 0; i < LIB_MAX_HEAP ; i++ ){
if ( pReady_heap[i] == task ) {
free_tcb_ptr++;
pFreeTCB[free_tcb_ptr] = pReady_heap[i];
pReady_heap[i] = pReady_heap[ready_tcb_ptr];
pReady_heap[ready_tcb_ptr] = NULL;
temp_count = i;
ready_tcb_ptr--;
while (1) {
if ( pReady_heap[tree_left(temp_count)] != NULL) {
if ( pReady_heap[tree_left(temp_count)]->priority > pReady_heap[temp_count]->priority ){
Temp_TCB = pReady_heap[temp_count];
pReady_heap[temp_count] = pReady_heap[tree_left(temp_count)];
pReady_heap[tree_left(temp_count)] = Temp_TCB;
temp_count = tree_left(temp_count);
}
else break;
}
else break;
}
}
if ( pSuspend_heap[i] == task) {
free_tcb_ptr++;
pFreeTCB[free_tcb_ptr] = pSuspend_heap[i];
pSuspend_heap[i] = pSuspend_heap[suspend_tcb_ptr];
pSuspend_heap[suspend_tcb_ptr] = NULL;
suspend_tcb_ptr--;
return success;
}
}
LIB_Schedul();
return fail;
}
/* Resume task
*/
void LIB_resume_list(INT16U priority ){
int temp;
for ( int i = 0; i<= suspend_tcb_ptr ; i++ ) {
if ( pSuspend_heap[i]->priority == priority ) {
pReady_heap[ready_tcb_ptr] = pSuspend_heap[i];
pSuspend_heap[i] = pSuspend_heap[suspend_tcb_ptr];
pSuspend_heap[suspend_tcb_ptr] = NULL;
suspend_tcb_ptr--;
temp = ready_tcb_ptr;
goto EX_LOOP1;
}
}
return;
EX_LOOP1:
LIB_TCB *temp_tcb;
while (1) {
if ( pReady_heap[temp]->priority > pReady_heap[tree_parent(temp)]->priority ) {
temp_tcb = pReady_heap[tree_parent(temp)];
pReady_heap[tree_parent(temp)] = pReady_heap[temp];
pReady_heap[temp] = temp_tcb;
}
else break;
}
ready_tcb_ptr++;
}
가장 우선순위가 높은 걸 찾아준다...
~cpp
/* Find Ready Task & Run the Task
*/
void LIB_Schedul()
{
High_Task = pReady_heap[0];
}
#endif LIB_SCHE_CPP
음..내가 교수도 아니고 스케쥴링이 오에스에서 가장 중요할 것이다.. 그럼에도 불구하고 허접하다.
사실 내가 만든 것과 U_C_OS 와의 실행 속도 차이는 무지하게 크다. 이유는 소스를 보면 알 것이다..
여하튼..하지만..그래도 내 소스가 더 보기 쉽지 않나?? ㅋㅋㅋㅋㅋ
실행속도가 차이는 나지만 그래도 나름대로의 방식으로 만들려고 노력했다..그래서
이모양 이꼴인 오에스가 되었지만............