/* * �|�X�g�^�X�N�t�b�N�̌Ăяo�� */ void call_posttaskhook(void) { callevel = TCL_PREPOST; set_ipl(ipl_maxisr2); unlock_cpu(); PostTaskHook(); lock_cpu(); set_ipl(IPL_ENA_ALL); callevel = TCL_TASK; }
//dispatch entry, entered by "swi" instruction //do preempt the current running task <knl_ctxtsk>, //and then do dispatch the high ready task <knl_schedtsk> interrupt 4 void knl_dispatch_entry(void) { #if(cfgOS_POST_TASK_HOOK == STD_ON) PostTaskHook(); #endif knl_dispatch_disabled=1; /* Dispatch disable */ //asm ldd knl_taskmode //asm pshd; /* save knl_taskmode */ asm ldaa tk_ppage asm psha /* save ppage */ asm ldx knl_ctxtsk; asm sts SP_OFFSET,x; /* save 'ssp' to TCB */ knl_ctxtsk->tskctxb.dispatcher = knl_dispatch_r; knl_ctxtsk=(void*)0; asm jmp l_dispatch0; }
/********************************************************************** * Force a scheduler action * * @return Status E_OK * In fact the function never return **********************************************************************/ StatusType Schedule(void) { SuspendOSInterrupts(); kernelState |= SERVICES; if (kernelState & ISR) // Service called from ISR return (E_OK); kernelState &= ~SERVICES; /* Never return... */ if (kernelState & USER) { #ifdef PRETASKHOOK PostTaskHook(); #endif SCHEDULE(); } return (E_OK); }
/* |------------------+--------------------------------------------------------------| */ StatusType TerminateTask ( void ) { StatusType ercd = E_NOT_OK; OS_CHECK_EXT(!in_indp(),E_OS_CALLEVEL); OS_CHECK_EXT(isQueEmpty(&knl_ctxtsk->resque),E_OS_RESOURCE); DISABLE_INTERRUPT; #if(cfgOS_POST_TASK_HOOK == STD_ON) PostTaskHook(); #endif knl_ctxtsk->state = TS_DORMANT; //release internal resource or for non-preemtable task ReleaseInternalResource(); knl_ctxtsk->priority = knl_ctxtsk->itskpri; knl_search_schedtsk(); #if((cfgOS_CONFORMANCE_CLASS == ECC2) || (cfgOS_CONFORMANCE_CLASS == BCC2)) if(knl_ctxtsk->actcnt > 0) { knl_ctxtsk->actcnt -= 1; #if(cfgOSEK_FIFO_QUEUE_PER_PRIORITY == STD_OFF) knl_make_active(knl_ctxtsk); #else knl_make_ready(knl_ctxtsk); #endif } #endif knl_force_dispatch(); /* No return */ Error_Exit: #if(cfgOS_ERROR_HOOK == STD_ON) if(E_OK != ercd) { BEGIN_CRITICAL_SECTION; _errorhook_svcid = OSServiceId_TerminateTask; CallErrorHook(ercd); END_CRITICAL_SECTION; } #endif /* cfgOS_ERROR_HOOK */ return ercd; }
extern StatusType Schedule ( void ) #endif { /* \req OSEK_SYS_3.4 The system service StatusType Schedule ( void ) shall ** be defined */ /* \req OSEK_SYS_3.4.4 Possible return values in Standard mode is E_OK */ StatusType ret = E_OK; TaskType nextTask; TaskType actualTask; #if (ERROR_CHECKING_TYPE == ERROR_CHECKING_EXTENDED) ContextType actualContext; #endif IntSecure_Start(); /* get actual running task */ actualTask = GetRunningTask(); /* \req OSEK_SYS_3.3.5 Extra possible return values in Extended mode are E_OS ** CALLEVEL, E_OS_RESOURCE */ #if (ERROR_CHECKING_TYPE == ERROR_CHECKING_EXTENDED) /* get actual context */ actualContext = GetCallingContext(); /* if called from scheduler no checks shall be performed */ if (FALSE == PerformChecks) { /* no checks shall be performed */ } else if ( ( CONTEXT_TASK != actualContext ) && ( CONTEXT_SYS != actualContext ) ) { /* \req OSEK_SYS_3.3.5 Extra possible return values in Extended mode ** are E_OS_CALLEVEL, E_OS_RESOURCE */ ret = E_OS_CALLEVEL; } else if ( ( INVALID_TASK != actualTask ) && ( CONTEXT_TASK == actualContext ) ) { if ( TasksVar[actualTask].Resources != 0 ) { /* \req OSEK_SYS_3.3.5 Extra possible return values in Extended mode ** are E_OS_CALLEVEL, E_OS_RESOURCE */ ret = E_OS_RESOURCE; } } else { /* nothing to check Runngin Task is invalid */ } if (ret == E_OK) #endif { /* get next task */ nextTask = GetNextTask(); /* while until one or boths are not more invalid tasks */ while ( ( actualTask == INVALID_TASK ) && ( nextTask == INVALID_TASK) ) { IntSecure_End(); /* macro used to indicate the processor that we are in idle time */ osekpause(); IntSecure_Start(); /* get next task */ nextTask = GetNextTask(); }; /* if the actual task is invalid */ if ( actualTask == INVALID_TASK ) { /* set task state to running */ TasksVar[nextTask].Flags.State = TASK_ST_RUNNING; /* set as running task */ SetRunningTask(nextTask); /* set actual context task */ SetActualContext(CONTEXT_TASK); IntSecure_End(); #if (HOOK_PRETASKHOOK == OSEK_ENABLE) PreTaskHook(); #endif /* #if (HOOK_PRETASKHOOK == OSEK_ENABLE) */ /* jmp tp the next task */ JmpTask(nextTask); } else { /* check priorities */ /* \req OSEK_SYS_3.4.1 If a task with a lower or equal priority than the ** ceiling priority of the internal resource and higher priority than ** the priority of the calling task is ready */ if ( TasksConst[nextTask].StaticPriority > TasksVar[actualTask].ActualPriority ) { #if (HOOK_POSTTASKHOOK == OSEK_ENABLE) PostTaskHook(); #endif /* #if (HOOK_POSTTASKHOOK == OSEK_ENABLE) */ /* \req OSEK_SYS_3.4.1.1 the internal resource of the task shall be ** released */ ReleaseInternalResources(); /* \req OSEK_SYS_3.4.1.2 the current task is put into the ready state */ TasksVar[actualTask].Flags.State = TASK_ST_READY; /* set the new task to running */ TasksVar[nextTask].Flags.State = TASK_ST_RUNNING; /* set as running task */ SetRunningTask(nextTask); /* set actual context task */ SetActualContext(CONTEXT_TASK); IntSecure_End(); #if (HOOK_PRETASKHOOK == OSEK_ENABLE) PreTaskHook(); #endif /* #if (HOOK_PRETASKHOOK == OSEK_ENABLE) */ /* \req OSEK_SYS_3.4.1.3 its context is saved */ /* \req OSEK_SYS_3.4.1.4 and the higher-priority task is executed */ CallTask(actualTask, nextTask); } else { IntSecure_End(); /* \req OSEK_SYS_3.4.2 Otherwise the calling task is continued */ } } } #if (ERROR_CHECKING_TYPE == ERROR_CHECKING_EXTENDED) else { IntSecure_End(); } #endif /* #if (ERROR_CHECKING_TYPE == ERROR_CHECKING_EXTENDED) */ #if (HOOK_ERRORHOOK == OSEK_ENABLE) /* \req OSEK_ERR_1.3-4/xx The ErrorHook hook routine shall be called if a ** system service returns a StatusType value not equal to E_OK.*/ /* \req OSEK_ERR_1.3.1-4/xx The hook routine ErrorHook is not called if a ** system service is called from the ErrorHook itself. */ if ( ( ret != E_OK ) && (ErrorHookRunning != 1)) { SetError_Api(OSServiceId_Schedule); SetError_Ret(ret); SetError_Msg("Schedule Task returns != than E_OK"); SetError_ErrorHook(); } #endif return ret; }
/* |------------------+-------------------------------------------------------------| */ StatusType ChainTask ( TaskType TaskID ) { StatusType ercd = E_NOT_OK; TCB * tcb; TSTAT state; OS_CHECK((TaskID<cfgOSEK_TASK_NUM),E_OS_ID); OS_CHECK_EXT(!in_indp(),E_OS_CALLEVEL); OS_CHECK_EXT(isQueEmpty(&knl_ctxtsk->resque),E_OS_RESOURCE); DISABLE_INTERRUPT; if(TaskID == knl_ctxtsk->tskid){ /* chain to itself */ knl_search_schedtsk(); knl_make_active(knl_ctxtsk); } else{ /* firstly terminate current running task knl_ctxtsk, * and then activate TaskID */ tcb = &knl_tcb_table[TaskID]; state = (TSTAT)tcb->state; if (TS_DORMANT != state) { #if((cfgOS_CONFORMANCE_CLASS == ECC2) || (cfgOS_CONFORMANCE_CLASS == BCC2)) if(tcb->actcnt < knl_gtsk_table[TaskID].maxact) { tcb->actcnt += 1; #if(cfgOSEK_FIFO_QUEUE_PER_PRIORITY == STD_ON) knl_ready_queue_insert(&knl_ready_queue, tcb); #endif } else #endif { ercd = E_OS_LIMIT; goto Error_Exit; } } #if(cfgOS_POST_TASK_HOOK == STD_ON) PostTaskHook(); #endif knl_ctxtsk->state = TS_DORMANT; knl_search_schedtsk(); #if((cfgOS_CONFORMANCE_CLASS == ECC2) || (cfgOS_CONFORMANCE_CLASS == BCC2)) if(knl_ctxtsk->actcnt > 0) { knl_ctxtsk->actcnt -= 1; #if(cfgOSEK_FIFO_QUEUE_PER_PRIORITY == STD_OFF) knl_make_active(knl_ctxtsk); #else knl_make_ready(knl_ctxtsk); #endif } #endif if (TS_DORMANT == state) { knl_make_active(tcb); } } knl_force_dispatch(); /* No return */ Error_Exit: ENABLE_INTERRUPT; #if(cfgOS_ERROR_HOOK == STD_ON) if(E_OK != ercd) { BEGIN_CRITICAL_SECTION; _errorhook_svcid = OSServiceId_ChainTask; _errorhook_par1.tskid = TaskID; CallErrorHook(ercd); END_CRITICAL_SECTION; } #endif /* cfgOS_ERROR_HOOK */ return ercd; }