/* |------------------+-----------------------------------------------------------| */ StatusType GetResource (ResourceType ResID) { StatusType ercd = E_OK; RESCB *rescb; PRI ceilpri,oldpri; OS_CHECK_EXT(!in_indp(),E_OS_CALLEVEL); //add as share resource with ISR was not supported OS_CHECK_EXT((ResID < cfgOSEK_RESOURCE_NUM),E_OS_ID); rescb = &knl_rescb_table[ResID]; OS_CHECK_EXT((isQueEmpty(&rescb->resque)),E_OS_ACCESS); oldpri = knl_ctxtsk->priority; ceilpri = knl_gres_table[ResID]; OS_CHECK_EXT((ceilpri <= knl_ctxtsk->itskpri),E_OS_ACCESS); BEGIN_DISABLE_INTERRUPT; if(ceilpri < oldpri) { knl_ctxtsk->priority = ceilpri; } rescb->tskpri = oldpri; QueInsert(&rescb->resque,&knl_ctxtsk->resque); END_DISABLE_INTERRUPT; Error_Exit: #if(cfgOS_ERROR_HOOK == STD_ON) if(E_OK != ercd) { BEGIN_CRITICAL_SECTION; _errorhook_svcid = OSServiceId_GetResource; _errorhook_par1.resid = ResID; CallErrorHook(ercd); END_CRITICAL_SECTION; } #endif /* cfgOS_ERROR_HOOK */ return ercd; }
StatusType SleepTask ( TickType Timeout ) { StatusType ercd = E_OK; OS_CHECK_EXT(!in_indp(),E_OS_CALLEVEL); OS_CHECK_EXT(isQueEmpty(&knl_ctxtsk->resque),E_OS_RESOURCE); BEGIN_CRITICAL_SECTION; if ( knl_ctxtsk->wupcnt > 0 ) { knl_ctxtsk->wupcnt--; } else { ercd = E_OS_TMOUT; if ( Timeout != 0 ) { knl_ctxtsk->wspec = &knl_wspec_slp; knl_ctxtsk->wid = 0; knl_ctxtsk->wercd = &ercd; knl_make_wait(Timeout); QueInit(&knl_ctxtsk->tskque); } } END_CRITICAL_SECTION; Error_Exit: return ercd; }
/* |------------------+------------------------------------------------------------| */ StatusType ReleaseResource ( ResourceType ResID ) { StatusType ercd = E_OK; RESCB *rescb; PRI ceilpri,oldpri; OS_CHECK_EXT(!in_indp(),E_OS_CALLEVEL); //add as share resource with ISR was not supported OS_CHECK_EXT((ResID < cfgOSEK_RESOURCE_NUM),E_OS_ID); rescb = &knl_rescb_table[ResID]; OS_CHECK_EXT((knl_ctxtsk->resque.prev == &rescb->resque),E_OS_NOFUNC); oldpri = rescb->tskpri; ceilpri = knl_gres_table[ResID]; OS_CHECK_EXT((ceilpri <= knl_ctxtsk->itskpri),E_OS_ACCESS); BEGIN_CRITICAL_SECTION; knl_ctxtsk->priority = oldpri; QueRemove(&rescb->resque); QueInit(&rescb->resque); if(oldpri > knl_ready_queue.top_priority) { knl_preempt(); } END_CRITICAL_SECTION; Error_Exit: #if(cfgOS_ERROR_HOOK == STD_ON) if(E_OK != ercd) { BEGIN_CRITICAL_SECTION; _errorhook_svcid = OSServiceId_ReleaseResource; _errorhook_par1.resid = ResID; CallErrorHook(ercd); END_CRITICAL_SECTION; } #endif /* cfgOS_ERROR_HOOK */ return ercd; }
/* |------------------+---------------------------------------------------------| */ StatusType ClearEvent ( EventMaskType Mask ) { StatusType ercd = E_OK; ID flgid; FLGCB *flgcb; OS_CHECK_EXT(!in_indp(),E_OS_CALLEVEL); flgid = knl_ctxtsk - knl_tcb_table; flgid = knl_gtsk_table[flgid].flgid; OS_CHECK_EXT((flgid != INVALID_EVENT),E_OS_ACCESS); flgcb = &knl_flgcb_table[flgid]; BEGIN_DISABLE_INTERRUPT; flgcb->flgptn &= ~Mask; END_DISABLE_INTERRUPT; Error_Exit: #if(cfgOS_ERROR_HOOK == STD_ON) if(E_OK != ercd) { BEGIN_CRITICAL_SECTION; _errorhook_svcid = OSServiceId_ClearEvent; _errorhook_par1.mask = Mask; CallErrorHook(ercd); END_CRITICAL_SECTION; } #endif /* cfgOS_ERROR_HOOK */ return ercd; }
/* * End and delete its own task */ SYSCALL void _tk_exd_tsk( void ) { /* Check context error */ #if CHK_CTX2 if ( in_indp() ) { #if USE_KERNEL_MESSAGE tm_putstring((UB*)"tk_exd_tsk was called in the task independent\n"); #endif tm_monitor(); /* To monitor */ } #endif #if CHK_CTX1 if ( in_ddsp() ) { #if USE_KERNEL_MESSAGE tm_putstring((UB*)"tk_exd_tsk was called in the dispatch disabled\n"); #endif } #endif DISABLE_INTERRUPT; _ter_tsk(ctxtsk); _del_tsk(ctxtsk); force_dispatch(); /* No return */ }
/* |------------------+-------------------------------------------------------------| */ StatusType Schedule ( void ) { StatusType ercd = E_OK; OS_CHECK_EXT(!in_indp(),E_OS_CALLEVEL); OS_CHECK_EXT(isQueEmpty(&knl_ctxtsk->resque),E_OS_RESOURCE); BEGIN_CRITICAL_SECTION; //if task has internal resource or task is non-premtable if(knl_ready_queue.top_priority <= knl_ctxtsk->itskpri) { //release internal resource or for Non-Preemtable Task knl_ctxtsk->priority = knl_ctxtsk->itskpri; knl_reschedule(); } END_CRITICAL_SECTION; //re-get internal resource or for Non-Preemtable task knl_ctxtsk->priority = knl_ctxtsk->runpri; Error_Exit: #if(cfgOS_ERROR_HOOK == STD_ON) if(E_OK != ercd) { BEGIN_CRITICAL_SECTION; _errorhook_svcid = OSServiceId_Schedule; CallErrorHook(ercd); END_CRITICAL_SECTION; } #endif /* cfgOS_ERROR_HOOK */ return ercd; }
/* * Branch routine to extended SVC handler */ EXPORT ER knl_svc_ientry P2GP( VP pk_para, FN fncd ) { ID ssid; SSYCB *ssycb; ER ercd; /* Lower 8 bits are subsystem ID */ ssid = fncd & 0xff; if ( ssid < MIN_SSYID || ssid > MAX_SSYID ) { return E_RSFN; } ssycb = get_ssycb(ssid); if ( in_indp() ) { /* Execute at task-independent part */ ercd = CallUserHandlerP2_GP(pk_para, fncd, ssycb->svchdr, ssycb); } else { DISABLE_INTERRUPT; knl_ctxtsk->sysmode++; ENABLE_INTERRUPT; /* Call extended SVC handler */ ercd = CallUserHandlerP2_GP(pk_para, fncd, ssycb->svchdr, ssycb); DISABLE_INTERRUPT; knl_ctxtsk->sysmode--; ENABLE_INTERRUPT; } return ercd; }
/* |------------------+-------------------------------------------------------------| */ 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; } else #endif { ercd = E_OS_LIMIT; goto Error_Exit; } } 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; knl_make_active(knl_ctxtsk); } #endif if (TS_DORMANT == state) { knl_make_active(tcb); } } knl_force_dispatch(); /* No return */ Error_Exit: return ercd; }
/* |------------------+------------------------------------------------------------| */ StatusType ReleaseResource ( ResourceType ResID ) { StatusType ercd = E_OK; RESCB *rescb; PRI newpri,oldpri; OS_CHECK_EXT((ResID < cfgOSEK_RESOURCE_NUM),E_OS_ID); rescb = &knl_rescb_table[ResID]; if(in_indp()) /* Interrupt level */ { /* not supported */ } else { OS_CHECK_EXT((knl_ctxtsk->resque.prev == &rescb->resque),E_OS_NOFUNC); oldpri = knl_gres_table[ResID]; newpri = rescb->tskpri; OS_CHECK_EXT((newpri > oldpri),E_OS_ACCESS); BEGIN_CRITICAL_SECTION; if(oldpri < 0) { /* Task share resource with ISR */ /* should change IPL */ /* not supported */ } else { knl_ctxtsk->priority = newpri; QueRemove(&rescb->resque); QueInit(&rescb->resque); if(newpri > knl_ready_queue.top_priority) { knl_preempt(); } } END_CRITICAL_SECTION; } Error_Exit: #if(cfgOS_ERROR_HOOK == STD_ON) if(E_OK != ercd) { BEGIN_CRITICAL_SECTION; _errorhook_svcid = OSServiceId_ReleaseResource; _errorhook_par1.resid = ResID; CallErrorHook(ercd); END_CRITICAL_SECTION; } #endif /* cfgOS_ERROR_HOOK */ return ercd; }
/* |------------------+-------------------------------------------------------------| */ StatusType Schedule ( void ) { StatusType ercd = E_NOT_OK; OS_CHECK_EXT(!in_indp(),E_OS_CALLEVEL); OS_CHECK_EXT(isQueEmpty(&knl_ctxtsk->resque),E_OS_RESOURCE); //As Internal Resource was not supported,So in fact this API only has effect on //Non-preemtable Task. BEGIN_CRITICAL_SECTION; knl_reschedule(); END_CRITICAL_SECTION; Error_Exit: return ercd; }
/* |------------------+-----------------------------------------------------------| */ StatusType GetResource (ResourceType ResID) { StatusType ercd = E_OK; RESCB *rescb; PRI newpri,oldpri; OS_CHECK_EXT((ResID < cfgOSEK_RESOURCE_NUM),E_OS_ID); rescb = &knl_rescb_table[ResID]; OS_CHECK_EXT((isQueEmpty(&rescb->resque)),E_OS_ACCESS); if(in_indp()) /* Interrupt level */ { /* not supported */ } else { oldpri = knl_ctxtsk->priority; newpri = knl_gres_table[ResID]; OS_CHECK_EXT((newpri < oldpri),E_OS_ACCESS); BEGIN_DISABLE_INTERRUPT; if(newpri < 0) { //TODO: share resourse with ISR /* Task share resource with ISR */ /* should change IPL */ /* not supported */ } else { knl_ctxtsk->priority = newpri; rescb->tskpri = oldpri; QueInsert(&rescb->resque,&knl_ctxtsk->resque); } END_DISABLE_INTERRUPT; } Error_Exit: #if(cfgOS_ERROR_HOOK == STD_ON) if(E_OK != ercd) { BEGIN_CRITICAL_SECTION; _errorhook_svcid = OSServiceId_GetResource; _errorhook_par1.resid = ResID; CallErrorHook(ercd); END_CRITICAL_SECTION; } #endif /* cfgOS_ERROR_HOOK */ return ercd; }
/* * Rotate ready queue */ SYSCALL ER _tk_rot_rdq( PRI tskpri ) { CHECK_PRI_RUN(tskpri); BEGIN_CRITICAL_SECTION; if ( tskpri == TPRI_RUN ) { if ( in_indp() ) { rotate_ready_queue_run(); } else { rotate_ready_queue(ctxtsk->priority); } } else { rotate_ready_queue(int_priority(tskpri)); } END_CRITICAL_SECTION; return E_OK; }
/* |------------------+-------------------------------------------------------------| */ StatusType ChainTask ( TaskType xTaskID ) { StatusType ercd; #ifdef DORMANT_STACK_SIZE /* To avoid destroying stack used in 'knl_make_dormant', allocate the dummy area on the stack. */ volatile VB _dummy[DORMANT_STACK_SIZE]; #endif /* Check context error */ #if CHK_CTX2 if ( in_indp() ) { #if USE_KERNEL_MESSAGE tm_putstring((UB*)"ChainTask was called in the task independent\n"); #endif tm_monitor(); /* To monitor */ } #endif #if CHK_CTX1 if ( in_ddsp() ) { #if USE_KERNEL_MESSAGE tm_putstring((UB*)"ChainTask was called in the dispatch disabled\n"); #endif } #endif DISABLE_INTERRUPT; ercd = tk_sta_tsk(xTaskID,xTaskID); if(ercd < E_OK) { ENABLE_INTERRUPT; return ercd; } knl_ter_tsk(knl_ctxtsk); knl_make_dormant(knl_ctxtsk); OsekStartHighReadyTask(); /* No return */ #ifdef DORMANT_STACK_SIZE /* for WARNING */ _dummy[0] = 0; #endif }
/* |------------------+--------------------------------------------------------------| */ 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; }
/* * Refer system state */ SYSCALL ER tk_ref_sys_impl( T_RSYS *pk_rsys ) { if ( in_indp() ) { pk_rsys->sysstat = TSS_INDP; } else { if ( in_qtsk() ) { pk_rsys->sysstat = TSS_QTSK; } else { pk_rsys->sysstat = TSS_TSK; } if ( in_loc() ) { pk_rsys->sysstat |= TSS_DINT; } if ( in_ddsp() ) { pk_rsys->sysstat |= TSS_DDSP; } } pk_rsys->runtskid = ( knl_ctxtsk != NULL )? knl_ctxtsk->tskid: 0; pk_rsys->schedtskid = ( knl_schedtsk != NULL )? knl_schedtsk->tskid: 0; 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; 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; knl_make_active(knl_ctxtsk); } #endif knl_force_dispatch(); /* No return */ Error_Exit: return ercd; }
/* * End its own task */ SYSCALL void _tk_ext_tsk( void ) { #ifdef DORMANT_STACK_SIZE /* To avoid destroying stack used in 'make_dormant', allocate the dummy area on the stack. */ volatile VB _dummy[DORMANT_STACK_SIZE]; MEMSET((void *)_dummy, 0xCC, DORMANT_STACK_SIZE); #endif /* Check context error */ #if CHK_CTX2 if ( in_indp() ) { #if USE_KERNEL_MESSAGE tm_putstring((UB*)"tk_ext_tsk was called in the task independent\n"); #endif tm_monitor(); /* To monitor */ } #endif #if CHK_CTX1 if ( in_ddsp() ) { #if USE_KERNEL_MESSAGE tm_putstring((UB*)"tk_ext_tsk was called in the dispatch disabled\n"); #endif } #endif DISABLE_INTERRUPT; _ter_tsk(ctxtsk); make_dormant(ctxtsk); force_dispatch(); /* No return */ #ifdef DORMANT_STACK_SIZE /* for WARNING */ _dummy[0] = 0; #endif }
/* |------------------+------------------------------------------------------------| */ StatusType WaitEvent( EventMaskType Mask ) { StatusType ercd = E_OK; ID flgid; FLGCB *flgcb; OS_CHECK_EXT(!in_indp(),E_OS_CALLEVEL); OS_CHECK_EXT(isQueEmpty(&knl_ctxtsk->resque),E_OS_RESOURCE); flgid = knl_ctxtsk - knl_tcb_table; flgid = knl_gtsk_table[flgid].flgid; OS_CHECK_EXT((flgid != INVALID_EVENT),E_OS_ACCESS); flgcb = &knl_flgcb_table[flgid]; BEGIN_CRITICAL_SECTION; if((flgcb->flgptn & Mask) == NO_EVENT) { flgcb->waipth = Mask; knl_ctxtsk->state = TS_WAIT; //release internal resource or for Non-Preemtable Task ReleaseInternalResource(); knl_search_schedtsk(); } END_CRITICAL_SECTION; //re-get internal resource or for Non-Preemtable task GetInternalResource(); Error_Exit: #if(cfgOS_ERROR_HOOK == STD_ON) if(E_OK != ercd) { BEGIN_CRITICAL_SECTION; _errorhook_svcid = OSServiceId_WaitEvent; _errorhook_par1.mask = Mask; CallErrorHook(ercd); END_CRITICAL_SECTION; } #endif /* cfgOS_ERROR_HOOK */ return ercd; }
SYSCALL ER _tk_snd_mbf_u( ID mbfid, CONST void *msg, INT msgsz, TMO_U tmout ) { MBFCB *mbfcb; TCB *tcb; ER ercd = E_OK; CHECK_MBFID(mbfid); CHECK_PAR(msgsz > 0); CHECK_TMOUT(tmout); CHECK_DISPATCH_POL(tmout); mbfcb = get_mbfcb(mbfid); BEGIN_CRITICAL_SECTION; if ( mbfcb->mbfid == 0 ) { ercd = E_NOEXS; goto error_exit; } #if CHK_PAR if ( msgsz > mbfcb->maxmsz ) { ercd = E_PAR; goto error_exit; } #endif /* Check send wait disable */ if ( !in_indp() && is_diswai((GCB*)mbfcb, ctxtsk, TTW_SMBF) ) { ercd = E_DISWAI; goto error_exit; } if ( !isQueEmpty(&mbfcb->recv_queue) ) { /* Send directly to the receive wait task */ tcb = (TCB*)mbfcb->recv_queue.next; memcpy(tcb->winfo.rmbf.msg, msg, (UINT)msgsz); *tcb->winfo.rmbf.p_msgsz = msgsz; wait_release_ok(tcb); } else if ( (in_indp() || gcb_top_of_wait_queue((GCB*)mbfcb, ctxtsk) == ctxtsk) &&(mbf_free(mbfcb, msgsz)) ) { /* Store the message to message buffer */ msg_to_mbf(mbfcb, msg, msgsz); } else { ercd = E_TMOUT; if ( tmout != TMO_POL ) { /* Ready for send wait */ ctxtsk->wspec = ( (mbfcb->mbfatr & TA_TPRI) != 0 )? &wspec_smbf_tpri: &wspec_smbf_tfifo; ctxtsk->wercd = &ercd; ctxtsk->winfo.smbf.msg = msg; ctxtsk->winfo.smbf.msgsz = msgsz; gcb_make_wait_with_diswai((GCB*)mbfcb, tmout); } } error_exit: END_CRITICAL_SECTION; return ercd; }
/* |------------------+-------------------------------------------------------------| */ 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; }