electronix79
/
CoOS_mbed
CooCox 1.1.4 on mbed with simple blinky example
Embed:
(wiki syntax)
Show/hide line numbers
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>© 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
Generated on Tue Jul 12 2022 18:19:10 by 1.7.2