Published 03 Dec 2010, by
Eric Ebert
CoOS,
rtos
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <coocox.h>
00019
00020
00021 #if CFG_KHEAP_EN >0
00022
00023 U32 KernelHeap[KHEAP_SIZE] = {0};
00024 P_FMB FMBlist = 0;
00025 KHeap Kheap = {0};
00026
00027
00028
00029 static P_FMB GetPreFMB(P_UMB usedMB);
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 void CoCreateKheap(void)
00042 {
00043 Kheap.startAddr = (U32)(KernelHeap);
00044 Kheap.endAddr = (U32)(KernelHeap) + KHEAP_SIZE*4;
00045 FMBlist = (P_FMB)KernelHeap;
00046 FMBlist->nextFMB = 0;
00047 FMBlist->nextUMB = 0;
00048 FMBlist->preUMB = 0;
00049 }
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
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
00073 if( size == 0 )
00074 {
00075 return 0;
00076 }
00077 #endif
00078
00079
00080 size = (((size+3)>>2)<<2) + 8;
00081 kheapAddr = Kheap.endAddr;
00082 OsSchedLock ();
00083 freeMB = FMBlist;
00084 preFMB = 0;
00085 while(freeMB != 0 )
00086 {
00087 if(freeMB->nextUMB == 0)
00088 {
00089 freeSize = kheapAddr - (U32)(freeMB);
00090 }
00091 else
00092 {
00093 freeSize = (U32)(freeMB->nextUMB) -1 - (U32)(freeMB);
00094 }
00095 if(freeSize >= size)
00096 {
00097 usedMB=(P_UMB)freeMB;
00098
00099
00100 memAddr = (U8*)((U32)(usedMB) + 8);
00101
00102
00103 if((freeSize-size) < 12)
00104 {
00105
00106
00107 if(preFMB != 0)
00108 {
00109 preFMB->nextFMB = freeMB->nextFMB;
00110 }
00111 else
00112 {
00113 FMBlist = freeMB->nextFMB;
00114 }
00115
00116 if(freeMB->nextUMB != 0)
00117 {
00118 tmpUMB = (P_UMB)((U32)(freeMB->nextUMB)-1);
00119 tmpUMB->preMB = (void*)((U32)usedMB|0x1);
00120 }
00121
00122 usedMB->nextMB = freeMB->nextUMB;
00123 usedMB->preMB = freeMB->preUMB;
00124 }
00125 else
00126 {
00127
00128 newFMB = (P_FMB)((U32)(freeMB) + size);
00129
00130 if(preFMB != 0)
00131 {
00132 preFMB->nextFMB = newFMB;
00133 }
00134 else
00135 {
00136 FMBlist = newFMB;
00137 }
00138
00139
00140 newFMB->preUMB = (P_UMB)((U32)usedMB|0x1);
00141 newFMB->nextUMB = freeMB->nextUMB;
00142 newFMB->nextFMB = freeMB->nextFMB;
00143
00144 if(freeMB->nextUMB != 0)
00145 {
00146 tmpUMB = (P_UMB)((U32)(freeMB->nextUMB)-1);
00147 tmpUMB->preMB = newFMB;
00148 }
00149
00150 usedMB->nextMB = newFMB;
00151 usedMB->preMB = freeMB->preUMB;
00152 }
00153
00154 if(freeMB->preUMB != 0)
00155 {
00156 tmpUMB = (P_UMB)((U32)(freeMB->preUMB)-1);
00157 tmpUMB->nextMB = (void*)((U32)usedMB|0x1);
00158 }
00159
00160 OsSchedUnlock();
00161 return memAddr;
00162 }
00163 preFMB = freeMB;
00164 freeMB = freeMB->nextFMB;
00165 }
00166 OsSchedUnlock();
00167 return 0;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
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
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
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 ();
00209
00210 #if CFG_PAR_CHECKOUT_EN >0
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
00264 if( (((U32)(usedMB->nextMB)&0x1) == 0) && (((U32)(usedMB->preMB)&0x1)==0) )
00265 {
00266 if((usedMB->nextMB == 0) && (usedMB->preMB == 0))
00267 {
00268 curFMB = (P_FMB)usedMB;
00269 curFMB->nextFMB = 0;
00270 curFMB->nextUMB = 0;
00271 curFMB->preUMB = 0;
00272 FMBlist = curFMB;
00273 }
00274 else if(usedMB->preMB == 0)
00275 {
00276
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)
00286 {
00287 curFMB = (P_FMB)(usedMB->preMB);
00288 curFMB->nextFMB = 0;
00289 curFMB->nextUMB = 0;
00290 }
00291 else
00292 {
00293
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)
00302 {
00303 if(usedMB->preMB == 0)
00304 {
00305
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
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)
00322 {
00323 preUMB = (P_UMB)(usedMB->preMB);
00324 curFMB = (P_FMB)(usedMB);
00325 preFMB = GetPreFMB(usedMB);
00326 if(preFMB == 0)
00327 {
00328 nextFMB = FMBlist;
00329 FMBlist = curFMB;
00330 }
00331 else
00332 {
00333 nextFMB = preFMB->nextFMB;
00334 preFMB->nextFMB = curFMB;
00335 }
00336
00337 if(nextFMB == 0)
00338 {
00339 curFMB->preUMB = preUMB;
00340 curFMB->nextUMB = 0;
00341 curFMB->nextFMB = 0;
00342 }
00343 else
00344 {
00345 curFMB->preUMB = preUMB;
00346 curFMB->nextUMB = nextFMB->nextUMB;
00347 curFMB->nextFMB = nextFMB->nextFMB;
00348 }
00349 }
00350 else
00351 {
00352 curFMB = (P_FMB)(usedMB);
00353 preFMB = GetPreFMB(usedMB);
00354 preUMB = (P_UMB)(usedMB->preMB);
00355 nextUMB = (P_UMB)(usedMB->nextMB);
00356
00357 if(preFMB == 0 )
00358 {
00359 nextFMB = FMBlist;
00360 FMBlist = curFMB;
00361 }
00362 else
00363 {
00364 nextFMB = preFMB->nextFMB;
00365 preFMB->nextFMB = curFMB;
00366 }
00367
00368 curFMB->preUMB = preUMB;
00369 curFMB->nextUMB = nextUMB;
00370 curFMB->nextFMB = nextFMB;
00371 }
00372
00373 if(curFMB->preUMB != 0)
00374 {
00375 preUMB = (P_UMB)((U32)(curFMB->preUMB)-1);
00376 preUMB->nextMB = (void*)curFMB;
00377 }
00378 if(curFMB->nextUMB != 0)
00379 {
00380 nextUMB = (P_UMB)((U32)(curFMB->nextUMB)-1);
00381 nextUMB->preMB = (void*)curFMB;
00382 }
00383 OsSchedUnlock();
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 static P_FMB GetPreFMB(P_UMB usedMB)
00399 {
00400 P_UMB preUMB;
00401 preUMB = usedMB;
00402 while(((U32)(preUMB->preMB)&0x1))
00403 {
00404 preUMB = (P_UMB)((U32)(preUMB->preMB)-1);
00405 }
00406 return (P_FMB)(preUMB->preMB);
00407 }
00408
00409 #endif