실행할 준비가 되어있는 태스크들을 관리하기 위해, OSRdyGrp와 OSRdyTbl[] 변수로 구성된 준비 리스트에 해당 우선순위의 태스크가 준비상태임을 표시해 둔다. 태스크 우선순위에 대해 8개의 우선순위를 그룹화하여 그룹당 OSRdyGrp의 1비트씩 대응시킨다. 즉 OSRdyGrp에서 각 비트는 해당 우선순위 그룹 내에 하나 이상의 실행 가능한 태스크의 존재 여부를 나타낸다. 태스크가 준비상태가 될 때, 준비 테이블(OSRdyTbl[])의 해당 비트 또한 기록해 둔다.
OSRdyTbl[]의 크기는 OS_LOWEST_PRIO 값에 따라 달라진다. 이런 특징 때문에 응용프로그램에서 사용하는 우선순위 개수가 적을수록 uC/OS-II에 필요한 메모리는 절약된다. uC/OS-II의 스케줄러는 다음 번으로 실행할 태스크를 결정할 때 OSRdyTbl[] 에서 가장 작은 우선순위 값에 해당하는 비트를 찾아내야 한다.
아래 코드는 태스크를 준비 리스트에 삽입하는 부분이다. 여기서 prio는 태스크 우선순위이다.
(태스크를 준비 상태로 만든다.)
OSRdyGrp = OSMapTbl [prio >> 3];
OSRdyTbl [prio >> 3] = OSMapTbl [prio & 0x07];
우선순위 값의 하위 3비트(bit2-bit0)는 OSRdyTbl[]의 항목에 대해 검사해야 할 비트위치를 나타내고, 다음 3비트(bit5-bit3)는 OSRdyTbl[]에서 항목 선택을 위한 인덱스 값으로 사용한다.
태스크는 삽입과정을 거꾸로 수행하여 준비 리스트로부터 삭제된다.
(준비 리스트에서 태스크 삭제)
if ((OSRdyTbl [prio >> 3] &= ~OSMapTbl [prio & 0x07]) == 0)
OSRdyGrp &= ~OSMapTbl [prio >> 3];
이 코드에서는 OSRdyTbl[] 배열에서 삭제하고자 하는 태스크의 우선순위에 해당하는 비트를 0으로 만든다. 이 과정에서 같은 우선순위 그룹 내에 준비상태의 태스크가 하나도 존재하지 않는 상태가 되면 OSRdyGrp의 우선순위 그룹 비트도 0으로 만든다.
준비 리스트에서 가장 우선순위가 높은 태스크를 찾기 위해 OSRdyTbl[0]에서 차례로 검색해 나가는 방법 대신 특별한 방법을 사용한다. 이때 사용하는 배열이 OSUnMapTbl[256]이다. OSRdyTbl[] 배열의 내용인 8비트 값은 실행 가능한 태스크의 우선순위와 1:1로 대응, 해당 우선순위의 태스크가 실행 가능한지 여부를 나타낸다. 0번 비트가 가장 높은 우선순위이다. 이렇게 실행 가능한 우선순위 상태를 나타내는 8비트 값을 그대로 인덱스 값으로 삼아 OSUnMapTbl[] 배열 값을 읽으면, 상황별로 실행 가능한 가장 높은 우선순위 비트 값을 0에서 7사이의 값으로 돌려준다. 이 과정은 아래와 같이 수행된다.
(준비 리스트에서 최상위 태스크 찾기)
y = OSUnMapTbl [OSRdyGrp]; /* OSRdyTbl[]에서 Y 위치를 결정한다. */
x = OSUnMapTbl [OSRdyTbl[y]]; /* OSRdyTbl[Y]에서 X 위치를 결정한다. */
prio = (y <<>
아래 그림과 같이 OSRdyGrp 값이 01101000(2진수) 이면 OSUnMapTbl [OSRdyGrp] 값은 3이 된다. 즉 OSRdyGrp의 3번 비트가 설정돼 있으므로 3번 비트에 대응한 우선순위 그룹이 실행 가능한 가장 높은 우선순위 그룹임을 의미한다. 참고로 이 경우 8비트 값의 가장 오른쪽 비트가 0번 비트이다. 그리고 OSRdyTbl[3]의 값이 11100100(2진수) 라면 OSUnMapTbl[OSRdyTbl[3]] 값은 2가 된다. (2번 비트를 의미) 결과적으로 준비 리스트 내의 가장 높은 우선순위 태스크는 우선순위 값 26(3 * 8 + 2)을 갖고 있음을 알 수 있다. 이제 해당 태스크 컨트롤 블록의 주소는 우선순위 값을 OSTCBPrioTbl[] 배열의 인덱스로 참조해서 얻을 수 있다.
참조> uC/OS-II 실시간 커널...
댓글 없음:
댓글 쓰기