Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
queue.c
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>© 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
Generated on Tue Jul 12 2022 15:09:51 by
1.7.2