E D R , A S I H C RSS

LIB_3

이제는 스케줄링을 담당하는 소스를 살펴 보겠다.

우선 내가 만든 프로그램에서 스케줄링을 담당하는 큐는 대략
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 와의 실 속도 차이는 무지하게 크다. 이유는 소스를 보면 알 것이다..

여하튼..하지만..그래도 내 소스가 더 보기 쉽지 않나?? ㅋㅋㅋㅋㅋ

속도가 차이는 나지만 그래도 나름대로의 방식으로 만들려고 노력했다..그래서

이모양 이꼴인 오에스가 되었지만............


Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:23:37
Processing time 0.0117 sec