示例#1
0
/**
 *  준비 큐에서 태스크를 제거
 */
static TCB* kRemoveTaskFromReadyList( BYTE bAPICID, QWORD qwTaskID )
{
    TCB* pstTarget;
    BYTE bPriority;
    
    // 태스크 ID가 유효하지 않으면 실패
    if( GETTCBOFFSET( qwTaskID ) >= TASK_MAXCOUNT )
    {
        return NULL;
    }
    
    // TCB 풀에서 해당 태스크의 TCB를 찾아 실제로 ID가 일치하는가 확인
    pstTarget = &( gs_stTCBPoolManager.pstStartAddress[ GETTCBOFFSET( qwTaskID ) ] );
    if( pstTarget->stLink.qwID != qwTaskID )
    {
        return NULL;
    }
    
    // 태스크가 존재하는 준비 리스트에서 태스크 제거
    bPriority = GETPRIORITY( pstTarget->qwFlags );
    if( bPriority >= TASK_MAXREADYLISTCOUNT )
    {
        return NULL;
    }    

    pstTarget = kRemoveList( &( gs_vstScheduler[ bAPICID ].vstReadyList[ bPriority ]), 
                     qwTaskID );
    return pstTarget;
}
示例#2
0
void* kRemoveListFromTail( LIST* pstList )
{
	LISTLINK* pstLink;

	if( pstList->iItemCount == 0 )
	{
		return NULL;
	}
	pstLink = (LISTLINK*)pstList->pvTail;
	return kRemoveList(pstList, pstLink->qwID);
}
示例#3
0
文件: kList.cpp 项目: pdpdds/OrangeOS
/**
 *  리스트의 첫 번째 데이터를 제거하여 반환
 */
void* kRemoveListFromHeader( LIST* pstList )
{
    LISTLINK* pstLink;
    
    if( pstList->iItemCount == 0 )
    {
        return NULL;
    }

    // 헤더를 제거하고, 반환
    pstLink = ( LISTLINK* ) pstList->pvHeader;
    return kRemoveList( pstList, pstLink->qwID );
}
示例#4
0
/**
 *  유휴 태스크
 *      대기 큐에 삭제 대기중인 태스크를 정리
 */
void kIdleTask( void )
{
    TCB* pstTask, * pstChildThread, * pstProcess;
    QWORD qwLastMeasureTickCount, qwLastSpendTickInIdleTask;
    QWORD qwCurrentMeasureTickCount, qwCurrentSpendTickInIdleTask;
    QWORD qwTaskID, qwChildThreadID;
    int i, iCount;
    void* pstThreadLink;
    BYTE bCurrentAPICID;
    BYTE bProcessAPICID;
    
    // 현재 코어의 로컬 APIC ID를 확인
    bCurrentAPICID = kGetAPICID();
    
    // 프로세서 사용량 계산을 위해 기준 정보를 저장
    qwLastSpendTickInIdleTask = 
        gs_vstScheduler[ bCurrentAPICID ].qwSpendProcessorTimeInIdleTask;
    qwLastMeasureTickCount = kGetTickCount();
    
    while( 1 )
    {
        // 현재 상태를 저장
        qwCurrentMeasureTickCount = kGetTickCount();
        qwCurrentSpendTickInIdleTask = 
            gs_vstScheduler[ bCurrentAPICID ].qwSpendProcessorTimeInIdleTask;
        
        // 프로세서 사용량을 계산
        // 100 - ( 유휴 태스크가 사용한 프로세서 시간 ) * 100 / ( 시스템 전체에서 
        // 사용한 프로세서 시간 )
        if( qwCurrentMeasureTickCount - qwLastMeasureTickCount == 0 )
        {
            gs_vstScheduler[ bCurrentAPICID ].qwProcessorLoad = 0;
        }
        else
        {
            gs_vstScheduler[ bCurrentAPICID ].qwProcessorLoad = 100 - 
                ( qwCurrentSpendTickInIdleTask - qwLastSpendTickInIdleTask ) * 
                100 /( qwCurrentMeasureTickCount - qwLastMeasureTickCount );
        }
        
        // 현재 상태를 이전 상태에 보관
        qwLastMeasureTickCount = qwCurrentMeasureTickCount;
        qwLastSpendTickInIdleTask = qwCurrentSpendTickInIdleTask;

        // 프로세서의 부하에 따라 쉬게 함
        kHaltProcessorByLoad( bCurrentAPICID );
        
        // 대기 큐에 대기중인 태스크가 있으면 태스크를 종료함
        if( kGetListCount( &( gs_vstScheduler[ bCurrentAPICID ].stWaitList ) ) 
                > 0 )
        {
            while( 1 )
            {
                // 임계 영역 시작
                kLockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );
                pstTask = kRemoveListFromHeader( 
                    &( gs_vstScheduler[ bCurrentAPICID ].stWaitList ) );
                // 임계 영역 끝
                kUnlockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );
                
                if( pstTask == NULL )
                {
                    break;
                }
                
                if( pstTask->qwFlags & TASK_FLAGS_PROCESS )
                {
                    // 프로세스를 종료할 때 자식 스레드가 존재하면 스레드를 모두 
                    // 종료하고, 다시 자식 스레드 리스트에 삽입
                    iCount = kGetListCount( &( pstTask->stChildThreadList ) );
                    for( i = 0 ; i < iCount ; i++ )
                    {
                        // 임계 영역 시작
                        kLockForSpinLock( 
                            &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );
                        // 스레드 링크의 어드레스에서 꺼내 스레드를 종료시킴
                        pstThreadLink = ( TCB* ) kRemoveListFromHeader( 
                                &( pstTask->stChildThreadList ) );
                        if( pstThreadLink == NULL )
                        {
                            // 임계 영역 끝
                            kUnlockForSpinLock( 
                                &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );
                            break;
                        }
                        
                        // 자식 스레드 리스트에 연결된 정보는 태스크 자료구조에 있는 
                        // stThreadLink의 시작 어드레스이므로, 태스크 자료구조의 시작
                        // 어드레스를 구하려면 별도의 계산이 필요함
                        pstChildThread = GETTCBFROMTHREADLINK( pstThreadLink );                        

                        // 다시 자식 스레드 리스트에 삽입하여 해당 스레드가 종료될 때
                        // 자식 스레드가 프로세스를 찾아 스스로 리스트에서 제거하도록 함
                        kAddListToTail( &( pstTask->stChildThreadList ),
                                &( pstChildThread->stThreadLink ) );
                        qwChildThreadID = pstChildThread->stLink.qwID;
                        // 임계 영역 끝
                        kUnlockForSpinLock( 
                            &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );
                        
                        // 자식 스레드를 찾아서 종료
                        kEndTask( qwChildThreadID );
                    }
                    
                    // 아직 자식 스레드가 남아있다면 자식 스레드가 다 종료될 때까지
                    // 기다려야 하므로 다시 대기 리스트에 삽입
                    if( kGetListCount( &( pstTask->stChildThreadList ) ) > 0 )
                    {
                        // 임계 영역 시작
                        kLockForSpinLock( 
                            &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );
                        kAddListToTail( 
                             &( gs_vstScheduler[ bCurrentAPICID ].stWaitList ), 
                             pstTask );
                        // 임계 영역 끝
                        kUnlockForSpinLock( 
                            &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );
                        continue;
                    }
                    // 프로세스를 종료해야 하므로 할당 받은 메모리 영역을 삭제
                    else
                    {
                        // 유저 레벨 프로세스라면 메모리를 할당 받았을 것이므로 할당
                        // 받은 메모리를 삭제
                        if( pstTask->qwFlags & TASK_FLAGS_USERLEVEL )
                        {
                            kFreeMemory( pstTask->pvMemoryAddress );
                        }
                    }
                }                
                else if( pstTask->qwFlags & TASK_FLAGS_THREAD )
                {
                    // 스레드라면 프로세스의 자식 스레드 리스트에서 제거
                    pstProcess = kGetProcessByThread( pstTask );
                    if( pstProcess != NULL )
                    {
                        // 프로세스 ID로 프로세스가 속한 스케줄러의 ID를 찾고 스핀락 잠금
                        if( kFindSchedulerOfTaskAndLock( pstProcess->stLink.qwID, 
                                &bProcessAPICID ) == TRUE )
                        {
                            kRemoveList( &( pstProcess->stChildThreadList ), 
                                         pstTask->stLink.qwID );
                            kUnlockForSpinLock( &( gs_vstScheduler[ 
                                bProcessAPICID ].stSpinLock ) );
                        }
                    }
                }
                
                // 여기까지 왔다면 태스크가 정상적으로 종료된 것이므로, 
                // 태스크 자료구조(TCB)와 스택을 반환
                qwTaskID = pstTask->stLink.qwID;

                // 스택을 반환
                kFreeMemory( pstTask->pvStackAddress );
                 
                // 태스크 자료구조(TCB)를 반환
                kFreeTCB( qwTaskID );                
                kPrintf( "IDLE: Task ID[0x%q] is completely ended.\n", 
                        qwTaskID );
            }
        }
        
        kSchedule();
    }
}
示例#5
0
/**
 *  유휴 태스크
 *      대기 큐에 삭제 대기중인 태스크를 정리
 */
void kIdleTask( void )
{
    TCB* pstTask, * pstChildThread, * pstProcess;
    QWORD qwLastMeasureTickCount, qwLastSpendTickInIdleTask;
    QWORD qwCurrentMeasureTickCount, qwCurrentSpendTickInIdleTask;
    int i, iCount;
    QWORD qwTaskID;
    void* pstThreadLink;
    
    // 프로세서 사용량 계산을 위해 기준 정보를 저장
    qwLastSpendTickInIdleTask = gs_stScheduler.qwSpendProcessorTimeInIdleTask;
    qwLastMeasureTickCount = kGetTickCount();
    
    while( 1 )
    {
        // 현재 상태를 저장
        qwCurrentMeasureTickCount = kGetTickCount();
        qwCurrentSpendTickInIdleTask = gs_stScheduler.qwSpendProcessorTimeInIdleTask;
        
        // 프로세서 사용량을 계산
        // 100 - ( 유휴 태스크가 사용한 프로세서 시간 ) * 100 / ( 시스템 전체에서 
        // 사용한 프로세서 시간 )
        if( qwCurrentMeasureTickCount - qwLastMeasureTickCount == 0 )
        {
            gs_stScheduler.qwProcessorLoad = 0;
        }
        else
        {
            gs_stScheduler.qwProcessorLoad = 100 - 
                ( qwCurrentSpendTickInIdleTask - qwLastSpendTickInIdleTask ) * 
                100 /( qwCurrentMeasureTickCount - qwLastMeasureTickCount );
        }
        
        // 현재 상태를 이전 상태에 보관
        qwLastMeasureTickCount = qwCurrentMeasureTickCount;
        qwLastSpendTickInIdleTask = qwCurrentSpendTickInIdleTask;

        // 프로세서의 부하에 따라 쉬게 함
        kHaltProcessorByLoad();
        
        // 대기 큐에 대기중인 태스크가 있으면 태스크를 종료함
        if( kGetListCount( &( gs_stScheduler.stWaitList ) ) >= 0 )
        {
            while( 1 )
            {
                // 임계 영역 시작
                kLockForSpinLock( &( gs_stScheduler.stSpinLock ) );
                pstTask = kRemoveListFromHeader( &( gs_stScheduler.stWaitList ) );
                if( pstTask == NULL )
                {
                    // 임계 영역 끝
                    kUnlockForSpinLock( &( gs_stScheduler.stSpinLock ) );
                    break;
                }
                
                if( pstTask->qwFlags & TASK_FLAGS_PROCESS )
                {
                    // 프로세스를 종료할 때 자식 스레드가 존재하면 스레드를 모두 
                    // 종료하고, 다시 자식 스레드 리스트에 삽입
                    iCount = kGetListCount( &( pstTask->stChildThreadList ) );
                    for( i = 0 ; i < iCount ; i++ )
                    {
                        // 스레드 링크의 어드레스에서 꺼내 스레드를 종료시킴
                        pstThreadLink = ( TCB* ) kRemoveListFromHeader( 
                                &( pstTask->stChildThreadList ) );
                        if( pstThreadLink == NULL )
                        {
                            break;
                        }
                        
                        // 자식 스레드 리스트에 연결된 정보는 태스크 자료구조에 있는 
                        // stThreadLink의 시작 어드레스이므로, 태스크 자료구조의 시작
                        // 어드레스를 구하려면 별도의 계산이 필요함
                        pstChildThread = GETTCBFROMTHREADLINK( pstThreadLink );

                        // 다시 자식 스레드 리스트에 삽입하여 해당 스레드가 종료될 때
                        // 자식 스레드가 프로세스를 찾아 스스로 리스트에서 제거하도록 함
                        kAddListToTail( &( pstTask->stChildThreadList ),
                                &( pstChildThread->stThreadLink ) );

                        // 자식 스레드를 찾아서 종료
                        kEndTask( pstChildThread->stLink.qwID );
                    }
                    
                    // 아직 자식 스레드가 남아있다면 자식 스레드가 다 종료될 때까지
                    // 기다려야 하므로 다시 대기 리스트에 삽입
                    if( kGetListCount( &( pstTask->stChildThreadList ) ) > 0 )
                    {
                        kAddListToTail( &( gs_stScheduler.stWaitList ), pstTask );

                        // 임계 영역 끝
                        kUnlockForSpinLock( &( gs_stScheduler.stSpinLock ) );
                        continue;
                    }
                    // 프로세스를 종료해야 하므로 할당 받은 메모리 영역을 삭제
                    else
                    {
                        // TODO: 추후에 코드 삽입
                    }
                }                
                else if( pstTask->qwFlags & TASK_FLAGS_THREAD )
                {
                    // 스레드라면 프로세스의 자식 스레드 리스트에서 제거
                    pstProcess = kGetProcessByThread( pstTask );
                    if( pstProcess != NULL )
                    {
                        kRemoveList( &( pstProcess->stChildThreadList ), pstTask->stLink.qwID );
                    }
                }
                
                qwTaskID = pstTask->stLink.qwID;
                kFreeTCB( qwTaskID );
                // 임계 영역 끝
                kUnlockForSpinLock( &( gs_stScheduler.stSpinLock ) );
                
                kPrintf( "IDLE: Task ID[0x%q] is completely ended.\n", 
                        qwTaskID );
            }
        }
        
        kSchedule();
    }
}