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