Eric Ebert / Mbed 2 deprecated CoOS

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers queue.c Source File

queue.c

Go to the documentation of this file.
00001 /**
00002  *******************************************************************************
00003  * @file       queue.c
00004  * @version    V1.1.3    
00005  * @date       2010.04.26
00006  * @brief      Queue 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 /*---------------------------- Include ---------------------------------------*/
00017 #include <coocox.h>
00018 
00019 
00020 #if CFG_QUEUE_EN > 0                                         
00021 /*---------------------------- Variable Define -------------------------------*/
00022 QCB   QueueTbl [CFG_MAX_QUEUE] = {{0}};    /*!< Queue control block table        */
00023 U32   QueueIDVessel  = 0;                /*!< Queue list mask                  */
00024 
00025 
00026  
00027 /**
00028  *******************************************************************************
00029  * @brief      Create a queue    
00030  * @param[in]  qStart    Pointer to mail pointer buffer.
00031  * @param[in]  size      The length of queue.
00032  * @param[in]  sortType  Mail queue waiting list sort type.
00033  * @param[out] None  
00034  * @retval     E_CREATE_FAIL  Create queue fail.
00035  * @retval     others         Create queue successful.
00036  *
00037  * @par Description
00038  * @details    This function is called to create a queue. 
00039  * @note 
00040  *******************************************************************************
00041  */                    
00042 OS_EventID CoCreateQueue(void **qStart, U16 size ,U8 sortType)
00043 {
00044     U8    i;  
00045     P_ECB pecb;
00046 
00047 #if CFG_PAR_CHECKOUT_EN >0  
00048     if((qStart == 0) || (size == 0))    
00049     {
00050         return E_CREATE_FAIL;
00051     }
00052 #endif
00053 
00054     OsSchedLock();
00055     for(i = 0; i < CFG_MAX_QUEUE; i++)
00056     {
00057         /* Assign a free QUEUE control block                                  */
00058         if((QueueIDVessel  & (1 << i)) == 0) 
00059         {
00060             QueueIDVessel  |= (1<<i);        
00061             OsSchedUnlock();
00062             
00063             QueueTbl[i].qStart    = qStart;  /* Initialize the queue           */
00064             QueueTbl[i].id        = i;
00065             QueueTbl[i].head      = 0;
00066             QueueTbl[i].tail      = 0;
00067             QueueTbl[i].qMaxSize  = size; 
00068             QueueTbl[i].qSize     = 0;
00069             
00070             /* Get a event control block and initial the event content        */
00071             pecb = CreatEvent(EVENT_TYPE_QUEUE,sortType,&QueueTbl[i]);
00072             
00073             if(pecb == 0 )       /* If there is no free EVENT control block*/
00074             {
00075                 return E_CREATE_FAIL;
00076             }
00077             return (pecb->id );      
00078         }
00079     }
00080     
00081     OsSchedUnlock();
00082     return E_CREATE_FAIL;             /* There is no free QUEUE control block */    
00083 }
00084 
00085 
00086 /**
00087  *******************************************************************************
00088  * @brief      Delete a queue     
00089  * @param[in]  id     Event ID.     
00090  * @param[in]  opt    Delete option.     
00091  * @param[out] None   
00092  * @retval     E_INVALID_ID         Invalid event ID.
00093  * @retval     E_INVALID_PARAMETER  Invalid parameter.
00094  * @retval     E_TASK_WAITTING      Tasks waitting for the event,delete fail.
00095  * @retval     E_OK                 Event deleted successful. 
00096  *
00097  * @par Description
00098  * @details    This function is called to delete a queue. 
00099  * @note 
00100  *******************************************************************************
00101  */
00102 StatusType CoDelQueue(OS_EventID id,U8 opt)
00103 {
00104     P_ECB   pecb;
00105     P_QCB   pqcb;
00106     StatusType err;
00107 #if CFG_PAR_CHECKOUT_EN >0      
00108     if(id >= CFG_MAX_EVENT)                      
00109     {
00110         return E_INVALID_ID;            /* Invalid id,return error            */
00111     }
00112 #endif
00113 
00114     pecb = &EventTbl [id];
00115 #if CFG_PAR_CHECKOUT_EN >0
00116     if( pecb->eventType  != EVENT_TYPE_QUEUE)
00117     {
00118         return E_INVALID_ID;            /* The event is not queue,return error*/    
00119     }
00120 #endif
00121     pqcb = (P_QCB)pecb->eventPtr ;       /* Point at queue control block       */
00122     err  = DeleteEvent(pecb,opt);       /* Delete the event control block     */
00123     if(err == E_OK)                   /* If the event block have been deleted */
00124     {
00125         QueueIDVessel  &= ~((U32)(1<<(pqcb->id )));   /* Update free queue list             */
00126         pqcb->qStart    = 0;
00127             pqcb->id        = 0;
00128         pqcb->head      = 0;
00129         pqcb->tail      = 0;
00130         pqcb->qMaxSize  = 0;
00131         pqcb->qSize     = 0;
00132     }
00133     return err; 
00134 }
00135 
00136 
00137  
00138 /**
00139  *******************************************************************************
00140  * @brief      Accept a mail from queue   
00141  * @param[in]  id     Event ID.      
00142  * @param[out] perr   A pointer to error code.  
00143  * @retval     0    
00144  * @retval     A pointer to mail accepted.
00145  *
00146  * @par Description
00147  * @details    This function is called to accept a mail from queue.
00148  * @note 
00149  *******************************************************************************
00150  */
00151 void* CoAcceptQueueMail(OS_EventID id,StatusType* perr)
00152 {
00153   P_ECB pecb;
00154   P_QCB pqcb;
00155   void* pmail;
00156 #if CFG_PAR_CHECKOUT_EN >0
00157     if(id >= CFG_MAX_EVENT)             
00158     {
00159         *perr = E_INVALID_ID;           /* Invalid id,return error            */
00160         return 0;
00161     }
00162 #endif
00163 
00164     pecb = &EventTbl [id];
00165 #if CFG_PAR_CHECKOUT_EN >0
00166     if(pecb->eventType  != EVENT_TYPE_QUEUE)/* Invalid event control block type*/                
00167     {
00168         *perr = E_INVALID_ID;
00169         return 0;   
00170     }
00171 #endif  
00172     pqcb = (P_QCB)pecb->eventPtr ;       /* Point at queue control block       */
00173     OsSchedLock();
00174     if(pqcb->qSize  != 0)            /* If there are any messages in the queue */
00175     {
00176         /* Extract oldest message from the queue */
00177         pmail = *(pqcb->qStart  + pqcb->head );  
00178         pqcb->head ++;                   /* Update the queue head              */ 
00179         pqcb->qSize --;          /* Update the number of messages in the queue */  
00180         if(pqcb->head  == pqcb->qMaxSize )
00181         {
00182             pqcb->head  = 0; 
00183         }
00184         OsSchedUnlock();
00185         *perr = E_OK;
00186         return pmail;                   /* Return message received            */
00187     }
00188     else                                /* If there is no message in the queue*/
00189     {
00190         OsSchedUnlock();
00191         *perr = E_QUEUE_EMPTY;                 
00192         return 0;                    /* Return 0                        */ 
00193     }   
00194 }
00195 
00196 
00197 
00198 /**
00199  *******************************************************************************
00200  * @brief      Pend for a mail   
00201  * @param[in]  id       Event ID.    
00202  * @param[in]  timeout  The longest time for writting mail. 
00203  * @param[out] perr     A pointer to error code.   
00204  * @retval     0    
00205  * @retval     A pointer to mail accept.     
00206  *
00207  * @par Description
00208  * @details    This function is called to wait for a mail.          
00209  * @note 
00210  *******************************************************************************
00211  */
00212 void* CoPendQueueMail(OS_EventID id,U32 timeout,StatusType* perr)
00213 {
00214     P_ECB   pecb;
00215     P_QCB   pqcb;
00216     P_OSTCB curTCB;
00217     void*   pmail;
00218     if(OSIntNesting  > 0)                /* If the caller is ISR               */
00219     {
00220         *perr = E_CALL;
00221         return 0;
00222     }
00223 #if CFG_PAR_CHECKOUT_EN >0
00224     if(id >= CFG_MAX_EVENT)          
00225     {
00226         *perr = E_INVALID_ID;           /* Invalid event id,return error      */
00227         return 0;
00228     }
00229 #endif
00230 
00231     pecb = &EventTbl [id];
00232 #if CFG_PAR_CHECKOUT_EN >0
00233     if(pecb->eventType  != EVENT_TYPE_QUEUE) /* The event type is not queue    */
00234     {
00235         *perr = E_INVALID_ID;
00236         return 0;   
00237     }
00238 #endif  
00239     if(OSSchedLock  != 0)                /* Judge schedule is locked or not?   */
00240     {   
00241         *perr = E_OS_IN_LOCK;           /* Schedule is locked,return error    */                                 
00242         return 0;          
00243     }   
00244     pqcb = (P_QCB)pecb->eventPtr ;       /* Point at queue control block       */
00245      
00246     if(pqcb->qSize  != 0)            /* If there are any messages in the queue */
00247     {
00248         /* Extract oldest message from the queue                              */
00249         pmail = *(pqcb->qStart  + pqcb->head );   
00250         pqcb->head ++;                   /* Update the queue head              */ 
00251         pqcb->qSize --;          /* Update the number of messages in the queue */  
00252         if(pqcb->head  == pqcb->qMaxSize )/* Check queue head                   */
00253         {
00254             pqcb->head  = 0; 
00255         }
00256         *perr = E_OK;
00257         return pmail;                   /* Return message received            */
00258     }
00259     else                                /* If there is no message in the queue*/
00260     {
00261         curTCB = TCBRunning ;
00262         if(timeout == 0)                /* If time-out is not configured      */
00263         {
00264             /* Block current task until the event occur                       */
00265             EventTaskToWait(pecb,curTCB); 
00266             
00267             /* Have recived message or the queue have been deleted            */
00268             pmail = curTCB->pmail ;              
00269             curTCB->pmail  = 0;
00270             *perr = E_OK;
00271             return pmail;               /* Return message received or 0    */
00272         }
00273         else                            /* If time-out is configured          */
00274         {
00275             OsSchedLock(); 
00276             
00277             /* Block current task until event or timeout occurs               */           
00278             EventTaskToWait(pecb,curTCB);       
00279             InsertDelayList(curTCB,timeout);
00280             OsSchedUnlock();
00281             if(curTCB->pmail  == 0)   /* If time-out occurred               */
00282             {
00283                 *perr = E_TIMEOUT;
00284                 return 0;
00285             }
00286             else                        /* If event occured                   */
00287             {
00288                 pmail = curTCB->pmail ;
00289                 curTCB->pmail  = 0;
00290                 *perr = E_OK;
00291                 return pmail;           /* Return message received or 0    */
00292             }               
00293         }   
00294     }
00295 }
00296 
00297 
00298  
00299 /**
00300  *******************************************************************************
00301  * @brief      Post a mail to queue    
00302  * @param[in]  id      Event ID.
00303  * @param[in]  pmail   Pointer to mail that want to send.        
00304  * @param[out] None   
00305  * @retval     E_OK
00306  * @retval     E_INVALID_ID
00307  * @retval     E_QUEUE_FULL      
00308  *
00309  * @par Description
00310  * @details    This function is called to post a mail to queue.
00311  * @note 
00312  *******************************************************************************
00313  */
00314 StatusType CoPostQueueMail(OS_EventID id,void* pmail)
00315 {   
00316     P_ECB pecb;
00317     P_QCB pqcb;
00318 #if CFG_PAR_CHECKOUT_EN >0                     
00319     if(id >= CFG_MAX_EVENT) 
00320     {
00321         return E_INVALID_ID;          
00322     }
00323 #endif
00324 
00325     pecb = &EventTbl [id];
00326 #if CFG_PAR_CHECKOUT_EN >0
00327     if(pecb->eventType  != EVENT_TYPE_QUEUE)   
00328     {
00329         return E_INVALID_ID;            /* The event type isn't queue,return  */    
00330     }   
00331 #endif
00332     pqcb = (P_QCB)pecb->eventPtr ;   
00333     if(pqcb->qSize  == pqcb->qMaxSize )   /* If queue is full                   */
00334     {
00335         return E_QUEUE_FULL;
00336     }
00337     else                                /* If queue is not full               */
00338     {
00339         OsSchedLock();
00340         *(pqcb->qStart  + pqcb->tail ) = pmail;   /* Insert message into queue  */
00341         pqcb->tail ++;                           /* Update queue tail          */
00342         pqcb->qSize ++;          /* Update the number of messages in the queue */
00343         if(pqcb->tail  == pqcb->qMaxSize )        /* Check queue tail           */   
00344         {
00345             pqcb->tail  = 0; 
00346         }
00347         EventTaskToRdy(pecb);           /* Check the event waiting list       */
00348         OsSchedUnlock();
00349         return E_OK;
00350     }
00351 }
00352 
00353 
00354 /**
00355  *******************************************************************************
00356  * @brief      Post a mail to queue in ISR   
00357  * @param[in]  id      Event ID.
00358  * @param[in]  pmail   Pointer to mail that want to send.        
00359  * @param[out] None   
00360  * @retval     E_OK
00361  * @retval     E_INVALID_ID
00362  * @retval     E_QUEUE_FULL      
00363  *
00364  * @par Description
00365  * @details    This function is called in ISR to post a mail to queue.
00366  * @note                   
00367  *******************************************************************************
00368  */
00369 #if CFG_MAX_SERVICE_REQUEST > 0
00370 StatusType isr_PostQueueMail(OS_EventID id,void* pmail)
00371 {
00372     if(OSSchedLock  > 0)         /* If scheduler is locked,(the caller is ISR) */
00373     {
00374         /* Insert the request into service request queue                      */
00375         if(InsertInSRQ(QUEUE_REQ,id,pmail) == FALSE)   
00376         {
00377             return E_SEV_REQ_FULL;      /* If service request queue is full   */          
00378         }           
00379         else  /* If the request have been inserted into service request queue */
00380         {
00381             return E_OK;
00382         }
00383     }
00384     else                                /* The scheduler is unlocked          */
00385     {
00386         return(CoPostQueueMail(id,pmail));    /* Send the message to the queue*/ 
00387     }
00388 }
00389 #endif
00390                                  
00391 #endif