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