00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "src/common/shared.hpp"
00022 #include "src/common/string.hpp"
00023 #include "src/thread/thread.hpp"
00024 #include "src/thread/scheduler.hpp"
00025 #include "src/memory/align.hpp"
00026 #include "src/memory/zone.hpp"
00027 #include "src/memory/memset.hpp"
00028 #include "src/memory/alloc4k.hpp"
00029 #include "src/memory/pager.hpp"
00030 #include "src/memory/heap.hpp"
00031
00035 #define OUT_OF_MEMORY_CRITICAL 0
00036 #define INVALID_FREE_ALERT 0
00037
00038 #define HEAP_DONT_USE_PROLOG 0
00039
00040
00041
00042
00045 namespace Memory {
00050 namespace Heap {
00051 uint32 dbg=0;
00052
00057
00058 class heapbox heap0;
00059 Memory::zone virtual_pages;
00060 class blist_t HeapList;
00061
00062 heapbox::heapbox() { lock_heap.init(const_cast<char*>("heap")); } ;
00063
00064
00065 void init()
00066 {
00067 uint32 *stack_addr, stack_size;
00068 uint32 page0,page1;uint32 i,n;
00069 uint32 x;
00070 HeapList.init("HeapList",&heap0);
00071
00072 page0=align_up(mem_heap_start+Memory::Physical::heap_area_addend,PAGE_ALIGN);
00073 page1=mem_heap_end;
00074 stack_size=align_up((page1-page0)/HEAP_STACK_GRAN * sizeof(uint32),PAGE_ALIGN);
00075 Memory::Physical::disable_balloc();
00076
00077
00078 stack_addr = (uint32*) page0; page0+=stack_size;
00079 for (i=0;i<stack_size;i+=PAGE_SIZE)
00080 { x= alloc4k(1,true);
00081 Memory::Pager::kmem.pte_map(i+(uint32)stack_addr,
00082 x|PTE_PRESENT|PTE_WRITEABLE); }
00083
00084 virtual_pages.init(stack_addr,stack_size/sizeof(uint32),HEAP_STACK_GRAN);
00085 n=0;
00086 #if 0
00087 cout("\npage1-HEAP_STACK_GRAN=");
00088 cout(page1-HEAP_STACK_GRAN);
00089 cout("\npage0=");
00090 cout(page0);
00091 #endif
00092 for (i=page1-HEAP_STACK_GRAN;i>page0;i-=HEAP_STACK_GRAN)
00093 {
00094 stack_addr[n++]=i;
00095 }
00096 virtual_pages.set_length(n);
00097 #if 0
00098 cout("\nvirt stack_addr=");cout((uint32)stack_addr);
00099 cout("\nstack_size=");cout(stack_size);
00100 cout("\nphys=");cout(Memory::Pager::kmem.pte_val((uint32)stack_addr&0xfffff000));
00101 cout("\n&stack_addr[n]=");cout((uint32)&stack_addr[n]);
00102 for (i=0;i<1000000;i++)
00103 {
00104 int in= Memory::Physical::free_pages_low.alloc(1);
00105 if (in) { cout("{");cout(in);cout("}"); }
00106 }
00107 sysfail("");
00108 #endif
00109
00110
00111 int r;
00112 r = allocate_heapbox(&heap0, "heap0");
00113 if (r != ESUCCESS)
00114 sysfail("error allocating heap0");
00115 }
00116
00119 int allocate_heapbox(class heapbox *hbx, const char *name)
00120 {
00121
00122
00123
00124 addr_t heap_addr = morecore(HEAP_GRAN);
00125 uint32 prolog_shift =
00126 #if HEAP_DONT_USE_PROLOG
00127 0
00128 #else
00129 sizeof(struct block_prolog)
00130 #endif
00131 ;
00132 addr_t heap0_addr = heap_addr+prolog_shift;
00133 size_t used_blocks_table_size = HEAP_TBLE*sizeof(block_used);
00134 size_t used_blocks_alloc_size = used_blocks_table_size+prolog_shift;
00135 if ( (used_blocks_alloc_size/HEAP_MIN_BLOCK) * HEAP_MIN_BLOCK != used_blocks_alloc_size)
00136 used_blocks_alloc_size = (used_blocks_alloc_size/HEAP_MIN_BLOCK+1)*HEAP_MIN_BLOCK;
00137
00138 if (heap_addr == NULL) {
00139 #if OUT_OF_MEMORY_CRITICAL
00140 sysfail("cannot allocate heapbox");
00141 #else
00142 complain("cannot allocate heapbox");
00143 #endif
00144 return EOUTOFMEMORY;
00145 }
00146
00147
00148 block_free *firstfree;
00149 memset((void*)heap0_addr,NULL,used_blocks_table_size);
00150
00151
00152 ((block_used*)heap0_addr)->ptr=(void*) heap_addr;
00153 ((block_used*)heap0_addr)->size=used_blocks_alloc_size;
00154 ((block_used*)heap0_addr)->facility=FAC_MEMORY|FAC_USEDBLOCKS;
00155 ((block_used*)heap0_addr)->destruct=null;
00156 countMagic((block_used*)heap0_addr);
00157
00158
00159 firstfree=(block_free*)(heap_addr + used_blocks_alloc_size);
00160 firstfree->prev=NULL;
00161 firstfree->next=NULL;
00162 firstfree->size=HEAP_GRAN*HEAP_STACK_GRAN - used_blocks_alloc_size;
00163 countMagic(firstfree);
00164
00165
00166 hbx->init((block_used*)heap0_addr, HEAP_TBLE, firstfree, name);
00167
00168 #if HEAP_DONT_USE_PROLOG
00169 #else
00170 ((struct block_prolog*)heap_addr)->ov= 0;
00171 ((struct block_prolog*)heap_addr)->check= PROLOG_CHECKSUM - 0 + hbx->heapbox_no;
00172 #endif
00173
00174
00175 hbx->stats.max=HEAP_GRAN*HEAP_STACK_GRAN;
00176 hbx->stats.used=used_blocks_alloc_size;
00177
00178
00179 hbx->VirtAddrs.init("virtaddrs", hbx);
00180 hbx->VirtAddrs.ptr((void*) heap_addr, NULL);
00181
00182 HeapList.ptr(hbx,NULL);
00183
00184 hbx->morecor_new_node= (struct blist_s*) hbx->mallocFunc(sizeof(struct blist_s), NO_ALIGN, (uint32)"virtaddr", NULL, 0);
00185
00186 return ESUCCESS;
00187 }
00188
00189
00190 addr_t morecore(size_t cnt)
00191 {
00192 addr_t ret;
00193 uint32 i,x;
00194
00195 ret=virtual_pages.alloc(cnt);
00196
00197
00198
00199
00200
00201
00202 if ((ret==NULL) || (ret==0xFFFFFFFF)) return ret;
00203
00204 if (!Pager::lazy_enable)
00205 for (i=0;i<cnt*HEAP_STACK_GRAN/PAGE_SIZE;i++)
00206 { x=alloc4k(1,true);
00207 Memory::Pager::kmem.pte_map(ret+i*PAGE_SIZE,x|PTE_WRITEABLE|PTE_PRESENT);}
00208 else
00209 for (i=0;i<cnt*HEAP_STACK_GRAN/PAGE_SIZE;i++)
00210 Pager::kmem.pte_lazy(ret+i*PAGE_SIZE,PTE_WRITEABLE);
00211
00212 return ret;
00213 }
00214
00215
00216 void freecore(addr_t virt, size_t cnt)
00217 {
00218
00219 notimpl();
00220 }
00221
00222
00223 int checkMagic(block_free *item)
00224 {
00225
00226 return 1;
00227 }
00228
00229
00230 int checkMagic(block_used *item)
00231 {
00232
00233 return 1;
00234 }
00235
00236
00237 int countMagic(block_free *item)
00238 {
00239
00240 return 1;
00241 }
00242
00243
00244 int countMagic(block_used *item)
00245 {
00246
00247 return 1;
00248 }
00249
00250
00251
00252 void heapbox::init(block_used *usd, size_t max_blcks, block_free *fir, const char *nam)
00253 {
00254 static uint32 heapbox_no_acc;
00255 heapbox_no = heapbox_no_acc ;
00256 heapbox_no_acc ++ ;
00257
00258 memset(this, 0, sizeof(heapbox));
00259
00260 lock_heap.init(nam);
00261 used=usd; max_blocks=max_blcks; first=fir;
00262 memmove(&name, nam, MIN(lgth(nam),HEAPBOX_NAME-1));
00263 }
00264
00265
00266 void heapbox::destruct()
00267 {
00268 size_t i;
00269 uint32 z;
00270 blist_s *item,*next;
00271 uint32 addr,ph;
00272
00273 HeapList.del(HeapList.find(this));
00274
00275 for (i=0;i<max_blocks;i++)
00276 if (used[i].destruct)
00277 used[i].destruct(this,used[i].ptr);
00278
00279 for (item=VirtAddrs.head;item;item=next)
00280 {
00281 next=item->next;
00282 addr=(uint32)item->data;
00283 for(z=0;z<HEAP_STACK_GRAN;z+=PAGE_SIZE)
00284 if ((ph=Memory::Pager::kmem.pte_val(z+addr))&PTE_PRESENT)
00285 disalloc4k(ph&0xfffff000);
00286 virtual_pages.free(addr);
00287 }
00288
00289 VirtAddrs.done();
00290 }
00291
00292
00293
00294 int can_be_aligned(uint32 r0, size_t r_size, size_t size, uint32 allignment)
00295 {
00296 uint32 i;
00297
00298
00299 if (r_size < size) return EINVAL;
00300
00301 if (allignment == 0)
00302 allignment = 1;
00303
00304 i = (r0 + r_size - size) & (0xFFFFFFFF - allignment + 1);
00305
00306 if (i >= r0) return i;
00307 return EINVAL;
00308 }
00309
00310
00311 void new_bl_bl (block_free *item, block_free *new_block)
00312 {
00313 block_free *i;
00314 uint32 old_size;
00315 i = item -> next;
00316
00317
00318 if ((uint32)new_block <= (uint32) item) sysfail("error #1");
00319
00320
00321 if ((i != 0)&&((uint32) new_block >= (uint32) i)) sysfail("error #2");
00322
00323
00324 item -> next = new_block;
00325 old_size = item -> size;
00326 item -> size = (uint32) new_block - (uint32) item;
00327 countMagic(item);
00328
00329
00330 new_block -> prev = item;
00331 new_block -> next = i;
00332 new_block -> size = old_size - item -> size;
00333 countMagic(new_block);
00334
00335 if (i) {
00336 i -> prev = new_block;
00337 countMagic(i);}
00338
00339 }
00340
00341
00342 void heapbox::unAnchorBlock(block_free *item)
00343 {
00344
00345 if (item -> prev) {
00346 item -> prev -> next = item -> next;
00347 countMagic(item -> prev);}
00348
00349
00350 if (item -> next) {
00351 item -> next -> prev = item -> prev;
00352 countMagic(item -> next);}
00353
00354
00355 if ((!item -> prev)&&(!item -> next))
00356 {
00357
00358
00359
00360
00361 first = NULL;
00362
00363 morecor(HEAP_GRAN, !Memory::Pager::lazy_enable);
00364 } else
00365 if (item == first)
00366 {
00367 first = item -> next;
00368 first -> prev = 0;
00369 countMagic(first);
00370 }
00371 }
00372
00373
00374 int heapbox::take_block (block_free *item, uint32 facility, int (destructor)(class heapbox*,void*))
00375 {
00376
00377 unAnchorBlock(item);
00378
00379
00380
00381 int bu = knew_used(item, item -> size, facility, destructor);
00382 if (bu == -1) {
00383 complain("knew_used failed;");
00385 panic();
00386 return -1;
00387 }
00388
00389 stats.used+=item->size;
00390 return bu;
00391 }
00392
00393
00394 int heapbox::knew_used(void *ptr, uint32 size, uint32 facility, int (*destruct)(class heapbox*,void*))
00395 {
00396 uint32 i;
00397 i = begin_search;
00398
00399 while (used[i].size)
00400 {
00401 i++;
00402 if (i >= max_blocks)
00403 {
00404 TTYDisableLock=true;
00405 cout(const_cast<char*>("knew_used failed; reached allocated heap blocks limit"));
00406 #if 0
00407 complain(max_blocks);
00408 complain(stats.allocs);
00409 #endif
00410
00411 asm volatile("cli\nhlt");
00412 return -1;
00413 }
00414 #if 0
00415 {
00416 for (i=0;i<1000000;i++)
00417 {
00418 int in;
00419 (in=Memory::Physical::free_pages_high.alloc(1))||(in=Memory::Physical::free_pages_low.alloc(1));
00420 if (in) { cout("{");cout(in);cout("}"); }
00421 }
00422
00423 cout("\nname=");
00424 cout(name);
00425 cout("\nstats.used=");
00426 cout(stats.used);
00427 cout("\nstats.max=");
00428 cout(stats.max);
00429 cout("\nstats.allocs=");
00430 cout(stats.allocs);
00431 cout("\nmax_blocks=");
00432 cout(max_blocks);
00433 cout("\nbegin_search=");
00434 cout(begin_search);
00435 cout("\ni=");
00436 cout(i);
00437 sysfail("oh no!");
00438 }
00439 #endif
00440 } begin_search=i;
00441
00442 used[i].size = size;
00443 used[i].ptr = ptr;
00444 used[i].facility = facility;
00445 used[i].destruct=destruct;
00446 countMagic(&used[i]);
00447
00448 stats.allocs++;
00449
00450 return i;
00451 }
00452
00454 addr_t heapbox::morecor(uint32 cnt, bool alloc_pgs)
00455 {
00456
00457
00458
00459 addr_t ret;
00460 uint32 i,x;
00461 block_free *item;
00462 block_free *list, *pr=NULL;
00463 blist_s *node;
00464 ret=virtual_pages.alloc(cnt);
00465
00466 if (ret==NULL) return NULL;
00467
00468
00469
00470 node= morecor_new_node;
00471 morecor_new_node=null;
00472 memset(node,0,sizeof(struct blist_s*));
00473 node->size= 0; node->data= (void*)ret; node->func=(char*)__func__; node->line=__LINE__; node->file=(char*)__FILE__; node->tree= NULL;
00474 VirtAddrs.link(node);
00475
00476 for (i=0;i<cnt*(HEAP_STACK_GRAN/PAGE_SIZE);i++)
00477 if (alloc_pgs)
00478 { x=alloc4k(1,true);
00479 Memory::Pager::kmem.pte_map(ret+i*PAGE_SIZE,x|PTE_WRITEABLE|PTE_PRESENT); }
00480 else
00481 Memory::Pager::kmem.pte_lazy(ret+i*PAGE_SIZE, PTE_WRITEABLE);
00482
00483 item=(block_free*)ret;
00484 memset(item,0,sizeof(block_free));
00485 item->size=cnt*HEAP_STACK_GRAN;
00486
00487 for (list=first;list;list=list->next)
00488 { pr= list; if (list > item) break; }
00489
00490 if (list == NULL)
00491 {
00492 if (pr==NULL)
00493 first=item;
00494 else
00495 {
00496 pr->next=item;
00497 countMagic(pr);
00498 item->prev=pr;
00499 countMagic(item);
00500 }
00501 } else
00502 {
00503 item->prev=list->prev;
00504 item->next=list;
00505 if (list->prev)
00506 list->prev->next=item;
00507 list->prev=item;
00508 }
00509
00510 kdefragment(item);
00511
00512 stats.max+= cnt*HEAP_STACK_GRAN;
00513
00514 return ESUCCESS;
00515 }
00516
00517
00518 void *heapbox::mallocFunc(size_t size, size_t alignment,uint32 facility, int (*destruct)(class heapbox*, void*), uint32 MallocState) {
00519 void *ret;
00520 #if 1
00521 assert( kget_info(((struct block_prolog*)used)-1) );
00522 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00523 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00524 freeze();
00525 }
00526 #endif
00527 #if HEAP_DONT_USE_PROLOG
00528 ret= mallocFuncPr(size,alignment,facility,destruct,MallocState);
00529 #else
00530 #if 1
00531 assert( kget_info(((struct block_prolog*)used)-1) );
00532 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00533 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00534 freeze();
00535 }
00536 #endif
00537 ret= mallocFuncPr(size+sizeof(struct block_prolog),alignment,facility,destruct,MallocState);
00538 #if 1
00539 assert( kget_info(((struct block_prolog*)used)-1) );
00540 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00541 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00542 freeze();
00543 }
00544 #endif
00545 assert(kget_info(ret));
00546 ret = (void*) (((struct block_prolog*)ret)+1);
00547 #endif
00548 #if 1
00549 assert( kget_info(((struct block_prolog*)used)-1) );
00550 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00551 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00552 freeze();
00553 }
00554 #endif
00555
00556 if ( ( (MallocState & MALLOC_NORESCUE) == 0) && ( (MallocState & MALLOC_MORECOR_NEW_NODE) == 0) && (morecor_new_node == null) ) {
00557 morecor_new_node= (struct blist_s*) mallocFunc(sizeof(struct blist_s), NO_ALIGN, (uint32)"virtaddr", NULL, MALLOC_MORECOR_NEW_NODE);
00558 }
00559 #if 1
00560 assert( kget_info(((struct block_prolog*)used)-1) );
00561 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00562 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00563 freeze();
00564 }
00565 #endif
00566 return ret;
00567 }
00568
00569 void *heapbox::mallocFuncPr(size_t size, size_t alignment, uint32 facility, int (*destruct)(class heapbox*,void*), uint32 MallocState)
00570 {
00571
00572
00573
00574
00575
00576
00577 block_free *item;
00578 uint32 n;
00579 uint32 prolog_alignment_shift=
00580 #if HEAP_DONT_USE_PROLOG
00581 0
00582 #else
00583 sizeof(struct block_prolog)
00584 #endif
00585 ;
00586
00587
00588 if ((MallocState & MALLOC_NOLOCKS)==0)
00589 lock_heap.lock();
00590
00591
00592
00593 #if HEAP_DONT_USE_PROLOG
00594
00595 if (stats.allocs+2 >= max_blocks-1)
00596 #else
00597 if (stats.allocs+2 >= max_blocks-22)
00598 #endif
00599 if ((MallocState&MALLOC_NORESCUE)==0)
00600
00601 { NowResizingUsed= true;
00602 resize_used_blocks_table();
00603 #if 1
00604 assert( kget_info(((struct block_prolog*)used)-1) );
00605 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00606 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00607 freeze();
00608 }
00609 #endif
00610
00611 NowResizingUsed= false; }
00612 #if 1
00613 assert( kget_info(((struct block_prolog*)used)-1) );
00614 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00615 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00616 freeze();
00617 }
00618 #endif
00619
00620
00621 size=align_up(size, HEAP_MIN_BLOCK);
00622
00623 #if 1
00624 assert( kget_info(((struct block_prolog*)used)-1) );
00625 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00626 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00627 freeze();
00628 }
00629 #endif
00630 for (item=first; item; item=item->next)
00631 {
00632
00633 checkMagic(item);
00634
00635
00636 n = can_be_aligned(prolog_alignment_shift+ (uint32) item, item->size-prolog_alignment_shift,
00637 size-prolog_alignment_shift, alignment);
00638 #if HEAP_DONT_USE_PROLOG
00639 #else
00640 assert(prolog_alignment_shift == sizeof(struct block_prolog));
00641 assert(8 == sizeof(struct block_prolog));
00642 #endif
00643
00644
00645
00646 if (n==(uint32)EINVAL) continue;
00647
00648 assert ( (alignment==0) || ( (n & (alignment-1)) == 0) );
00649 n -= prolog_alignment_shift;
00650
00651
00652 #if 1
00653 assert( kget_info(((struct block_prolog*)used)-1) );
00654 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00655 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00656 freeze();
00657 }
00658 #endif
00659
00660
00661
00662
00663 if (n != (uint32) item) {
00664 if (n - (uint32)item < HEAP_MIN_BLOCK) {
00665 continue;
00666 }
00667 else
00668 if (n!= (uint32) item)
00669 {
00670
00671
00672 #if 1
00673 assert( kget_info(((struct block_prolog*)used)-1) );
00674 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00675 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00676 freeze();
00677 }
00678 #endif
00679 new_bl_bl(item, (block_free*)n);
00680 #if 1
00681 assert( kget_info(((struct block_prolog*)used)-1) );
00682 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00683 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00684 complain((uint32)item);
00685 complain(n);
00686 complain((uint32)used);
00687 complain((uint32)&used[max_blocks]);
00688 freeze();
00689 }
00690 #endif
00691
00692
00693 item = (block_free*) n;
00694 }
00695 }
00696
00697
00698 #if 1
00699 assert( kget_info(((struct block_prolog*)used)-1) );
00700 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00701 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00702 freeze();
00703 }
00704 #endif
00705 if (item -> size - size >= HEAP_MIN_BLOCK)
00706 {
00707
00708 new_bl_bl (item, (block_free*)((uint32)item + size));
00709
00710 int bu;
00711 bu= take_block (item,facility,destruct);
00712 #if HEAP_DONT_USE_PROLOG
00713 #else
00714
00715 struct block_prolog *bp;
00716 bp= reinterpret_cast<struct block_prolog*>(item);
00717 bp->ov=bu;
00718 bp->check = PROLOG_CHECKSUM - bp->ov+heapbox_no;
00719 assert(kget_info(item));
00720 #endif
00721
00722 if ((MallocState & MALLOC_NOLOCKS)==0)
00723 lock_heap.ulock();
00724
00725
00726 #if 1
00727 assert( kget_info(((struct block_prolog*)used)-1) );
00728 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00729 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00730 freeze();
00731 }
00732 #endif
00733
00734 return ((char*) item);
00735 }
00736 else
00737 {
00738 #if 1
00739 assert( kget_info(((struct block_prolog*)used)-1) );
00740 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00741 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00742 freeze();
00743 }
00744 #endif
00745
00746 int bu;
00747 bu=take_block(item,facility,destruct);
00748 #if HEAP_DONT_USE_PROLOG
00749 #else
00750
00751 struct block_prolog *bp;
00752 bp= reinterpret_cast<struct block_prolog*>(item);
00753 bp->ov=bu;
00754 bp->check = PROLOG_CHECKSUM - bp->ov + heapbox_no;
00755 assert(kget_info(item));
00756 #endif
00757
00758 if ((MallocState & MALLOC_NOLOCKS)==0)
00759 lock_heap.ulock();
00760
00761
00762 #if 1
00763 assert( kget_info(((struct block_prolog*)used)-1) );
00764 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00765 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00766 freeze();
00767 }
00768 #endif
00769
00770 return((char*) item);
00771 }
00772 }
00773
00774
00775
00776 if ((size/HEAP_STACK_GRAN) < HEAP_GRAN) {
00777 morecor (HEAP_GRAN, !Memory::Pager::lazy_enable);
00778 }
00779 else {
00780 morecor((size/HEAP_STACK_GRAN) + 1, !Memory::Pager::lazy_enable);
00781 }
00782
00783
00784 void *d;
00785
00786 d= mallocFuncPr(size, alignment, facility, destruct, MallocState|MALLOC_NOLOCKS);
00787
00788
00789 if ((MallocState & MALLOC_NOLOCKS)==0)
00790 lock_heap.ulock();
00791
00792 return(d);
00793 }
00794
00795
00805
00806 void *heapbox::malloc(size_t size, size_t alignment, uint32 facility, int (*destruct)(class heapbox*,void*)) {
00807 _PF;
00808 uint32 fl;
00810 asm volatile("pushf\npopl %0\ncli" :"=g"(fl));
00811 void *ret;
00812 ret= mallocFunc(size,alignment,facility,destruct, 0);
00813 asm volatile("pushl %0\npopf"::"g"(fl));
00814 Preturn (ret);
00815 }
00816
00817
00818 void *heapbox::malloc(size_t size, size_t alignment, const char *name, int (*destruct)(class heapbox*,void*)) {
00819 return malloc(size,alignment,(uint32)name,destruct);
00820 }
00821
00822
00823 block_used *heapbox::kget_info(void *ptr)
00824 {
00825 if (ptr == 0) {
00826 sysfail("kget_info: ptr == 0");
00827
00828 }
00829
00830 #if HEAP_DONT_USE_PROLOG
00831 uint32 i = 0;
00832 while (used[i].ptr != ptr)
00833 {
00834 i++;
00835 if (i >= max_blocks) return NULL;
00836 }
00837
00838 return used + i;
00839 #else
00840 struct block_prolog *pr;
00841 pr= static_cast<struct block_prolog*>(ptr);
00842 if (pr->ov + pr->check != PROLOG_CHECKSUM+heapbox_no) {
00843 #if INVALID_FREE_ALERT
00844 complain("kget_info: prolog checksum erroneous");
00845 complain((uint32)ptr);
00846 complain(pr->ov + pr->check);
00847
00848
00849
00850
00851 #endif
00852 return null;
00853 }
00854 return &used[pr->ov];
00855
00856 #endif
00857 }
00858
00859
00860 uint32 heapbox::blsize(char *ptr)
00861 {
00862 block_used *info;
00863
00864 info = kget_info(ptr);
00865
00866 if (info == NULL) return 0;
00867
00868 return info -> size;
00869 }
00870
00871
00872 block_free *heapbox::klastfree()
00873 {
00874 block_free *item;
00875 for (item = first; item -> next; item = item -> next) ;
00876 return item;
00877 }
00878
00879
00880
00881 #if 1
00882 int heapbox::freeFunc2(void *ptr, uint32 FreeState) {
00883 int ret;
00884 if (ptr==null) { complain("free:null ptr"); freeze(); }
00885 ret=freeFuncPr2( (void*)(((struct block_prolog*)ptr)-1), FreeState);
00886 return ret;
00887 }
00888
00889 int heapbox::freeFuncPr2(void *ptr, uint32 FreeState)
00890 {
00891 block_used *info;
00892 block_free *item, *i;
00893
00894 info = kget_info(ptr);
00895 item = (block_free*) ptr;
00896
00897
00898
00899 ptr= (void*)(((struct block_prolog*)ptr)+0);
00900 ((struct block_prolog*)ptr)->ov=0;
00901 ((struct block_prolog*)ptr)->check=0;
00902
00903 if (info == NULL || info->size == 0) {
00904 lnDbg;
00905 return EINVAL;
00906 }
00907
00908 if (info->destruct != NULL) {
00909 lnDbg;
00910 info->destruct(this,ptr);
00911 }
00912
00913 stats.allocs--;
00914
00915
00916 if (item < first)
00917 {
00918 first -> prev = item;
00919 countMagic(first);
00920 item -> next = first;
00921 item -> prev = 0;
00922 item -> size = info->size;
00923 first = item;
00924
00925 countMagic(item);
00926 } else
00927 {
00928 #if 1
00929 i = klastfree();
00930 if (item > i)
00931 {
00932 i -> next = item;
00933 item -> prev = i;
00934 item -> next = 0;
00935 item -> size = info->size;
00936
00937 countMagic(item); countMagic(i);
00938 } else
00939 {
00940 i = first;
00941
00942
00943 while ((uint32)i -> next < (uint32)item) i = i -> next;
00944
00945
00946 item -> next = i -> next;
00947 i -> next = item;
00948 item -> prev = i;
00949 item -> next -> prev = item;
00950 item -> size = info -> size;
00951
00952 #if 0
00953 countMagic(item); countMagic(i);
00954 countMagic(item -> next);
00955 #endif
00956 }
00957 #endif
00958 }
00959
00960
00961 stats.used-= info->size;
00962
00963 info -> ptr = null;
00964 info -> facility = 0;
00965 info -> size = 0;
00966 info -> destruct = null;
00967 countMagic(info);
00968
00969 uint32 b_new;
00970 b_new = ((uint32)info-(uint32)used) / sizeof(block_used);
00971 if (b_new < begin_search)
00972 begin_search=b_new;
00973
00974 kdefragment(ptr);
00975
00976
00977
00978
00979 return ESUCCESS;
00980 }
00981 #endif
00982
00986 int heapbox::freeFunc(void *ptr, uint32 FreeState) {
00987 int ret;
00988 if (ptr==null) {
00989 complain("free:null ptr");
00990 freeze();
00991 }
00992 #if 1
00993 assert( kget_info(((struct block_prolog*)used)-1) );
00994 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
00995 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
00996 freeze();
00997 }
00998 #endif
00999 #if HEAP_DONT_USE_PROLOG
01000 ret=freeFuncPr( ptr, FreeState );
01001 #else
01002 ret=freeFuncPr( (void*)(((struct block_prolog*)ptr)-1), FreeState);
01003 #endif
01004 #if 1
01005 assert( kget_info(((struct block_prolog*)used)-1) );
01006 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
01007 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
01008 freeze();
01009 }
01010 #endif
01011 return ret;
01012 }
01013
01014 int heapbox::freeFuncPr(void *ptr, uint32 FreeState)
01015 {
01016 #if INVALID_FREE_ALERT
01017 if (ptr==null)
01018 complain("free: null ptr");
01019 #endif
01020 if (ptr == null)
01021 return EINVAL;
01022 block_used *info;
01023 block_free *item, *i;
01024
01025 info = kget_info(ptr);
01026 item = (block_free*) ptr;
01027
01028
01029 sbg;
01030
01031 #if HEAP_DONT_USE_PROLOG
01032 #else
01033 ptr= (void*)(((struct block_prolog*)ptr)+0);
01034 ((struct block_prolog*)ptr)->ov=0;
01035 ((struct block_prolog*)ptr)->check=0;
01036 #endif
01037
01038 if (info == NULL || info->size == 0) {
01039 #if INVALID_FREE_ALERT
01040 complain(name); complain("invalid free "); complain(reinterpret_cast<uint32>((void*)(((struct block_prolog*)ptr)+1)));
01041 #endif
01042 return EINVAL;
01043 }
01044
01045
01046 if (info->destruct != NULL) {
01047 info->destruct(this,ptr);
01048 }
01049
01050 if ((FreeState&MALLOC_NOLOCKS)==0)
01051 lock_heap.lock();
01052
01053 stats.allocs--;
01054
01055
01056 if (item < first)
01057 {
01058 sbg;
01059
01060 first -> prev = item;
01061 countMagic(first);
01062 item -> next = first;
01063 item -> prev = 0;
01064 item -> size = info->size;
01065 first = item;
01066 sbg;
01067
01068 countMagic(item);
01069 } else
01070 {
01071 sbg;
01072 i = klastfree();
01073 if (item > i)
01074 {
01075 sbg;
01076 i -> next = item;
01077 item -> prev = i;
01078 item -> next = 0;
01079 item -> size = info->size;
01080
01081 countMagic(item); countMagic(i);
01082 } else
01083 {
01084 i = first;
01085
01086
01087 while (i -> next < item) i = i -> next;
01088
01089
01090 item -> next = i -> next;
01091 i -> next = item;
01092 item -> prev = i;
01093 item -> next -> prev = item;
01094 item -> size = info -> size;
01095
01096 countMagic(item); countMagic(i);
01097 countMagic(item -> next);
01098 }
01099 }
01100
01101
01102 stats.used-= info->size;
01103
01104 info -> ptr = null;
01105 info -> facility = 0;
01106 info -> size = 0;
01107 info -> destruct = null;
01108 countMagic(info);
01109
01110 uint32 b_new;
01111 b_new = ((uint32)info-(uint32)used) / sizeof(block_used);
01112 if (b_new < begin_search)
01113 begin_search=b_new;
01114
01115 kdefragment(ptr);
01116
01117 if ((FreeState&MALLOC_NOLOCKS)==0)
01118 lock_heap.ulock();
01119
01120 sbg;
01121 return ESUCCESS;
01122 }
01123
01124 int heapbox::free(void *ptr) {
01125 uint32 fl;
01127 asm volatile("pushf\npopl %0\ncli":"=g"(fl));
01128 int ret;
01129 ret=freeFunc(ptr,0);
01130 asm volatile("pushl %0\npopf"::"g"(fl));
01131 return ret;
01132 }
01133
01134
01135
01137 uint32 heapbox::allocated_count() {
01138 return stats.allocs;
01139 }
01140
01141
01142
01143 void heapbox::kdefragment(void *ptr)
01144 {
01145 block_free *item;
01146
01147 item = (block_free*) ptr;
01148
01149
01150 if (item -> prev)
01151
01152
01153 if (item -> prev -> size + (uint32) item -> prev == (uint32) item)
01154 {
01155 item -> prev -> size += item -> size;
01156 item -> prev -> next = item -> next;
01157 if (item -> next) item -> next -> prev = item -> prev;
01158
01159 countMagic(item -> prev);
01160 if (item -> next) countMagic(item -> prev -> next);
01161
01162 item = item -> prev;
01163 }
01164
01165
01166 if (item -> next)
01167
01168
01169 if ((uint32) item -> next == item -> size + (uint32) item)
01170 {
01171
01172 item -> size += item -> next -> size;
01173
01174 item -> next = item -> next -> next;
01175
01176 if (item->next)
01177 {item -> next -> prev = item;countMagic(item -> next);}
01178
01179
01180 countMagic(item);
01181 }
01182 }
01183
01184 int heapbox::resize_used_blocks_table()
01185 {
01186 void *new_table, *old_table=used;
01187
01188
01189 new_table=mallocFunc((max_blocks+HEAP_TBLE_GRAN)*sizeof(block_used),
01190 STACK_ALIGN, FAC_MEMORY|FAC_USEDBLOCKS, NULL, MALLOC_NOLOCKS|MALLOC_NORESCUE);
01191 #if 1
01192 assert( kget_info(((struct block_prolog*)old_table)-1) );
01193 if ( kget_info(((struct block_prolog*)old_table)-1)->destruct != null ) {
01194 complain( (uint32)kget_info(((struct block_prolog*)old_table)-1)->destruct );
01195 freeze();
01196 }
01197 #endif
01198 if (new_table == NULL)
01199 {
01200 #if OUT_OF_MEMORY_CRITICAL
01201 debug_dump_call_trace();
01202 #endif
01203 complain("out of memory!");
01204 #if OUT_OF_MEMORY_CRITICAL
01205 freeze();
01206 #endif
01207 return EINVAL; }
01208
01209
01210
01211 memmove(new_table, (void*)used, max_blocks*sizeof(block_used));
01212 memset((char*)new_table+max_blocks*sizeof(block_used), 0, HEAP_TBLE_GRAN*sizeof(block_used));
01213
01214 max_blocks+=HEAP_TBLE_GRAN;
01215 #if 0
01216 complain(name);
01217 complain(max_blocks);
01218 complain(stats.allocs);
01219 #endif
01220 used=(block_used*)new_table;
01221
01222
01223
01224 freeFunc(old_table, MALLOC_NOLOCKS);
01225
01226 #if 1
01227 assert( kget_info(((struct block_prolog*)used)-1) );
01228 if ( kget_info(((struct block_prolog*)used)-1)->destruct != null ) {
01229 complain( (uint32)kget_info(((struct block_prolog*)used)-1)->destruct );
01230 freeze();
01231 }
01232 #endif
01233
01234
01235 return ESUCCESS;
01236 }
01237
01238
01239
01240
01241 };
01242 };
01243
01245
01246 void debug_heap_stats(Memory::Heap::heapbox *hp)
01247 {
01248
01249 cout(const_cast<char*>("\n-----\n"));
01250
01251 Memory::Heap::block_free *item;
01252 for (item=hp->first; item; item=item->next)
01253 {
01254 cout(const_cast<char*>("@"));
01255 cout((uint32)item);
01256 cout(const_cast<char*>(", size=0x"));
01257 cout(item->size);
01258 cout(const_cast<char*>(", next=0x"));
01259 cout((uint32)item->next);
01260 cout(const_cast<char*>(", prev=0x"));
01261 cout((uint32)item->prev);
01262 cout(const_cast<char*>(";\n"));
01263 }
01264
01265 cout("\n\"");
01266 cout(hp->name);
01267 cout("\", stats.allocs=0x");
01268 cout(hp->stats.allocs);
01269 cout(", stats.max=0x");
01270 cout(hp->stats.max);
01271 cout(", stats.used=0x");
01272 cout(hp->stats.used);
01273 cout("\n==end heap_stats=====\n");
01274
01275 }
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289