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
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00131
00132 #include <cfg/os.h>
00133 #include <compiler.h>
00134 #include <string.h>
00135
00136 #include <sys/atom.h>
00137 #include <sys/heap.h>
00138
00139 #include <stdint.h>
00140
00141 #ifdef NUTDEBUG
00142 #include <sys/osdebug.h>
00143 #endif
00144
00145 #if defined(__arm__) || defined(__m68k__) || defined(__H8300H__) || defined(__H8300S__) || defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__)
00146 #define ARCH_32BIT
00147 #endif
00148
00152 HEAPNODE *volatile heapFreeList;
00153
00157 static size_t available;
00158
00163
00164 #define MEMOVHD (sizeof(size_t) + sizeof(0xDEADBEEF))
00165
00170 static INLINE void setBeef(HEAPNODE * node){
00171
00172 *((uint32_t *) ((uptr_t) node + node->hn_size - sizeof(0xDEADBEEF))) = 0xDEADBEEF;
00173 }
00174
00175 #if !defined(ARCH_32BIT)
00176
00184 static INLINE char checkBeef(HEAPNODE * node){
00185 return (*((uint32_t *) ((uptr_t) node + node->hn_size - sizeof(0xDEADBEEF))) == 0xDEADBEEF);
00186 }
00187 #endif
00188
00220 void *NutHeapAlloc(size_t size)
00221 {
00222 HEAPNODE *node;
00223 HEAPNODE **npp;
00224 HEAPNODE *fit = 0;
00225 HEAPNODE **fpp = 0;
00226
00227 #if defined(ARCH_32BIT)
00228
00229
00230
00231 while ((size & 0x03) != 0)
00232 size++;
00233 #endif
00234
00235 if (size >= available) {
00236 #ifdef NUTDEBUG
00237 if (__heap_trf)
00238 fputs("MEMOVR\n", __heap_trs);
00239 #endif
00240 return 0;
00241 }
00242
00243
00244
00245
00246
00247
00248 if ((size += MEMOVHD) < sizeof(HEAPNODE))
00249 size = sizeof(HEAPNODE);
00250
00251
00252
00253
00254 node = heapFreeList;
00255 npp = (HEAPNODE **) & heapFreeList;
00256 while (node) {
00257
00258
00259
00260
00261 if (node->hn_size >= size) {
00262
00263
00264
00265
00266 if (node->hn_size == size) {
00267 fit = node;
00268 fpp = npp;
00269 break;
00270 }
00271
00272
00273
00274
00275
00276 if (fit == 0 || (fit->hn_size > node->hn_size)) {
00277 fit = node;
00278 fpp = npp;
00279 }
00280 }
00281 npp = &node->hn_next;
00282 node = node->hn_next;
00283 }
00284
00285 if (fit) {
00286
00287
00288
00289
00290
00291
00292 if (fit->hn_size > size + sizeof(HEAPNODE) + ALLOC_THRESHOLD) {
00293 node = (HEAPNODE *) ((uptr_t) fit + size);
00294 node->hn_size = fit->hn_size - size;
00295 node->hn_next = fit->hn_next;
00296 fit->hn_size = size;
00297 *fpp = node;
00298 } else
00299 *fpp = fit->hn_next;
00300
00301 available -= fit->hn_size;
00302 setBeef(fit);
00303 fit = (HEAPNODE *) & fit->hn_next;
00304 }
00305 #ifdef NUTDEBUG
00306 if (__heap_trf) {
00307 fprintf(__heap_trs, "\n[H%x,A%d/%d] ", (u_int)(uptr_t) fit, (int)(((HEAPNODE *) (((uptr_t *) fit) - 1))->hn_size), (int)size);
00308 }
00309 #endif
00310 return fit;
00311 }
00312
00326 void *NutHeapAllocClear(size_t size)
00327 {
00328 void *ptr;
00329
00330 if ((ptr = NutHeapAlloc(size)) != 0)
00331 memset(ptr, 0, size);
00332
00333 return ptr;
00334 }
00335
00352 void * NutHeapRealloc( void * block, size_t size){
00353 HEAPNODE *node;
00354 HEAPNODE **npp;
00355 HEAPNODE *fnode;
00356 HEAPNODE *newNode;
00357 size_t size_miss;
00358 void * newmem;
00359
00360
00361 if(size == 0){
00362 if( NutHeapFree(block) == 0){
00363 return block;
00364 } else {
00365 return NULL;
00366 }
00367 } else if(block == NULL){
00368 return NutHeapAlloc(size);
00369 }
00370
00371
00372
00373
00374 fnode = (HEAPNODE *) (((uptr_t *) block) - 1);
00375
00376 #ifdef NUTDEBUG
00377 if (__heap_trf) {
00378 if (!checkBeef(fnode)){
00379 fputs("\nMEMCORR-", __heap_trs);
00380 }
00381 }
00382 #endif
00383
00384
00385 if ((size += MEMOVHD) < sizeof(HEAPNODE))
00386 size = sizeof(HEAPNODE);
00387
00388 #ifdef NUTDEBUG
00389 if (__heap_trf)
00390 fprintf(__heap_trs, "\n[H%x,R%d] ", (u_int)(uptr_t) block, (int)fnode->hn_size);
00391 #endif
00392
00393 if (size > fnode->hn_size){
00394
00395 node = heapFreeList;
00396 npp = (HEAPNODE **) & heapFreeList;
00397 size_miss = size - fnode->hn_size;
00398
00399 while(node != NULL && fnode < node){
00400 npp = &node->hn_next;
00401 node = node->hn_next;
00402 }
00403
00404 if(node != NULL){
00405
00406
00407
00408 if (((uptr_t) fnode + fnode->hn_size) == (uptr_t) node && node->hn_size >= size_miss) {
00409 if(node->hn_size + ALLOC_THRESHOLD >= size_miss){
00410 newNode = (HEAPNODE *) ((uptr_t) node + size_miss);
00411
00412 memmove(newNode, node, sizeof(HEAPNODE));
00413 newNode->hn_size -= size_miss;
00414
00415 *npp = newNode;
00416 fnode->hn_size = size;
00417 available -= size_miss;
00418 } else {
00419 *npp = node->hn_next;
00420 fnode->hn_size += node->hn_size;
00421 available -= node->hn_size;
00422 }
00423 setBeef(fnode);
00424 #ifdef NUTDEBUG
00425 if (__heap_trf) {
00426 fprintf(__heap_trs, "\n[H%x,R%d/%d] ", (u_int)(uptr_t) fit, (int)(((HEAPNODE *) ((size_t *) fit - 1))->hn_size), (int)size);
00427 }
00428 #endif
00429 return block;
00430 }
00431 }
00432
00433
00434 newmem = NutHeapAlloc(size);
00435 if(newmem == NULL) return NULL;
00436 memcpy(newmem, block, fnode->hn_size - MEMOVHD);
00437 NutHeapFree(block);
00438 return newmem;
00439 }
00440
00441
00442 if(size + REALLOC_THRESHOLD + MEMOVHD < fnode->hn_size){
00443 newNode = (HEAPNODE *) ((uptr_t) fnode + size);
00444 newNode->hn_size = fnode->hn_size - size;
00445 fnode->hn_size = size;
00446 setBeef(fnode);
00447 NutHeapFree((void *)((size_t *) newNode + 1));
00448 }
00449 #ifdef NUTDEBUG
00450 if (__heap_trf) {
00451 fprintf(__heap_trs, "\n[H%x,R%d/%d] ", (u_int)(uptr_t) fit, (int)(((HEAPNODE *) ((size_t *) fit - 1))->hn_size), (int)size);
00452 }
00453 #endif
00454 return block;
00455 }
00456
00457
00479 int NutHeapFree(void *block)
00480 {
00481 HEAPNODE *node;
00482 HEAPNODE **npp;
00483 HEAPNODE *fnode;
00484 size_t size;
00485
00486 if(block == NULL) return -3;
00487
00488
00489
00490
00491 fnode = (HEAPNODE *) (((uptr_t *) block) - 1);
00492
00493 #ifdef NUTDEBUG
00494 if (__heap_trf) {
00495 if (block) {
00496 if (!checkBeef(fnode)) {
00497 fputs("\nMEMCORR-", __heap_trs);
00498 }
00499 } else {
00500 fputs("\nMEMNULL", __heap_trs);
00501 }
00502 }
00503 #endif
00504 #if !defined(ARCH_32BIT)
00505 if(!checkBeef(fnode)) {
00506 return -2;
00507 }
00508 #endif
00509
00510 #ifdef NUTDEBUG
00511 if (__heap_trf)
00512 fprintf(__heap_trs, "\n[H%x,F%d] ", (u_int)(uptr_t) block, (int)fnode->hn_size);
00513 #endif
00514 size = fnode->hn_size;
00515
00516
00517
00518
00519
00520 node = heapFreeList;
00521 npp = (HEAPNODE **) & heapFreeList;
00522 while (node) {
00523
00524
00525
00526 if (((uptr_t) node + node->hn_size) == (uptr_t) fnode) {
00527 node->hn_size += fnode->hn_size;
00528
00529
00530
00531
00532 if (((uptr_t) node + node->hn_size) == (uptr_t) node->hn_next) {
00533 node->hn_size += node->hn_next->hn_size;
00534 node->hn_next = node->hn_next->hn_next;
00535 }
00536 break;
00537 }
00538
00539
00540
00541
00542 if ((uptr_t) node > (uptr_t) fnode) {
00543 *npp = fnode;
00544
00545
00546
00547
00548 if (((uptr_t) fnode + fnode->hn_size) == (uptr_t) node) {
00549 fnode->hn_size += node->hn_size;
00550 fnode->hn_next = node->hn_next;
00551 } else
00552 fnode->hn_next = node;
00553 break;
00554 }
00555
00556
00557
00558
00559
00560 if (((uptr_t) node + node->hn_size) > (uptr_t) fnode) {
00561 #ifdef NUTDEBUG
00562 if (__heap_trf)
00563 fputs("\nTWICE\n", __heap_trs);
00564 #endif
00565 return -1;
00566 }
00567
00568 npp = &node->hn_next;
00569 node = node->hn_next;
00570 }
00571
00572
00573
00574
00575 if (!node) {
00576 fnode->hn_next = node;
00577 *npp = fnode;
00578 }
00579 available += size;
00580
00581 return 0;
00582 }
00583
00596 void NutHeapAdd(void *addr, size_t size)
00597 {
00598 *((uptr_t *) addr) = size;
00599 #if !defined(ARCH_32BIT)
00600
00601
00602
00603 setBeef((HEAPNODE *)addr);
00604 #endif
00605 NutHeapFree(((uptr_t *) addr) + 1);
00606 }
00607
00613 size_t NutHeapAvailable(void)
00614 {
00615 return available;
00616 }
00617
00618
00619 #if defined (NUTMEM_STACKHEAP)
00620
00621
00622
00623
00624
00625
00626
00627 static HEAPNODE* volatile stackHeapFreeList;
00628 static uint16_t stackHeapAvailable;
00629
00630 void *NutStackAlloc(size_t size)
00631 {
00632 void * result;
00633 HEAPNODE* savedHeapNode;
00634 uint16_t savedAvailable;
00635
00636
00637 savedHeapNode = heapFreeList;
00638 savedAvailable = available;
00639
00640 heapFreeList = stackHeapFreeList;
00641 available = stackHeapAvailable;
00642
00643 result = NutHeapAlloc(size);
00644
00645
00646 stackHeapFreeList = heapFreeList;
00647 stackHeapAvailable = available;
00648
00649 heapFreeList = savedHeapNode;
00650 available = savedAvailable;
00651
00652 return result;
00653 }
00654
00655 int NutStackFree(void *block)
00656 {
00657 int result;
00658 HEAPNODE* savedHeapNode;
00659 uint16_t savedAvailable;
00660
00661
00662 savedHeapNode = heapFreeList;
00663 savedAvailable = available;
00664
00665 heapFreeList = stackHeapFreeList;
00666 available = stackHeapAvailable;
00667
00668 result = NutHeapFree(block);
00669
00670
00671 stackHeapFreeList = heapFreeList;
00672 stackHeapAvailable = available;
00673
00674 heapFreeList = savedHeapNode;
00675 available = savedAvailable;
00676
00677 return result;
00678 }
00679
00680 void NutStackAdd(void *addr, size_t size)
00681 {
00682 HEAPNODE* savedHeapNode;
00683 uint16_t savedAvailable;
00684
00685
00686 savedHeapNode = heapFreeList;
00687 savedAvailable = available;
00688
00689 heapFreeList = stackHeapFreeList;
00690 available = stackHeapAvailable;
00691
00692 NutHeapAdd(addr, size);
00693
00694
00695 stackHeapFreeList = heapFreeList;
00696 stackHeapAvailable = available;
00697
00698 heapFreeList = savedHeapNode;
00699 available = savedAvailable;
00700 }
00701
00702 #endif
00703