コード例 #1
0
ファイル: Task.c プロジェクト: SanguineGITHUB/source
/**
 *  다른 태스크를 찾아서 전환
 *      인터럽트나 예외가 발생했을 때 호출하면 안됨
 */
void kSchedule( void )
{
    TCB* pstRunningTask, * pstNextTask;
    BOOL bPreviousFlag;
    
    // 전환할 태스크가 있어야 함
    if( kGetReadyTaskCount() < 1 )
    {
        return ;
    }
    
    // 전환하는 도중 인터럽트가 발생하여 태스크 전환이 또 일어나면 곤란하므로 전환하는 
    // 동안 인터럽트가 발생하지 못하도록 설정
    // 임계 영역 시작
    bPreviousFlag = kLockForSystemData();
    
    // 실행할 다음 태스크를 얻음
    pstNextTask = kGetNextTaskToRun();
    if( pstNextTask == NULL )
    {
        // 임계 영역 끝
        kUnlockForSystemData( bPreviousFlag );
        return ;
    }
    
    // 현재 수행중인 태스크의 정보를 수정한 뒤 콘텍스트 전환
    pstRunningTask = gs_stScheduler.pstRunningTask; 
    gs_stScheduler.pstRunningTask = pstNextTask;
    
    // 유휴 태스크에서 전환되었다면 사용한 프로세서 시간을 증가시킴
    if( ( pstRunningTask->qwFlags & TASK_FLAGS_IDLE ) == TASK_FLAGS_IDLE )
    {
        gs_stScheduler.qwSpendProcessorTimeInIdleTask += 
            TASK_PROCESSORTIME - gs_stScheduler.iProcessorTime;
    }
    
    // 태스크 종료 플래그가 설정된 경우 콘텍스트를 저장할 필요가 없으므로, 대기 리스트에
    // 삽입하고 콘텍스트 전환
    if( pstRunningTask->qwFlags & TASK_FLAGS_ENDTASK )
    {
        kAddListToTail( &( gs_stScheduler.stWaitList ), pstRunningTask );
        kSwitchContext( NULL, &( pstNextTask->stContext ) );
    }
    else
    {
        kAddTaskToReadyList( pstRunningTask );
        kSwitchContext( &( pstRunningTask->stContext ), &( pstNextTask->stContext ) );
    }

    // 프로세서 사용 시간을 업데이트
    gs_stScheduler.iProcessorTime = TASK_PROCESSORTIME;

    // 임계 영역 끝
    kUnlockForSystemData( bPreviousFlag );
}
コード例 #2
0
ファイル: consoleShell.c プロジェクト: xaliver/Karlinux
// Test for context switching
void kTestTask(void)
{
	int i = 0;

	while (1)
	{
		// Print message and wait for key input
		kPrintf("[%d] This message is from kTestTask. Press any key to switch " "kConsolShell!!\n", i++);
		kGetCh();

		// Context switching
		kSwitchContext(&(gs_vstTask[1].stContext), &(gs_vstTask[0].stContext));
	}
}
コード例 #3
0
ファイル: ConsoleShell.c プロジェクト: SanguineGITHUB/source
/**
 *  태스크 전환을 테스트하는 태스크
 */
void kTestTask( void )
{
    int i = 0;
    
    while( 1 )
    {
        // 메시지를 출력하고 키 입력을 대기
        kPrintf( "[%d] This message is from kTestTask. Press any key to switch "
                 "kConsoleShell~!!\n", i++ );
        kGetCh();
        
        // 위에서 키가 입력되면 태스크를 전환
        kSwitchContext( &( gs_vstTask[ 1 ].stContext ), &( gs_vstTask[ 0 ].stContext ) );
    }
}
コード例 #4
0
ファイル: ConsoleShell.c プロジェクト: SanguineGITHUB/source
/**
 *  태스크를 생성해서 멀티 태스킹 수행
 */
void kCreateTestTask( const char* pcParameterBuffer )
{
    KEYDATA stData;
    int i = 0;
    
    // 태스크 설정
    kSetUpTask( &( gs_vstTask[ 1 ] ), 1, 0, ( QWORD ) kTestTask, &( gs_vstStack ), 
                sizeof( gs_vstStack ) );
    
    // 'q' 키가 입력되지 않을 때까지 수행
    while( 1 )
    {
        // 메시지를 출력하고 키 입력을 대기
        kPrintf( "[%d] This message is from kConsoleShell. Press any key to "
                 "switch TestTask~!!\n", i++ );
        if( kGetCh() == 'q' )
        {
            break;
        }
        // 위에서 키가 입력되면 태스크를 전환
        kSwitchContext( &( gs_vstTask[ 0 ].stContext ), &( gs_vstTask[ 1 ].stContext ) );
    }
}
コード例 #5
0
ファイル: Task.c プロジェクト: SanguineGITHUB/source
/**
 *  다른 태스크를 찾아서 전환
 *      인터럽트나 예외가 발생했을 때 호출하면 안됨
 *      단, 인터럽트나 예외에서 태스크를 종료하는 경우는 사용 가능
 */
BOOL kSchedule( void )
{
    TCB* pstRunningTask, * pstNextTask;
    BOOL bPreviousInterrupt;
    BYTE bCurrentAPICID;
    
    // 전환하는 도중 인터럽트가 발생하여 태스크 전환이 또 일어나면 곤란하므로 전환하는 
    // 동안 인터럽트가 발생하지 못하도록 설정
    bPreviousInterrupt = kSetInterruptFlag( FALSE );
    
    // 현재 로컬 APIC ID 확인
    bCurrentAPICID = kGetAPICID();
    
    // 전환할 태스크가 있어야 함
    if( kGetReadyTaskCount( bCurrentAPICID ) < 1 )
    {
        kSetInterruptFlag( bPreviousInterrupt );
        return FALSE;
    }
    
    // 임계 영역 시작
    kLockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );

    // 실행할 다음 태스크를 얻음
    pstNextTask = kGetNextTaskToRun( bCurrentAPICID );
    if( pstNextTask == NULL )
    {
        // 임계 영역 끝
        kUnlockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );
        kSetInterruptFlag( bPreviousInterrupt );
        return FALSE;
    }
    
    // 현재 수행중인 태스크의 정보를 수정한 뒤 콘텍스트 전환
    pstRunningTask = gs_vstScheduler[ bCurrentAPICID ].pstRunningTask; 
    gs_vstScheduler[ bCurrentAPICID ].pstRunningTask = pstNextTask;

    // 유휴 태스크에서 전환되었다면 사용한 프로세서 시간을 증가시킴
    if( ( pstRunningTask->qwFlags & TASK_FLAGS_IDLE ) == TASK_FLAGS_IDLE )
    {
        gs_vstScheduler[ bCurrentAPICID ].qwSpendProcessorTimeInIdleTask += 
            TASK_PROCESSORTIME - gs_vstScheduler[ bCurrentAPICID ].iProcessorTime;
    }

    // 다음에 수행할 태스크가 FPU를 쓴 태스크가 아니라면 TS 비트를 설정
    if( gs_vstScheduler[ bCurrentAPICID ].qwLastFPUUsedTaskID != 
        pstNextTask->stLink.qwID )
    {
        kSetTS();
    }
    else
    {
        kClearTS();
    }

    // 태스크 종료 플래그가 설정된 경우 콘텍스트를 저장할 필요가 없으므로, 대기 리스트에
    // 삽입하고 콘텍스트 전환
    if( pstRunningTask->qwFlags & TASK_FLAGS_ENDTASK )
    {
        kAddListToTail( &( gs_vstScheduler[ bCurrentAPICID ].stWaitList ), pstRunningTask );

        // 임계 영역 끝
        kUnlockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );

        // 태스크 전환
        kSwitchContext( NULL, &( pstNextTask->stContext ) );
    }
    else
    {
        kAddTaskToReadyList( bCurrentAPICID, pstRunningTask );
        
        // 임계 영역 끝
        kUnlockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );

        // 태스크 전환
        kSwitchContext( &( pstRunningTask->stContext ), &( pstNextTask->stContext ) );
    }

    // 프로세서 사용 시간을 업데이트
    gs_vstScheduler[ bCurrentAPICID ].iProcessorTime = TASK_PROCESSORTIME;
    
    // 인터럽트 플래그 복원
    kSetInterruptFlag( bPreviousInterrupt );
    return FALSE;
}