Example #1
0
/**
 *******************************************************************************
 * @brief      Remove a flag node from list
 * @param[in]  pnode    A node that will remove from flag waiting list.
 * @param[out] None
 * @retval     pnode    Next node of the node that have removed out.
 *
 * @par Description
 * @details   This function is called to remove a flag node from the wait list.
 * @note
 *******************************************************************************
 */
static P_FLAG_NODE RemoveFromLink(P_FLAG_NODE pnode)
{
    P_OSTCB ptcb;

    RemoveLinkNode(pnode);            /* Remove the flag node from wait list. */
    ptcb = pnode->waitTask;

    /* The task in the delay list */
    if(ptcb->delayTick != INVALID_VALUE)/* If the task is in tick delay list  */
    {
        RemoveDelayList(ptcb);        /* Remove the task from tick delay list */
    }

	ptcb->pnode = (void*)0xffffffff;

	if(ptcb == TCBRunning)
	{
		ptcb->state = TASK_RUNNING;
	}
	else
	{
		InsertToTCBRdyList(ptcb);         /* Insert the task to ready list        */
	}
    return (pnode->nextNode);
}
Example #2
0
/**
 *******************************************************************************
 * @brief      Dispose time delay	 
 * @param[in]  None	 
 * @param[out] None 
 * @retval     None 
 *
 * @par Description
 * @details    This function is called to dispose time delay of all task.  
 *******************************************************************************
 */
void TimeDispose(void)
{  
    P_OSTCB	dlyList;
    
    dlyList = DlyList;                  /* Get first item of DELAY list       */
    while((dlyList != Co_NULL) && (dlyList->delayTick == 0) )
    {	
    
#if CFG_EVENT_EN > 0
        if(dlyList->eventID != INVALID_ID) /* Is task in event waiting list?  */
        {								   
            RemoveEventWaittingList(dlyList); /* Yes,remove task from list    */	
        }
#endif

#if CFG_FLAG_EN  > 0
        if(dlyList->pnode != Co_NULL)          /* Is task in flag waiting list?  */
        {
            RemoveLinkNode(dlyList->pnode); /* Yes,remove task from list      */	
        }
#endif
        dlyList->delayTick = INVALID_VALUE; /* Set delay tick value as invalid*/
        DlyList = dlyList->TCBnext; /* Get next item as the head of DELAY list*/
        dlyList->TCBnext   = Co_NULL;

		InsertToTCBRdyList(dlyList);        /* Insert task into READY list    */
        
        dlyList = DlyList;                /* Get the first item of DELAY list */
        if(dlyList != Co_NULL)                 /* Is DELAY list as Co_NULL?         */
        {
            dlyList->TCBprev = Co_NULL;        /* No,initialize the first item   */
        }
    }
}
Example #3
0
/**
 *******************************************************************************
 * @brief      Reset task delay ticks
 * @param[in]  ptcb    Task that want to insert into DELAY list.
 * @param[in]  ticks   Specify system tick number which will delay .
 * @param[out] None
 * @retval     E_CALL               Error call in ISR.
 * @retval     E_INVALID_ID         Invalid task id.
 * @retval     E_NOT_IN_DELAY_LIST  Task not in delay list.
 * @retval     E_OK                 The current task was inserted to DELAY list
 *                                  successful,it will delay for specify time.
 * @par Description
 * @details    This function delay specify ticks for current task.
 *******************************************************************************
 */
StatusType CoResetTaskDelayTick(OS_TID taskID,U32 ticks) {
	P_OSTCB ptcb;


#if CFG_PAR_CHECKOUT_EN >0              /* Check validity of parameter        */
	if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM) {
		return E_INVALID_ID;
	}
#endif

	ptcb = &TCBTbl[taskID];
#if CFG_PAR_CHECKOUT_EN >0
	if(ptcb->stkPtr == Co_NULL) {
		return E_INVALID_ID;
	}
#endif

	if(ptcb->delayTick == INVALID_VALUE) { /* Is tick==INVALID_VALUE?          */
		return E_NOT_IN_DELAY_LIST;       /* Yes,error return                 */
	}
	OsSchedLock();                        /* Lock schedule                    */
	RemoveDelayList(ptcb);                /* Remove task from the DELAY list  */

	if(ticks == 0) {                      /* Is delay tick==0?                */
		InsertToTCBRdyList(ptcb);         /* Insert task into the DELAY list  */
	} else {
		InsertDelayList(ptcb,ticks);      /* No,insert task into DELAY list   */
	}
	OsSchedUnlock();                /* Unlock schedule,and call task schedule */
	return E_OK;                          /* Return OK                        */
}
Example #4
0
/**
 *******************************************************************************
 * @brief      Move a task from event WAITING list to the DELAY list	  
 * @param[in]  pecb    Pointer to event control block corresponding to the event. 		 	  
 * @param[out] None  
 * @retval     None	 
 *
 * @par Description
 * @details    This function is called to remove a task from event wait list,and	 
 *             then insert it into the READY list.
 *******************************************************************************
 */
void EventTaskToRdy(P_ECB pecb)
{
    P_OSTCB ptcb;
#if CFG_QUEUE_EN >0
    P_QCB   pqcb;
#endif
    ptcb = pecb->eventTCBList;
    if(ptcb == NULL)
        return;
    
    pecb->eventTCBList = ptcb->waitNext;/* Get first task in event waiting list*/
    if(pecb->eventTCBList != NULL)      /* Is no item in event waiting list?  */
    {
        pecb->eventTCBList->waitPrev = NULL; /* No,clear link for first item  */
    }
    
    ptcb->waitNext = NULL;                /* Clear event waiting link for task*/
    ptcb->eventID  = INVALID_ID;          /* Sign that not to use.            */
    
    if(ptcb->delayTick != INVALID_VALUE)  /* Is task in delay list?           */		         
    {
        RemoveDelayList(ptcb);            /* Yes,remove task from DELAY list  */
    }
    if(pecb->eventType == EVENT_TYPE_MBOX)/* Is it a mailbox event?           */
    {
        ptcb->pmail    = pecb->eventPtr;  /* Yes,send mail to task            */
        pecb->eventPtr = NULL;            /* Clear event sign                 */
        pecb->eventCounter--;
    }
#if CFG_QUEUE_EN >0
    else if(pecb->eventType == EVENT_TYPE_QUEUE)  /* Is it a queue event?     */
    {										   
        pqcb        = (P_QCB)pecb->eventPtr;      /* Yes,get queue pointer    */
        ptcb->pmail = *(pqcb->qStart + pqcb->head);   /* Send mail to task    */
        pqcb->head++;                             /* Clear event sign         */
        pqcb->qSize--;
        if(pqcb->head == pqcb->qMaxSize)
        {
            pqcb->head = 0;	
        }
    }
#endif

#if CFG_MAILBOX_EN >0
    else if(pecb->eventType == EVENT_TYPE_SEM)/* Is it a semaphore event?     */
    {
        pecb->eventCounter--;                 /* Yes,clear event sign         */
        ptcb->pmail = (void*)0xffffffff;      /* Indicate task woke by event  */
    }
#endif
	if(ptcb == TCBRunning)
	{
		ptcb->state = TASK_RUNNING;
	} 
	else
	{
		InsertToTCBRdyList(ptcb);            /* Insert task into ready list  */
	}
}
Example #5
0
/**
 *******************************************************************************
 * @brief      Delete a event	  
 * @param[in]  pecb     Pointer to event control block which will be deleted. 
 * @param[in]  opt      Delete option.
 * @arg        == OPT_DEL_ANYWAY     Delete event always   
 * @arg        == OPT_DEL_NO_PEND	 Delete event only when no task pending on.
 * @param[out] None  	 
 * @retval     E_INVALID_PARAMETER   Parameter passed is invalid,deleted fail.
 * @retval     E_TASK_WAITTING       These are one more tasks waitting event.  
 * @retval     E_OK                  Delete event control block successful.
 *		  	
 * @par Description
 * @details    This function is called to delete a event from the event wait list
 *             use specify option.
 *
 * @note       This is a internal function of Coocox CoOS,user can't call.		
 *******************************************************************************
 */
StatusType DeleteEvent(P_ECB pecb,U8 opt)
{
    P_OSTCB ptcb;
    if(opt == OPT_DEL_NO_PEND)          /* Do delete event when no task pend? */
    {
        if(pecb->eventTCBList != NULL)  /* Yes,is there task pend this event? */
        {
            return E_TASK_WAITING;      /* Yes,error return                   */
        }
        else
        {
            ReleaseECB(pecb);           /* No,release resource that event hold*/
        }
    }
    else if(opt == OPT_DEL_ANYWAY)      /* Do delete event anyway?            */
    {
        OsSchedLock();                      /* Lock schedule                  */
        while(pecb->eventTCBList != NULL)   /* Is there task pend this event? */
        {                                   /* Yes,remove it                  */
            ptcb = pecb->eventTCBList;/* Get first task in event waiting list */
            if(ptcb->delayTick != INVALID_VALUE) /* Is task in delay list?    */
            {
                RemoveDelayList(ptcb);    /* Yes,remove task from delay list  */
            }

            /* Set next item as event waiting list head */
            pecb->eventTCBList = ptcb->waitNext; 
            ptcb->waitNext     = NULL;  /* Clear link for event waiting list  */
            ptcb->eventID      = INVALID_ID;  /* Sign that not to use.        */

			InsertToTCBRdyList(ptcb);         /* Insert task into ready list  */
        }
        OsSchedUnlock();                  /* Unlock schedule                  */
        ReleaseECB(pecb);                 /* Release resource that event hold */
    }
    return E_OK;                          /* Return OK                        */
}
Example #6
0
/**
 *******************************************************************************
 * @brief      Create a task	   
 * @param[in]  task       Task code entry.
 * @param[in]  argv       The parameter passed to task.
 * @param[in]  parameter  Task priority + stack size + time slice + isWaitting.
 * @param[in]  stk        Pointer to stack top of task.
 * @param[out] None   
 * @retval     E_CREATE_FAIL    Fail to create a task .
 * @retval     others           Valid task id.				 
 *
 * @par Description
 * @details    This function is called by application to create a task,return a id 
 *             to mark this task.
 *******************************************************************************
 */
OS_TID CreateTask(FUNCPtr task,void *argv,U32 parameter,OS_STK *stk)
{
    OS_STK* stkTopPtr;
    P_OSTCB ptcb;
    U8      prio;
#if CFG_ROBIN_EN >0	
    U16     timeSlice;
#endif
   
#if CFG_STK_CHECKOUT_EN >0              /* Check validity of parameter        */
    U16 sktSz;
    sktSz = (parameter&0xfff00)>>8;    
#endif
    prio = parameter&0xff;

#if CFG_PAR_CHECKOUT_EN >0              /* Check validity of parameter        */
    if(task == Co_NULL)
    {
        return E_CREATE_FAIL;
    }
    if(stk == Co_NULL)
    {
        return E_CREATE_FAIL;
    }
    if(prio > CFG_LOWEST_PRIO)
    {
        return E_CREATE_FAIL;		
    }
#if CFG_STK_CHECKOUT_EN >0
    if(sktSz < 20)
    {
        return E_CREATE_FAIL;		
    }
#endif	  // CFG_STK_CHECKOUT_EN
#endif	  // CFG_PAR_CHECKOUT_EN

#if CFG_TASK_SCHEDULE_EN == 0
	if(TCBRunning != Co_NULL)
		 return E_CREATE_FAIL;	
#endif   

    stkTopPtr = InitTaskContext(task,argv,stk);   /* Initialize task context. */
    
    ptcb = AssignTCB();                 /* Get free TCB to use                */
    
    if(ptcb == Co_NULL)                    /* Is free TCB equal to Co_NULL?         */
    {
        return E_CREATE_FAIL;           /* Yes,error return                   */
    }
    
    ptcb->stkPtr = stkTopPtr;           /* Initialize TCB as user set         */
    ptcb->prio   = prio;
#if CFG_STK_CHECKOUT_EN >0
    ptcb->stack = stk+1 - sktSz; /* Set bottom stack for stack overflow check */
    *(U32*)(ptcb->stack) = MAGIC_WORD;
#endif	

#if CFG_TASK_WAITTING_EN >0
    ptcb->delayTick	= INVALID_VALUE;	
#endif		 

#if CFG_TASK_SCHEDULE_EN == 0
	ptcb->taskFuc = task;
	ptcb->taskStk = stk;
#endif     
    ptcb->TCBnext = Co_NULL;               /* Initialize TCB link in READY list  */
    ptcb->TCBprev = Co_NULL;

#if CFG_ROBIN_EN >0						/* Set task time slice for task robin */
    timeSlice = (parameter&0x7fff0000)>>20; 
    if(timeSlice == 0)
    {
        timeSlice = CFG_TIME_SLICE;
    }
    ptcb->timeSlice = timeSlice;
#endif

#if CFG_FLAG_EN > 0
    ptcb->pnode = Co_NULL;                 /* Initialize task as no flag waiting */
#endif

#if CFG_EVENT_EN > 0
    ptcb->eventID  = INVALID_ID;      	/* Initialize task as no event waiting*/
    ptcb->pmail    = Co_NULL;
    ptcb->waitNext = Co_NULL;
    ptcb->waitPrev = Co_NULL;
#endif

#if CFG_MUTEX_EN > 0
    /* Initialize task as no mutex holding or waiting                         */
    ptcb->mutexID = INVALID_ID; 
#endif 

#if CFG_ORDER_LIST_SCHEDULE_EN ==0
	ActiveTaskPri(prio);	
#endif	

	if((parameter>>31) == 0)			/* Is task in waitting state?         */
	{									/* No,set it into ready list          */
		OsSchedLock();                  /* Lock schedule                      */
		InsertToTCBRdyList(ptcb);       /* Insert into the READY list         */
	    OsSchedUnlock();                /* Unlock schedule                    */
	}
	else
	{									/* Yes,Set task status as TASK_WAITING*/
Example #7
0
/**
 *******************************************************************************
 * @brief      Schedule function	  
 * @param[in]  None 	 
 * @param[out] None  	 
 * @retval     None	 
 *
 * @par Description
 * @details    This function is called by every where need to switch context,
 *             It is schedule function of OS kernel.
 *******************************************************************************
 */
void Schedule(void)
{
    U8  RunPrio,RdyPrio;
    P_OSTCB pRdyTcb,pCurTcb;
   
	
    pCurTcb = TCBRunning;    
    pRdyTcb = TCBRdy;

	if((pRdyTcb==Co_NULL) || (pCurTcb != TCBNext) || (OSSchedLock >1) || (OSIntNesting >0))
	{
		return;
	}
    
	TaskSchedReq = Co_FALSE;
    RunPrio = pCurTcb->prio;
    RdyPrio = pRdyTcb->prio;

	/* Is Running task status was changed? */
    if(pCurTcb->state != TASK_RUNNING)	
    {
        TCBNext        = pRdyTcb;   /* Yes,set TCBNext and reorder READY list */
        pRdyTcb->state = TASK_RUNNING;
        RemoveFromTCBRdyList(pRdyTcb);
    }

    else if(RdyPrio < RunPrio )     /* Is higher PRI task coming in?          */
    {
        TCBNext        = pRdyTcb;   /* Yes,set TCBNext and reorder READY list */
        InsertToTCBRdyList(pCurTcb);
		RemoveFromTCBRdyList(pRdyTcb);
        pRdyTcb->state = TASK_RUNNING;
    }
    
#if CFG_ROBIN_EN >0                 /* Is time for robinning                  */                            
    else if((RunPrio == RdyPrio) && (OSCheckTime == OSTickCnt))
    {
        TCBNext        = pRdyTcb;   /* Yes,set TCBNext and reorder READY list */
        InsertToTCBRdyList(pCurTcb);
		RemoveFromTCBRdyList(pRdyTcb);
        pRdyTcb->state = TASK_RUNNING;
    }
#endif
    else
    {								    
        return;	
    }
    
#if CFG_ROBIN_EN >0
    if(TCBNext->prio == TCBRdy->prio)  /* Reset OSCheckTime for task robinnig */
        OSCheckTime = OSTickCnt + TCBNext->timeSlice;
#endif
    
  
#if CFG_STK_CHECKOUT_EN > 0                       /* Is stack overflow?       */
    if((pCurTcb->stkPtr < pCurTcb->stack)||(*(U32*)(pCurTcb->stack) != MAGIC_WORD))       
    {									
        CoStkOverflowHook(pCurTcb->taskID);       /* Yes,call handler         */		
    }   
#endif
 	
    SwitchContext();                              /* Call task context switch */
}
Example #8
0
/**
 *******************************************************************************
 * @brief      Change task priority	   
 * @param[in]  taskID     Specify task id.
 * @param[in]  priority   New priority.	 
 * @param[out] None		   
 * @retval     E_OK              Change priority successful.
 * @retval     E_INVALID_ID      Invalid id,change priority fail.
 * @retval     E_PROTECTED_TASK  Can't change idle task priority.		 
 *
 * @par Description
 * @details    This function is called to change priority for a specify task. 	
 *******************************************************************************
 */
StatusType CoSetPriority(OS_TID taskID,U8 priority)
{			
    P_OSTCB ptcb;
#if CFG_MUTEX_EN >0
    U8 prio;
    P_MUTEX	pMutex;
#endif
#if CFG_EVENT_EN >0
    P_ECB pecb;
#endif

    if(taskID == 0)                     /* Is idle task?                      */
    {											 
        return E_PROTECTED_TASK;        /* Yes,error return                   */
    }   
	
#if CFG_PAR_CHECKOUT_EN >0              /* Check validity of parameter        */
    if(taskID >= CFG_MAX_USER_TASKS + SYS_TASK_NUM)
    {
        return E_INVALID_ID;
    }
#endif
	ptcb = &TCBTbl[taskID];             /* Get TCB of task ID                 */
#if CFG_PAR_CHECKOUT_EN >0    
    if(ptcb->state == TASK_DORMANT)
    {
        return E_INVALID_ID;
    }
    if(priority > CFG_LOWEST_PRIO)
    {
        return E_INVALID_ID;
    }
#endif

    if(ptcb->prio != priority)          /* Is PRI equal to original PRI?      */
    {                                   /* No                                 */
#if CFG_MUTEX_EN >0
        if(ptcb->mutexID != INVALID_ID)
        {
            pMutex = &MutexTbl[ptcb->mutexID];
            if(pMutex->taskID == ptcb->taskID)  /* Task hold mutex?               */
            {
                 pMutex->originalPrio= priority;/* Yes,change original PRI in mutex*/
                 if(ptcb->prio < priority)     /* Is task priority higher than set?*/
                 {
                     return E_OK;                /* Yes,do nothing,return OK       */
                 }
            }		
         }

#endif	

#if CFG_ORDER_LIST_SCHEDULE_EN ==0
		DeleteTaskPri(ptcb->prio);
		ActiveTaskPri(priority);	
#endif	

        ptcb->prio = priority;              /* Change task PRI                */
        if(ptcb->state == TASK_READY)       /* Is task in READY list?         */
        {
            OsSchedLock();                  /* Yes,reorder task in READY list */
            RemoveFromTCBRdyList(ptcb);
            InsertToTCBRdyList(ptcb);	
            OsSchedUnlock();
        }
        else if(ptcb->state == TASK_RUNNING)/* Is task running?               */
        {
            if(ptcb->prio > TCBRdy->prio)   /* Yes,Is PRI higher than TCBRdy? */
            {
				OsSchedLock();              /* Yes,reorder task in READY list */
				TaskSchedReq = Co_TRUE;
                OsSchedUnlock();
            }
        }
        else
        {                                   /* No,task in WAITING list        */
#if CFG_MUTEX_EN >0
            if(ptcb->mutexID != INVALID_ID) /* Is task in mutex WAITING list? */
            {
                /* Yes,reset the highest PRI in the list */
				OsSchedLock(); 
				pMutex = &MutexTbl[ptcb->mutexID];
                ptcb = pMutex->waittingList;  
                prio = pMutex->originalPrio; 
                pMutex->hipriTaskID = pMutex->taskID;
                while(ptcb != Co_NULL)
                {
                    if(ptcb->prio < prio)
                    {
                        prio = ptcb->prio;
                        pMutex->hipriTaskID = ptcb->taskID;
                    }
                    ptcb = ptcb->TCBnext;			
                }
				OsSchedUnlock();
                if(pMutex->originalPrio != prio)
                {
                    CoSetPriority(pMutex->taskID,prio);	
                }	
            }
#endif

#if CFG_EVENT_EN >0
			ptcb = &TCBTbl[taskID];
            if(ptcb->eventID != INVALID_ID) /* Is task in event WAITING list? */
            {								    
                pecb = &EventTbl[ptcb->eventID];
                
                /* Yes,is event sort type as preemptive PRI?                  */
                if(pecb->eventSortType == EVENT_SORT_TYPE_PRIO)
                {	  
                    /* Yes,reorder task in the list                           */
                    RemoveEventWaittingList(ptcb);
                    EventTaskToWait(pecb,ptcb);
                }	
            }
#endif
        }
    }
    return E_OK;
}
Example #9
0
/**
 *******************************************************************************
 * @brief      Leave from a critical area	 
 * @param[in]  mutexID 	Specify mutex id.	 
 * @param[out] None 
 * @retval     E_INVALID_ID  Invalid mutex id.
 * @retval     E_CALL        Error call in ISR.
 * @retval     E_OK          Exit a critical area successful.
 *
 * @par Description		 
 * @details    This function must be called when exiting from a critical area.	
 * @note 
 *******************************************************************************
 */
StatusType CoLeaveMutexSection(OS_MutexID mutexID)
{
    P_OSTCB ptcb;
    P_MUTEX pMutex;
    U8      prio;
    U8      taskID;
    
    if(OSIntNesting > 0)                /* If the caller is ISR               */
    {
        return E_CALL;
    }

#if CFG_PAR_CHECKOUT_EN >0
    if(mutexID >= MutexFreeID)
    {
        return E_INVALID_ID;            /* Invalid mutex id, return error     */
    }
#endif	
    OsSchedLock();
    pMutex = &MutexTbl[mutexID];        /* Obtain point of mutex control block*/   
    ptcb = &TCBTbl[pMutex->taskID];
	ptcb->mutexID = INVALID_ID;
	if(pMutex->waittingList == Co_NULL)    /* If the mutex waiting list is empty */
    {
        pMutex->mutexFlag = MUTEX_FREE; /* The mutex resource is available    */
        pMutex->taskID    = INVALID_ID;
        OsSchedUnlock();
    }	
    else              /* If there is at least one task waitting for the mutex */
    { 
        taskID = pMutex->taskID;        /* Get task ID of mutex owner         */
        
                                /* we havn't promoted current task's priority */
        if(pMutex->hipriTaskID == taskID)   
        {
            ptcb = pMutex->waittingList;/* Point to mutex first waiting task  */		
            prio = ptcb->prio; 
            while(ptcb != Co_NULL)         /* Find the highest priority task     */
            {
                if(ptcb->prio < prio)  		
                {
                    prio = ptcb->prio;
                    pMutex->hipriTaskID = ptcb->taskID;
                }
                ptcb = ptcb->TCBnext;					
            }
        }
        else                     /* we have promoted current task's priority  */
        {
			prio = TCBTbl[taskID].prio;
        }
        
        /* Reset the task priority */
		pMutex->taskID = INVALID_ID;	
		CoSetPriority(taskID,pMutex->originalPrio);
        
        /* Find first task in waiting list ready to run  */	
        ptcb                 = pMutex->waittingList; 		
        pMutex->waittingList = ptcb->TCBnext;	
        pMutex->originalPrio = ptcb->prio;
        pMutex->taskID       = ptcb->taskID;

#if CFG_ORDER_LIST_SCHEDULE_EN ==0
		if(prio != ptcb->prio)
		{
			DeleteTaskPri(ptcb->prio);
			ActiveTaskPri(prio);			
		}
#endif	

        ptcb->prio           = prio;    /* Raise the task's priority          */       
        				   
        /* Insert the task which acquire the mutex into ready list.           */
        ptcb->TCBnext = Co_NULL;
        ptcb->TCBprev = Co_NULL;

		InsertToTCBRdyList(ptcb);     /* Insert the task into the READY list  */
        OsSchedUnlock();
    }
    return E_OK;			
}
Example #10
0
/**	
 *******************************************************************************		 	
 * @brief      Enter a critical area  
 * @param[in]  mutexID    Specify mutex. 	 
 * @param[out] None   
 * @retval     E_INVALID_ID  Invalid mutex id. 	
 * @retval     E_CALL        Error call in ISR.
 * @retval     E_OK          Enter critical area successful.
 *
 * @par Description
 * @details    This function is called when entering a critical area.	 
 * @note 
 *******************************************************************************
 */
StatusType CoEnterMutexSection(OS_MutexID mutexID)
{
    P_OSTCB ptcb,pCurTcb;
    P_MUTEX pMutex;

#if CFG_EVENT_EN >0
    P_ECB pecb;
#endif

    if(OSIntNesting > 0)                /* If the caller is ISR               */
    {
        return E_CALL;
    }
    if(OSSchedLock != 0)                /* Is OS lock?                        */
    {								 
        return E_OS_IN_LOCK;            /* Yes,error return                   */
    }	

#if CFG_PAR_CHECKOUT_EN >0
    if(mutexID >= MutexFreeID)          /* Invalid 'mutexID'                  */
    {
        return E_INVALID_ID;	
    }
#endif

    OsSchedLock();
    pCurTcb = TCBRunning;
    pMutex  = &MutexTbl[mutexID];
    
    pCurTcb->mutexID = mutexID;
    if(pMutex->mutexFlag == MUTEX_FREE)       /* If mutex is available        */	 
    {
        pMutex->originalPrio = pCurTcb->prio; /* Save priority of owning task */   
        pMutex->taskID       = pCurTcb->taskID;   /* Acquire the resource     */
        pMutex->hipriTaskID  = pCurTcb->taskID;
        pMutex->mutexFlag    = MUTEX_OCCUPY;      /* Occupy the mutex resource*/
    }
    /* If the mutex resource had been occupied                                */
    else if(pMutex->mutexFlag == MUTEX_OCCUPY)	 	
    {	
		ptcb = &TCBTbl[pMutex->taskID];
        if(ptcb->prio > pCurTcb->prio)  /* Need to promote priority of owner? */
        {
#if CFG_ORDER_LIST_SCHEDULE_EN ==0
			DeleteTaskPri(ptcb->prio);
			ActiveTaskPri(pCurTcb->prio);
#endif	
            ptcb->prio = pCurTcb->prio;	    /* Promote prio of owner          */
            
            /* Upgarde the highest priority about the mutex                   */
            pMutex->hipriTaskID	= pCurTcb->taskID;	
            if(ptcb->state == TASK_READY)   /* If the task is ready to run    */
            {
                RemoveFromTCBRdyList(ptcb); /* Remove the task from READY list*/
                InsertToTCBRdyList(ptcb);   /* Insert the task into READY list*/
            }
#if CFG_EVENT_EN >0
            /* If the task is waiting on a event                              */
            else if(ptcb->eventID != INVALID_ID) 
            {
                pecb = &EventTbl[ptcb->eventID];
                
                /* If the event waiting type is preemptive Priority           */
                if(pecb->eventSortType == EVENT_SORT_TYPE_PRIO)	
                {
                    /* Remove the task from event waiting list                */
                    RemoveEventWaittingList(ptcb);
                    
                    /* Insert the task into event waiting list                */ 	
                    EventTaskToWait(pecb,ptcb);		
                }	
            }
#endif	
        }
        
        pCurTcb->state   = TASK_WAITING;    /* Block current task             */
		TaskSchedReq     = Co_TRUE;
        pCurTcb->TCBnext = Co_NULL;
        pCurTcb->TCBprev = Co_NULL;
        
        ptcb = pMutex->waittingList;
        if(ptcb == Co_NULL)               /* If the event waiting list is empty  */
        {
            pMutex->waittingList = pCurTcb; /* Insert the task to head        */
        }
        else                        /* If the event waiting list is not empty */
        {            	
            while(ptcb->TCBnext != Co_NULL)    /* Insert the task to tail        */
            {
                ptcb = ptcb->TCBnext;		
            }
            ptcb->TCBnext    = pCurTcb;
            pCurTcb->TCBprev = ptcb;
            pCurTcb->TCBnext = Co_NULL;
        }
    }
    OsSchedUnlock();
    return E_OK;			
}