00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00110
00111 #include <cfg/os.h>
00112 #include <compiler.h>
00113 #include <string.h>
00114
00115 #include <sys/atom.h>
00116 #include <sys/heap.h>
00117
00118 #ifdef NUTDEBUG
00119 #include <sys/osdebug.h>
00120 #endif
00121
00122 #if defined(__arm__) || defined(__m68k__) || defined(__H8300H__) || defined(__H8300S__) || defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00123 #define ARCH_32BIT
00124 #endif
00125
00129 HEAPNODE *volatile heapFreeList;
00130
00134 static size_t available;
00135
00140
00141 #define MEMOVHD (sizeof(size_t) + sizeof(0xDEADBEEF))
00142
00174 void *NutHeapAlloc(size_t size)
00175 {
00176 HEAPNODE *node;
00177 HEAPNODE **npp;
00178 HEAPNODE *fit = 0;
00179 HEAPNODE **fpp = 0;
00180
00181 #if defined(__arm__) || defined(__m68k__) || defined(__H8300H__) || defined(__H8300S__) || defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00182
00183
00184
00185 while ((size & 0x03) != 0)
00186 size++;
00187 #endif
00188
00189 if (size >= available) {
00190 #ifdef NUTDEBUG
00191 if (__heap_trf)
00192 fputs("MEMOVR\n", __heap_trs);
00193 #endif
00194 return 0;
00195 }
00196
00197
00198
00199
00200
00201
00202 if ((size += MEMOVHD) < sizeof(HEAPNODE))
00203 size = sizeof(HEAPNODE);
00204
00205
00206
00207
00208 node = heapFreeList;
00209 npp = (HEAPNODE **) & heapFreeList;
00210 while (node) {
00211
00212
00213
00214
00215 if (node->hn_size >= size) {
00216
00217
00218
00219
00220 if (node->hn_size == size) {
00221 fit = node;
00222 fpp = npp;
00223 break;
00224 }
00225
00226
00227
00228
00229
00230 if (fit == 0 || (fit->hn_size > node->hn_size)) {
00231 fit = node;
00232 fpp = npp;
00233 }
00234 }
00235 npp = &node->hn_next;
00236 node = node->hn_next;
00237 }
00238
00239 if (fit) {
00240
00241
00242
00243
00244
00245
00246 if (fit->hn_size > size + sizeof(HEAPNODE) + ALLOC_THRESHOLD) {
00247 node = (HEAPNODE *) ((uptr_t) fit + size);
00248 node->hn_size = fit->hn_size - size;
00249 node->hn_next = fit->hn_next;
00250 fit->hn_size = size;
00251 *fpp = node;
00252 } else
00253 *fpp = fit->hn_next;
00254
00255 available -= fit->hn_size;
00256 *((u_long *) (((char *) fit) + (fit->hn_size - 4))) = 0xDEADBEEF;
00257 fit = (HEAPNODE *) & fit->hn_next;
00258 }
00259 #ifdef NUTDEBUG
00260 if (__heap_trf) {
00261 fprintf(__heap_trs, "\n[H%x,A%d/%d] ", (u_int)(uptr_t) fit, (int)(((HEAPNODE *) (((uptr_t *) fit) - 1))->hn_size), (int)size);
00262 }
00263 #endif
00264 return fit;
00265 }
00266
00280 void *NutHeapAllocClear(size_t size)
00281 {
00282 void *ptr;
00283
00284 if ((ptr = NutHeapAlloc(size)) != 0)
00285 memset(ptr, 0, size);
00286
00287 return ptr;
00288 }
00289
00308 int NutHeapFree(void *block)
00309 {
00310 HEAPNODE *node;
00311 HEAPNODE **npp;
00312 HEAPNODE *fnode;
00313 size_t size;
00314
00315 #ifdef NUTDEBUG
00316 if (__heap_trf) {
00317 if (block) {
00318 size_t size;
00319 size = *(((uptr_t *) block) - 1);
00320 if (*((u_long *) (((char *) block) + (size - MEMOVHD))) != 0xDEADBEEF)
00321 fputs("\nMEMCORR-", __heap_trs);
00322
00323 } else
00324 fputs("\nMEMNULL", __heap_trs);
00325 }
00326 #endif
00327
00328
00329
00330
00331 fnode = (HEAPNODE *) (((uptr_t *) block) - 1);
00332
00333 #ifdef NUTDEBUG
00334 if (__heap_trf)
00335 fprintf(__heap_trs, "\n[H%x,F%d] ", (u_int)(uptr_t) block, (int)fnode->hn_size);
00336 #endif
00337 size = fnode->hn_size;
00338
00339
00340
00341
00342
00343 node = heapFreeList;
00344 npp = (HEAPNODE **) & heapFreeList;
00345 while (node) {
00346
00347
00348
00349 if (((uptr_t) node + node->hn_size) == (uptr_t) fnode) {
00350 node->hn_size += fnode->hn_size;
00351
00352
00353
00354
00355 if (((uptr_t) node + node->hn_size) == (uptr_t) node->hn_next) {
00356 node->hn_size += node->hn_next->hn_size;
00357 node->hn_next = node->hn_next->hn_next;
00358 }
00359 break;
00360 }
00361
00362
00363
00364
00365 if ((uptr_t) node > (uptr_t) fnode) {
00366 *npp = fnode;
00367
00368
00369
00370
00371 if (((uptr_t) fnode + fnode->hn_size) == (uptr_t) node) {
00372 fnode->hn_size += node->hn_size;
00373 fnode->hn_next = node->hn_next;
00374 } else
00375 fnode->hn_next = node;
00376 break;
00377 }
00378
00379
00380
00381
00382
00383 if (((uptr_t) node + node->hn_size) > (uptr_t) fnode) {
00384 #ifdef NUTDEBUG
00385 if (__heap_trf)
00386 fputs("\nTWICE\n", __heap_trs);
00387 #endif
00388
00389 return -1;
00390 }
00391
00392 npp = &node->hn_next;
00393 node = node->hn_next;
00394 }
00395
00396
00397
00398
00399 if (!node) {
00400 fnode->hn_next = node;
00401 *npp = fnode;
00402 }
00403 available += size;
00404
00405 return 0;
00406 }
00407
00420 void NutHeapAdd(void *addr, size_t size)
00421 {
00422 *((uptr_t *) addr) = size;
00423 NutHeapFree(((uptr_t *) addr) + 1);
00424 }
00425
00431 size_t NutHeapAvailable(void)
00432 {
00433 return available;
00434 }
00435
00436
00437 #if defined (NUTMEM_STACKHEAP)
00438
00439
00440
00441
00442
00443
00444
00445 static HEAPNODE* volatile stackHeapFreeList;
00446 static u_short stackHeapAvailable;
00447
00448 void *NutStackAlloc(size_t size)
00449 {
00450 void * result;
00451 HEAPNODE* savedHeapNode;
00452 u_short savedAvailable;
00453
00454
00455 savedHeapNode = heapFreeList;
00456 savedAvailable = available;
00457
00458 heapFreeList = stackHeapFreeList;
00459 available = stackHeapAvailable;
00460
00461 result = NutHeapAlloc(size);
00462
00463
00464 stackHeapFreeList = heapFreeList;
00465 stackHeapAvailable = available;
00466
00467 heapFreeList = savedHeapNode;
00468 available = savedAvailable;
00469
00470 return result;
00471 }
00472
00473 int NutStackFree(void *block)
00474 {
00475 int result;
00476 HEAPNODE* savedHeapNode;
00477 u_short savedAvailable;
00478
00479
00480 savedHeapNode = heapFreeList;
00481 savedAvailable = available;
00482
00483 heapFreeList = stackHeapFreeList;
00484 available = stackHeapAvailable;
00485
00486 result = NutHeapFree(block);
00487
00488
00489 stackHeapFreeList = heapFreeList;
00490 stackHeapAvailable = available;
00491
00492 heapFreeList = savedHeapNode;
00493 available = savedAvailable;
00494
00495 return result;
00496 }
00497
00498 void NutStackAdd(void *addr, size_t size)
00499 {
00500 HEAPNODE* savedHeapNode;
00501 u_short savedAvailable;
00502
00503
00504 savedHeapNode = heapFreeList;
00505 savedAvailable = available;
00506
00507 heapFreeList = stackHeapFreeList;
00508 available = stackHeapAvailable;
00509
00510 NutHeapAdd(addr, size);
00511
00512
00513 stackHeapFreeList = heapFreeList;
00514 stackHeapAvailable = available;
00515
00516 heapFreeList = savedHeapNode;
00517 available = savedAvailable;
00518 }
00519
00520 #endif
00521