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.
mutex.c
00001 /** 00002 ******************************************************************************* 00003 * @file mutex.c 00004 * @version V1.1.3 00005 * @date 2010.04.26 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 = 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 15:09:51 by
1.7.2