Esempio n. 1
0
/* |------------------+-----------------------------------------------------------| */
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
/* |------------------+------------------------------------------------------------| */
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;
}
Esempio n. 4
0
/* |------------------+---------------------------------------------------------| */
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;
}
Esempio n. 5
0
/*
 * 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 */
}
Esempio n. 6
0
/* |------------------+-------------------------------------------------------------| */
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;
}
Esempio n. 8
0
/* |------------------+-------------------------------------------------------------| */
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;
}
Esempio n. 9
0
/* |------------------+------------------------------------------------------------| */
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;
}
Esempio n. 10
0
/* |------------------+-------------------------------------------------------------| */
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;
}
Esempio n. 11
0
/* |------------------+-----------------------------------------------------------| */
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;
}
Esempio n. 12
0
/*
 * 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
}
Esempio n. 14
0
/* |------------------+--------------------------------------------------------------| */
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;
}
Esempio n. 16
0
/* |------------------+--------------------------------------------------------------| */
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;
}
Esempio n. 17
0
/*
 * 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
}
Esempio n. 18
0
/* |------------------+------------------------------------------------------------| */
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;
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
/* |------------------+-------------------------------------------------------------| */
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;
}