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