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.
kernelHeap.c
00001 /** 00002 ******************************************************************************* 00003 * @file kernelHeap.c 00004 * @version V1.1.3 00005 * @date 2010.04.26 00006 * @brief kernel heap 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 /*---------------------------- Include ---------------------------------------*/ 00018 #include <coocox.h> 00019 00020 00021 #if CFG_KHEAP_EN >0 00022 /*---------------------------- Variable Define -------------------------------*/ 00023 U32 KernelHeap [KHEAP_SIZE] = {0}; /*!< Kernel heap */ 00024 P_FMB FMBlist = 0; /*!< Free memory block list */ 00025 KHeap Kheap = {0}; /*!< Kernel heap control */ 00026 00027 00028 /*---------------------------- Function Declare ------------------------------*/ 00029 static P_FMB GetPreFMB(P_UMB usedMB); 00030 /** 00031 ******************************************************************************* 00032 * @brief Create kernel heap 00033 * @param[in] None 00034 * @param[out] None 00035 * @retval None 00036 * 00037 * @par Description 00038 * @details This function is called to create kernel heap. 00039 ******************************************************************************* 00040 */ 00041 void CoCreateKheap(void) 00042 { 00043 Kheap .startAddr = (U32)(KernelHeap ); /* Initialize kernel heap control */ 00044 Kheap .endAddr = (U32)(KernelHeap ) + KHEAP_SIZE*4; 00045 FMBlist = (P_FMB)KernelHeap ; /* Initialize free memory block list*/ 00046 FMBlist ->nextFMB = 0; 00047 FMBlist ->nextUMB = 0; 00048 FMBlist ->preUMB = 0; 00049 } 00050 00051 00052 /** 00053 ******************************************************************************* 00054 * @brief Allocation size bytes of memory block from kernel heap. 00055 * @param[in] size Length of menory block. 00056 * @param[out] None 00057 * @retval 0 Allocate fail. 00058 * @retval others Pointer to memory block. 00059 * 00060 * @par Description 00061 * @details This function is called to allocation size bytes of memory block. 00062 ******************************************************************************* 00063 */ 00064 void* CoKmalloc(U32 size) 00065 { 00066 P_FMB freeMB,newFMB,preFMB; 00067 P_UMB usedMB,tmpUMB; 00068 U8* memAddr; 00069 U32 freeSize; 00070 U32 kheapAddr; 00071 00072 #if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */ 00073 if( size == 0 ) 00074 { 00075 return 0; 00076 } 00077 #endif 00078 00079 /* Word alignment,and add used memory head size */ 00080 size = (((size+3)>>2)<<2) + 8; 00081 kheapAddr = Kheap .endAddr; /* Get the end address of kernel heap */ 00082 OsSchedLock(); /* Lock schedule */ 00083 freeMB = FMBlist ; /* Get first item of free memory list */ 00084 preFMB = 0; 00085 while(freeMB != 0 ) /* Is out of free memory list? */ 00086 { /* No */ 00087 if(freeMB->nextUMB == 0) /* Is last item of free memory list? */ 00088 { /* Yes,get size for this free item */ 00089 freeSize = kheapAddr - (U32)(freeMB); 00090 } 00091 else /* No,get size for this free item */ 00092 { 00093 freeSize = (U32)(freeMB->nextUMB) -1 - (U32)(freeMB); 00094 } 00095 if(freeSize >= size) /* If the size equal or greater than need */ 00096 { /* Yes,assign in this free memory */ 00097 usedMB=(P_UMB)freeMB;/* Get the address for used memory block head*/ 00098 00099 /* Get the address for used memory block */ 00100 memAddr = (U8*)((U32)(usedMB) + 8); 00101 00102 /* Is left size of free memory smaller than 12? */ 00103 if((freeSize-size) < 12) 00104 { 00105 /* Yes,malloc together(12 is the size of the header information 00106 of free memory block ). */ 00107 if(preFMB != 0)/* Is first item of free memory block list? */ 00108 { /* No,set the link for list */ 00109 preFMB->nextFMB = freeMB->nextFMB; 00110 } 00111 else /* Yes,reset the first item */ 00112 { 00113 FMBlist = freeMB->nextFMB; 00114 } 00115 00116 if(freeMB->nextUMB != 0) /* Is last item? */ 00117 { /* No,set the link for list */ 00118 tmpUMB = (P_UMB)((U32)(freeMB->nextUMB)-1); 00119 tmpUMB->preMB = (void*)((U32)usedMB|0x1); 00120 } 00121 00122 usedMB->nextMB = freeMB->nextUMB;/* Set used memory block link*/ 00123 usedMB->preMB = freeMB->preUMB; 00124 } 00125 else /* No,the left size more than 12 */ 00126 { 00127 /* Get new free memory block address */ 00128 newFMB = (P_FMB)((U32)(freeMB) + size); 00129 00130 if(preFMB != 0)/* Is first item of free memory block list? */ 00131 { 00132 preFMB->nextFMB = newFMB; /* No,set the link for list */ 00133 } 00134 else 00135 { 00136 FMBlist = newFMB; /* Yes,reset the first item */ 00137 } 00138 00139 /* Set link for new free memory block */ 00140 newFMB->preUMB = (P_UMB)((U32)usedMB|0x1); 00141 newFMB->nextUMB = freeMB->nextUMB; 00142 newFMB->nextFMB = freeMB->nextFMB; 00143 00144 if(freeMB->nextUMB != 0) /* Is last item? */ 00145 { /* No,set the link for list */ 00146 tmpUMB = (P_UMB)((U32)(freeMB->nextUMB)-1); 00147 tmpUMB->preMB = newFMB; 00148 } 00149 00150 usedMB->nextMB = newFMB; /* Set used memory block link */ 00151 usedMB->preMB = freeMB->preUMB; 00152 } 00153 00154 if(freeMB->preUMB != 0) /* Is first item? */ 00155 { /* No,set the link for list */ 00156 tmpUMB = (P_UMB)((U32)(freeMB->preUMB)-1); 00157 tmpUMB->nextMB = (void*)((U32)usedMB|0x1); 00158 } 00159 00160 OsSchedUnlock(); /* Unlock schedule */ 00161 return memAddr; /* Return used memory block address */ 00162 } 00163 preFMB = freeMB; /* Save current free memory block as previous */ 00164 freeMB = freeMB->nextFMB; /* Get the next item as current item*/ 00165 } 00166 OsSchedUnlock(); /* Unlock schedule */ 00167 return 0; /* Error return */ 00168 } 00169 00170 00171 /** 00172 ******************************************************************************* 00173 * @brief Release memory block to kernel heap. 00174 * @param[in] memBuf Pointer to memory block. 00175 * @param[out] None 00176 * @retval None 00177 * 00178 * @par Description 00179 * @details This function is called to release memory block. 00180 ******************************************************************************* 00181 */ 00182 void CoKfree(void* memBuf) 00183 { 00184 P_FMB curFMB,nextFMB,preFMB; 00185 P_UMB usedMB,nextUMB,preUMB; 00186 00187 #if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */ 00188 if(memBuf == 0) 00189 { 00190 return; 00191 } 00192 #endif 00193 00194 usedMB = (P_UMB)((U32)(memBuf)-8); 00195 00196 #if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */ 00197 if((U32)(memBuf) < Kheap .startAddr) 00198 { 00199 return; 00200 } 00201 if((U32)(memBuf) > Kheap .endAddr) 00202 { 00203 return; 00204 } 00205 #endif 00206 00207 00208 OsSchedLock(); /* Lock schedule */ 00209 00210 #if CFG_PAR_CHECKOUT_EN >0 /* Check UMB in list */ 00211 if((U32)(usedMB) < (U32)(FMBlist )) 00212 { 00213 preUMB = (P_UMB)((U32)(FMBlist ->preUMB)-1); 00214 while(preUMB != usedMB) 00215 { 00216 if(preUMB == 0) 00217 { 00218 OsSchedUnlock(); 00219 return; 00220 } 00221 preUMB = (P_UMB)((U32)(preUMB->preMB)-1); 00222 } 00223 } 00224 else 00225 { 00226 if(FMBlist == 0) 00227 { 00228 nextUMB = (P_UMB)(Kheap .startAddr); 00229 } 00230 else 00231 { 00232 if(FMBlist ->nextUMB != 0) 00233 { 00234 nextUMB = (P_UMB)((U32)(FMBlist ->nextUMB)-1); 00235 } 00236 else 00237 { 00238 nextUMB = 0; 00239 } 00240 } 00241 00242 while(nextUMB != usedMB) 00243 { 00244 if(nextUMB == 0) 00245 { 00246 OsSchedUnlock(); 00247 return; 00248 } 00249 if(((U32)(nextUMB->nextMB)&0x1) == 0) 00250 { 00251 nextFMB = (P_FMB)(nextUMB->nextMB); 00252 nextUMB = (P_UMB)((U32)(nextFMB->nextUMB)-1); 00253 } 00254 else 00255 { 00256 nextUMB = (P_UMB)((U32)(nextUMB->nextMB)-1); 00257 } 00258 } 00259 } 00260 #endif 00261 00262 00263 /* Is between two free memory block? */ 00264 if( (((U32)(usedMB->nextMB)&0x1) == 0) && (((U32)(usedMB->preMB)&0x1)==0) ) 00265 { /* Yes,is the only one item in kernel heap? */ 00266 if((usedMB->nextMB == 0) && (usedMB->preMB == 0)) 00267 { 00268 curFMB = (P_FMB)usedMB; /* Yes,release this item */ 00269 curFMB->nextFMB = 0; 00270 curFMB->nextUMB = 0; 00271 curFMB->preUMB = 0; 00272 FMBlist = curFMB; 00273 } 00274 else if(usedMB->preMB == 0) /* Is the first item in kernel heap */ 00275 { 00276 /* Yes,release this item,and set link for list */ 00277 curFMB = (P_FMB)usedMB; 00278 nextFMB = (P_FMB)usedMB->nextMB; 00279 00280 curFMB->nextFMB = nextFMB->nextFMB; 00281 curFMB->nextUMB = nextFMB->nextUMB; 00282 curFMB->preUMB = 0; 00283 FMBlist = curFMB; 00284 } 00285 else if(usedMB->nextMB == 0) /* Is the last item in kernel heap */ 00286 { /* Yes,release this item,and set link for list */ 00287 curFMB = (P_FMB)(usedMB->preMB); 00288 curFMB->nextFMB = 0; 00289 curFMB->nextUMB = 0; 00290 } 00291 else /* All no,show this item between two normal FMB */ 00292 { 00293 /* release this item,and set link for list */ 00294 nextFMB = (P_FMB)usedMB->nextMB; 00295 curFMB = (P_FMB)(usedMB->preMB); 00296 00297 curFMB->nextFMB = nextFMB->nextFMB; 00298 curFMB->nextUMB = nextFMB->nextUMB; 00299 } 00300 } 00301 else if(((U32)(usedMB->preMB)&0x1) == 0) /* Is between FMB and UMB? */ 00302 { 00303 if(usedMB->preMB == 0) /* Yes,is the first item in kernel heap? */ 00304 { 00305 /* Yes,release this item,and set link for list */ 00306 curFMB = (P_FMB)usedMB; 00307 nextUMB = (P_UMB)usedMB->nextMB; 00308 curFMB->nextUMB = nextUMB; 00309 curFMB->preUMB = 0; 00310 curFMB->nextFMB = FMBlist ; 00311 FMBlist = curFMB; 00312 } 00313 else /* No,release this item,and set link for list */ 00314 { 00315 curFMB = (P_FMB)usedMB->preMB; 00316 nextUMB = (P_UMB)usedMB->nextMB; 00317 curFMB->nextUMB = nextUMB; 00318 } 00319 00320 } 00321 else if(((U32)(usedMB->nextMB)&0x1) == 0) /* Is between UMB and FMB? */ 00322 { /* Yes */ 00323 preUMB = (P_UMB)(usedMB->preMB); /* Get previous UMB */ 00324 curFMB = (P_FMB)(usedMB); /* new FMB */ 00325 preFMB = GetPreFMB(usedMB); /* Get previous FMB */ 00326 if(preFMB == 0) /* Is previous FMB==0? */ 00327 { 00328 nextFMB = FMBlist ; /* Yes,get next FMB */ 00329 FMBlist = curFMB; /* Reset new FMB as the first item of FMB list*/ 00330 } 00331 else 00332 { 00333 nextFMB = preFMB->nextFMB; /* No,get next FMB */ 00334 preFMB->nextFMB = curFMB; /* Set link for FMB list */ 00335 } 00336 00337 if(nextFMB == 0) /* Is new FMB as last item of FMB list? */ 00338 { 00339 curFMB->preUMB = preUMB; /* Yes,set link for list */ 00340 curFMB->nextUMB = 0; 00341 curFMB->nextFMB = 0; 00342 } 00343 else 00344 { 00345 curFMB->preUMB = preUMB; /* No,set link for list */ 00346 curFMB->nextUMB = nextFMB->nextUMB; 00347 curFMB->nextFMB = nextFMB->nextFMB; 00348 } 00349 } 00350 else /* All no,show UMB between two UMB*/ 00351 { 00352 curFMB = (P_FMB)(usedMB); /* new FMB */ 00353 preFMB = GetPreFMB(usedMB); /* Get previous FMB */ 00354 preUMB = (P_UMB)(usedMB->preMB); /* Get previous UMB */ 00355 nextUMB = (P_UMB)(usedMB->nextMB); /* Get next UMB */ 00356 00357 if(preFMB == 0 ) /* Is previous FMB==0? */ 00358 { 00359 nextFMB = FMBlist ; /* Yes,get next FMB */ 00360 FMBlist = curFMB; /* Reset new FMB as the first item of FMB list */ 00361 } 00362 else 00363 { 00364 nextFMB = preFMB->nextFMB; /* No,get next FMB */ 00365 preFMB->nextFMB = curFMB; /* Set link for FMB list */ 00366 } 00367 00368 curFMB->preUMB = preUMB; /* Set current FMB link for list */ 00369 curFMB->nextUMB = nextUMB; 00370 curFMB->nextFMB = nextFMB; 00371 } 00372 00373 if(curFMB->preUMB != 0)/* Is current FMB as first item in kernel heap? */ 00374 { /* No,set link for list */ 00375 preUMB = (P_UMB)((U32)(curFMB->preUMB)-1); 00376 preUMB->nextMB = (void*)curFMB; 00377 } 00378 if(curFMB->nextUMB != 0)/* Is current FMB as last item in kernel heap? */ 00379 { /* No,set link for list */ 00380 nextUMB = (P_UMB)((U32)(curFMB->nextUMB)-1); 00381 nextUMB->preMB = (void*)curFMB; 00382 } 00383 OsSchedUnlock(); /* Unlock schedule */ 00384 } 00385 00386 00387 /** 00388 ******************************************************************************* 00389 * @brief Get previous free memory block pointer. 00390 * @param[in] usedMB Current used memory block. 00391 * @param[out] None 00392 * @retval Previous free memory block pointer. 00393 * 00394 * @par Description 00395 * @details This function is called to get previous free memory block pointer. 00396 ******************************************************************************* 00397 */ 00398 static P_FMB GetPreFMB(P_UMB usedMB) 00399 { 00400 P_UMB preUMB; 00401 preUMB = usedMB; 00402 while(((U32)(preUMB->preMB)&0x1)) /* Is previous MB as FMB? */ 00403 { /* No,get previous MB */ 00404 preUMB = (P_UMB)((U32)(preUMB->preMB)-1); 00405 } 00406 return (P_FMB)(preUMB->preMB); /* Yes,return previous MB */ 00407 } 00408 00409 #endif
Generated on Tue Jul 12 2022 15:09:51 by
1.7.2