CooCox 1.1.4 on mbed with simple blinky example

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mutex.c Source File

mutex.c

Go to the documentation of this file.
00001 /**
00002  *******************************************************************************
00003  * @file       mutex.c
00004  * @version    V1.1.4    
00005  * @date       2011.04.20
00006  * @brief      Mutex management implementation code of CooCox CoOS kernel.    
00007  *******************************************************************************
00008  * @copy
00009  *
00010  * INTERNAL FILE,DON'T PUBLIC.
00011  * 
00012  * <h2><center>&copy; COPYRIGHT 2009 CooCox </center></h2>
00013  *******************************************************************************
00014  */ 
00015 
00016 
00017 
00018 /*---------------------------- Include ---------------------------------------*/
00019 #include <coocox.h>
00020 
00021 
00022 /*---------------------------- Variable Define -------------------------------*/
00023 #if CFG_MUTEX_EN > 0
00024 
00025 OS_MutexID MutexFreeID  = 0;               /*!< Point to next vliad mutex ID.  */
00026 MUTEX      MutexTbl [CFG_MAX_MUTEX] = {{0}}; /*!< Mutex struct array             */
00027     
00028 
00029 
00030 /**
00031  *******************************************************************************
00032  * @brief      Create a mutex     
00033  * @param[in]  None          
00034  * @param[out] None  
00035  * @retval     E_CREATE_FAIL  Create mutex fail.
00036  * @retval     others         Create mutex successful.         
00037  *
00038  * @par Description                      
00039  * @details    This function is called to create a mutex. 
00040  * @note          
00041  *******************************************************************************
00042  */
00043 OS_MutexID CoCreateMutex(void)
00044 {
00045     OS_MutexID id;
00046     P_MUTEX pMutex;
00047     OsSchedLock();
00048     
00049     /* Assign a free mutex control block */
00050     if(MutexFreeID  < CFG_MAX_MUTEX )
00051     {
00052         id  = MutexFreeID ++;
00053         OsSchedUnlock();
00054         pMutex = &MutexTbl[id];
00055         pMutex->hipriTaskID   = INVALID_ID;
00056         pMutex->originalPrio  = 0xff;
00057         pMutex->mutexFlag     = MUTEX_FREE;  /* Mutex is free,not was occupied */
00058         pMutex->taskID        = INVALID_ID;
00059         pMutex->waittingList  = 0;
00060         return id;                      /* Return mutex ID                    */            
00061     }    
00062     
00063     OsSchedUnlock();     
00064     return E_CREATE_FAIL;               /* No free mutex control block        */    
00065 }
00066 
00067 
00068 
00069 /**    
00070  *******************************************************************************             
00071  * @brief      Enter a critical area  
00072  * @param[in]  mutexID    Specify mutex.      
00073  * @param[out] None   
00074  * @retval     E_INVALID_ID  Invalid mutex id.     
00075  * @retval     E_CALL        Error call in ISR.
00076  * @retval     E_OK          Enter critical area successful.
00077  *
00078  * @par Description
00079  * @details    This function is called when entering a critical area.     
00080  * @note 
00081  *******************************************************************************
00082  */
00083 StatusType CoEnterMutexSection(OS_MutexID mutexID)
00084 {
00085     P_OSTCB ptcb,pCurTcb;
00086     P_MUTEX pMutex;
00087 
00088 #if CFG_EVENT_EN >0
00089     P_ECB pecb;
00090 #endif
00091 
00092     if(OSIntNesting  > 0)                /* If the caller is ISR               */
00093     {
00094         return E_CALL;
00095     }
00096     if(OSSchedLock  != 0)                /* Is OS lock?                        */
00097     {                                 
00098         return E_OS_IN_LOCK;            /* Yes,error return                   */
00099     }    
00100 
00101 #if CFG_PAR_CHECKOUT_EN >0
00102     if(mutexID >= MutexFreeID )          /* Invalid 'mutexID'                  */
00103     {
00104         return E_INVALID_ID;    
00105     }
00106 #endif
00107 
00108     OsSchedLock();
00109     pCurTcb = TCBRunning ;
00110     pMutex  = &MutexTbl[mutexID];
00111     
00112     pCurTcb->mutexID  = mutexID;
00113     if(pMutex->mutexFlag  == MUTEX_FREE)       /* If mutex is available        */     
00114     {
00115         pMutex->originalPrio  = pCurTcb->prio ; /* Save priority of owning task */   
00116         pMutex->taskID        = pCurTcb->taskID ;   /* Acquire the resource     */
00117         pMutex->hipriTaskID   = pCurTcb->taskID ;
00118         pMutex->mutexFlag     = MUTEX_OCCUPY;      /* Occupy the mutex resource*/
00119     }
00120     /* If the mutex resource had been occupied                                */
00121     else if(pMutex->mutexFlag  == MUTEX_OCCUPY)         
00122     {    
00123         ptcb = &TCBTbl [pMutex->taskID ];
00124         if(ptcb->prio  > pCurTcb->prio )  /* Need to promote priority of owner? */
00125         {
00126 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00127             DeleteTaskPri(ptcb->prio );
00128             ActiveTaskPri(pCurTcb->prio );
00129 #endif    
00130             ptcb->prio  = pCurTcb->prio ;        /* Promote prio of owner          */
00131             
00132             /* Upgarde the highest priority about the mutex                   */
00133             pMutex->hipriTaskID     = pCurTcb->taskID ;    
00134             if(ptcb->state  == TASK_READY)   /* If the task is ready to run    */
00135             {
00136                 RemoveFromTCBRdyList(ptcb); /* Remove the task from READY list*/
00137                 InsertToTCBRdyList(ptcb);   /* Insert the task into READY list*/
00138             }
00139 #if CFG_EVENT_EN >0
00140             /* If the task is waiting on a event                              */
00141             else if(ptcb->eventID  != INVALID_ID) 
00142             {
00143                 pecb = &EventTbl [ptcb->eventID ];
00144                 
00145                 /* If the event waiting type is preemptive Priority           */
00146                 if(pecb->eventSortType  == EVENT_SORT_TYPE_PRIO)    
00147                 {
00148                     /* Remove the task from event waiting list                */
00149                     RemoveEventWaittingList(ptcb);
00150                     
00151                     /* Insert the task into event waiting list                */     
00152                     EventTaskToWait(pecb,ptcb);        
00153                 }    
00154             }
00155 #endif    
00156         }
00157         
00158         pCurTcb->state    = TASK_WAITING;    /* Block current task             */
00159         TaskSchedReq     = Co_TRUE;
00160         pCurTcb->TCBnext  = 0;
00161         pCurTcb->TCBprev  = 0;
00162         
00163         ptcb = pMutex->waittingList ;
00164         if(ptcb == 0)               /* If the event waiting list is empty  */
00165         {
00166             pMutex->waittingList  = pCurTcb; /* Insert the task to head        */
00167         }
00168         else                        /* If the event waiting list is not empty */
00169         {                
00170             while(ptcb->TCBnext  != 0)    /* Insert the task to tail        */
00171             {
00172                 ptcb = ptcb->TCBnext ;        
00173             }
00174             ptcb->TCBnext     = pCurTcb;
00175             pCurTcb->TCBprev  = ptcb;
00176             pCurTcb->TCBnext  = 0;
00177         }
00178     }
00179     OsSchedUnlock();
00180     return E_OK;            
00181 }
00182 
00183 
00184 /**
00185  *******************************************************************************
00186  * @brief      Leave from a critical area     
00187  * @param[in]  mutexID     Specify mutex id.     
00188  * @param[out] None 
00189  * @retval     E_INVALID_ID  Invalid mutex id.
00190  * @retval     E_CALL        Error call in ISR.
00191  * @retval     E_OK          Exit a critical area successful.
00192  *
00193  * @par Description         
00194  * @details    This function must be called when exiting from a critical area.    
00195  * @note 
00196  *******************************************************************************
00197  */
00198 StatusType CoLeaveMutexSection(OS_MutexID mutexID)
00199 {
00200     P_OSTCB ptcb;
00201     P_MUTEX pMutex;
00202     U8      prio;
00203     U8      taskID;
00204     
00205     if(OSIntNesting  > 0)                /* If the caller is ISR               */
00206     {
00207         return E_CALL;
00208     }
00209 
00210 #if CFG_PAR_CHECKOUT_EN >0
00211     if(mutexID >= MutexFreeID )
00212     {
00213         return E_INVALID_ID;            /* Invalid mutex id, return error     */
00214     }
00215 #endif    
00216     OsSchedLock();
00217     pMutex = &MutexTbl[mutexID];        /* Obtain point of mutex control block*/   
00218     ptcb = &TCBTbl [pMutex->taskID ];
00219     ptcb->mutexID  = INVALID_ID;
00220     if(pMutex->waittingList  == 0)    /* If the mutex waiting list is empty */
00221     {
00222         pMutex->mutexFlag  = MUTEX_FREE; /* The mutex resource is available    */
00223         pMutex->taskID     = INVALID_ID;
00224         OsSchedUnlock();
00225     }    
00226     else              /* If there is at least one task waitting for the mutex */
00227     { 
00228         taskID = pMutex->taskID ;        /* Get task ID of mutex owner         */
00229         
00230                                 /* we havn't promoted current task's priority */
00231         if(pMutex->hipriTaskID  == taskID)   
00232         {
00233             ptcb = pMutex->waittingList ;/* Point to mutex first waiting task  */        
00234             prio = ptcb->prio ; 
00235             while(ptcb != 0)         /* Find the highest priority task     */
00236             {
00237                 if(ptcb->prio  < prio)          
00238                 {
00239                     prio = ptcb->prio ;
00240                     pMutex->hipriTaskID  = ptcb->taskID ;
00241                 }
00242                 ptcb = ptcb->TCBnext ;                    
00243             }
00244         }
00245         else                     /* we have promoted current task's priority  */
00246         {
00247             prio = TCBTbl [taskID].prio ;
00248         }
00249         
00250         /* Reset the task priority */
00251         pMutex->taskID  = INVALID_ID;    
00252         CoSetPriority(taskID,pMutex->originalPrio );
00253         
00254         /* Find first task in waiting list ready to run  */    
00255         ptcb                 = pMutex->waittingList ;         
00256         pMutex->waittingList  = ptcb->TCBnext ;    
00257         pMutex->originalPrio  = ptcb->prio ;
00258         pMutex->taskID        = ptcb->taskID ;
00259 
00260 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
00261         if(prio != ptcb->prio )
00262         {
00263             DeleteTaskPri(ptcb->prio );
00264             ActiveTaskPri(prio);            
00265         }
00266 #endif    
00267 
00268         ptcb->prio            = prio;    /* Raise the task's priority          */       
00269                            
00270         /* Insert the task which acquire the mutex into ready list.           */
00271         ptcb->TCBnext  = 0;
00272         ptcb->TCBprev  = 0;
00273 
00274         InsertToTCBRdyList(ptcb);     /* Insert the task into the READY list  */
00275         OsSchedUnlock();
00276     }
00277     return E_OK;            
00278 }
00279 
00280 /**
00281  *******************************************************************************
00282  * @brief      Remove a task from mutex waiting list       
00283  * @param[in]  ptcb   TCB which will remove out.     
00284  * @param[out] None      
00285  * @retval     None
00286  *
00287  * @par Description         
00288  * @details   This function be called when delete a task.    
00289  * @note 
00290  *******************************************************************************
00291  */
00292 void RemoveMutexList(P_OSTCB ptcb)
00293 {
00294     U8 prio;
00295     OS_TID taskID;
00296     P_MUTEX pMutex;
00297     pMutex = &MutexTbl[ptcb->mutexID ];
00298     
00299     /* If only one task waiting on mutex                                      */    
00300     if((ptcb->TCBnext  ==0) && (ptcb->TCBprev  == 0))
00301     {
00302         pMutex->waittingList  = 0;     /* Waiting list is empty             */
00303     }
00304     else if(ptcb->TCBnext  == 0)  /* If the task is the last of waiting list*/
00305     {
00306         /* Remove task from mutex waiting list                                */
00307         ptcb->TCBprev ->TCBnext  = 0;
00308         ptcb->TCBprev  = 0;
00309     }    
00310     else if(ptcb->TCBprev  ==  0)/* If the task is the first of waiting list*/
00311     {
00312         /* Remove task from waiting list                                      */
00313         ptcb->TCBnext ->TCBprev  = 0;
00314         ptcb->TCBnext  = 0;
00315     }
00316     else                      /* If the task is in the middle of waiting list */
00317     {
00318         /* Remove task from wait list */
00319         ptcb->TCBnext ->TCBprev  = ptcb->TCBprev ;
00320         ptcb->TCBprev ->TCBnext  = ptcb->TCBnext ;
00321         ptcb->TCBprev           = 0;
00322         ptcb->TCBnext           = 0;
00323     }
00324     
00325     ptcb->mutexID  = INVALID_ID;
00326     
00327     /* If the task have highest priority in mutex waiting list                */    
00328     if(pMutex->hipriTaskID  == ptcb->taskID )                        
00329     {
00330         ptcb = pMutex->waittingList ;
00331         prio = pMutex->originalPrio ; 
00332         pMutex->hipriTaskID  = pMutex->taskID ;
00333         while(ptcb != 0)           /* Find task ID of highest priority task*/
00334         {
00335             if(ptcb->prio  < prio)
00336             {
00337                 prio = ptcb->prio ;
00338                 pMutex->hipriTaskID  = ptcb->taskID ;
00339             }
00340             ptcb = ptcb->TCBnext ;            
00341         }
00342         taskID = pMutex->taskID ;
00343         pMutex->taskID  = INVALID_ID;
00344         CoSetPriority(taskID,prio);         /* Reset the mutex ower priority  */
00345         pMutex->taskID  = taskID;
00346     }
00347 }
00348 
00349 #endif