home *** CD-ROM | disk | FTP | other *** search
/ Netrunner 2004 October / NETRUNNER0410.ISO / regular / irvine1_0_9.lzh / mmgr / source / xmalloc.pas < prev   
Pascal/Delphi Source File  |  2003-05-19  |  12KB  |  619 lines

  1. unit xmalloc;
  2.  
  3. {
  4.   K&R C 2nd malloc  
  5. }
  6.  
  7. {..$DEFINE REPLACE_MANAGER}
  8. {..$DEFINE HEAP_PROFILE}
  9. {..$DEFINE CONSOLE_TEST}
  10. {$DEFINE HEAP_DECOMMIT}
  11.  
  12. interface
  13.  
  14. uses
  15.   windows;
  16.  
  17. function malloc(nbytes: Integer): Pointer;
  18. function free(ap: Pointer): Integer;
  19. function realloc(ap: Pointer; nbytes: Integer): Pointer;
  20.  
  21. {$IFDEF CONSOLE_TEST}
  22. procedure test;
  23. procedure test2;
  24. procedure test3;
  25. procedure test4;
  26. procedure test5;
  27. procedure test6;
  28. {$ENDIF}
  29.  
  30. implementation
  31.  
  32. type
  33.   PHeader = ^THeader;
  34.   THeader = packed record
  35.     next: PHeader;
  36.     _size: UINT;
  37.   end;
  38.  
  39.   PHeap = ^THeap;
  40.   THeap = record
  41.     heap_base: PHeader;
  42.     heap_reserve: UINT;
  43.     heap_left: Pointer;
  44.   end;
  45.  
  46.   PCore = ^TCore;
  47.   TCore = record
  48.     base: THeader;
  49.     free_p: PHeader;
  50.     heap: PHeap;
  51.   end;
  52.  
  53. const
  54.   _NALIGN = SizeOf(THeader);          //8     8bytesï½èEé╔æ╡éªéΘ
  55.   _NALLOC = 1024 * 64;                //64K   VirtualAllocé═64KÆPê╩
  56.   _NFREEALLOC = _NALLOC * 2;          //128K  îπéδé╔128Ké╠ï≤é½é¬é┼é½é╜éτèJò·
  57.   _NCORE = 128 div 4 - 8;             //24    1byteü`192bytesé╞é╗éΩê╚ì~é≡24é╠free_pé┼è╟ù¥
  58.   _NHEAP = 8;                         //8     16bytesü`64bytesé≡ô┴ò╩ê╡éó
  59.   _NRESERVE = _NALLOC * 1024 div 2;   //32M   16bytesü`64bytesé╔é╗éΩé╝éΩ32MèäéΦôûé─
  60.   _NRESERVE_BIG = _NALLOC * 1024 * 2; //128M  192bytesê╚ì~é╔128MèäéΦôûé─
  61.   
  62.  
  63. var
  64.   cores: array[0..pred(_NCORE)] of TCore;
  65.   heaps: array[0..pred(_NHEAP)] of THeap;
  66.  
  67.   corelock: TRTLCriticalSection;
  68.  
  69. {$IFDEF HEAP_PROFILE}
  70.   ntotal: array[0..pred(_NCORE)] of UINT;
  71. {$ENDIF}
  72.  
  73. {$IFDEF CONSOLE_TEST}
  74.   nblocks: UINT;  
  75. {$ENDIF}
  76.  
  77. function selectcore(size: UINT): PCore;
  78. //8 ü` 192é▄é┼
  79. var
  80.   n: UINT;
  81. begin
  82.   n := size div _NALIGN;
  83.   if n > pred(_NCORE) then
  84.     n := 0;
  85.  
  86.   Result := @cores[n];
  87. end;   
  88.  
  89. procedure malloc_init;
  90. //virtualallocé≡Ägé┴é─æSé─ù\û±
  91. var
  92.   i,n: Integer;
  93. begin
  94.   for i := 0 to pred(_NHEAP) do
  95.   begin
  96.     if i = 0 then
  97.       heaps[i].heap_reserve := _NRESERVE_BIG
  98.     else
  99.       heaps[i].heap_reserve := _NRESERVE;
  100.  
  101.     while True do
  102.     begin
  103.       heaps[i].heap_base :=
  104.         VirtualAlloc(nil,heaps[i].heap_reserve,MEM_RESERVE,PAGE_NOACCESS);
  105.       //reserveé≡î╕éτé╖
  106.       if heaps[i].heap_base = nil then
  107.         heaps[i].heap_reserve := heaps[i].heap_reserve shr 1
  108.       else
  109.         break;
  110.     end;
  111.  
  112.     heaps[i].heap_left := heaps[i].heap_base;
  113.   end;
  114.  
  115.   for i := 0 to pred(_NCORE) do
  116.   begin
  117.     cores[i].base.next := @cores[i].base;
  118.     cores[i].free_p := @cores[i].base;
  119.     cores[i].base._size := 0;
  120.  
  121.     case i of
  122.       0: n := 0;
  123.       2..pred(_NHEAP): n := i - 1;
  124.     else
  125.       n := pred(_NHEAP);  
  126.     end;
  127.  
  128.     cores[i].heap := @heaps[n];
  129.   end;
  130. end;
  131.  
  132. procedure malloc_free;
  133. //âüâéâèèJò·
  134. var
  135.   i: Integer;
  136. begin
  137. {$IFDEF CONSOLE_TEST}
  138.   writeln('blocks: ',nblocks);
  139. {$ENDIF}
  140.   for i := 0 to pred(_NHEAP) do
  141.   begin
  142.     VirtualFree(heaps[i].heap_base,heaps[i].heap_reserve,MEM_DECOMMIT);
  143.     VirtualFree(heaps[i].heap_base,0,MEM_RELEASE);
  144.   end;
  145.  
  146. {$IFDEF HEAP_PROFILE}
  147.   Inc(ntotal[0]);
  148. {$ENDIF}
  149. end;
  150.  
  151. function _free(ap: Pointer; core: PCore): Integer;
  152. //âüâéâèé≡free_pé╔û▀é╖
  153. var
  154.   bp,p: PHeader;
  155.   del,more: Boolean;
  156. begin
  157.   Result := 0;
  158.   //nilé╠ÅΩìçé═ë╜éαé╡é╚éó
  159.   if ap = nil then
  160.     Exit;
  161.  
  162.   EnterCriticalSection(corelock);
  163.   try
  164.     //âwâbâ_é≡ô╛éΘ
  165.     bp := Pointer(UINT(ap) - SizeOf(THeader));
  166.     if core = nil then
  167.     begin
  168.       core := selectcore(bp._size);
  169.       more := False;
  170.     end
  171.     else
  172.       more := True;
  173.       
  174.     p := core.free_p;
  175.     //æ}ôⁿê╩Æup < bp < p.nexté≡ÆTé╖
  176.     //bpé¬pé╞p.nexté╠è╘é╔é╚é»éΩé╬
  177.     while not ((UINT(p) < UINT(bp)) and (UINT(bp) < UINT(p.next))) do
  178.     begin
  179.       if ((UINT(p) >= UINT(p.next)) and  //âuâìâbâNé╠ì┼îπé┼
  180.          //bpé¬péµéΦæσé½éóé▄é╜é═bpé¬nextéµéΦżé│éó
  181.          ((UINT(p) < UINT(bp)) or (UINT(bp) < UINT(p.next)))) then
  182.         break;
  183.  
  184.       //ăé╓
  185.       p := p.next;
  186.     end;
  187.  
  188.     //bpé¬nexté╞É┌é╡é─éóéΘÅΩìç
  189.     if (UINT(bp) + bp._size) = UINT(p.next) then
  190.     begin
  191.       //bpé╞nexté╞ò╣ìç
  192.       bp._size := bp._size + p.next._size;
  193.       bp.next := p.next.next;
  194.  
  195. {$IFDEF HEAP_DECOMMIT}
  196.       //êΩÆΦù╩é≡èJò·é╖éΘ
  197.       if (not more) and (bp._size >= _NFREEALLOC) and
  198.          ((UINT(bp) + bp._size) = UINT(core.heap.heap_left)) then
  199.       begin
  200.   {$IFDEF CONSOLE_TEST}
  201.         writeln('free: ',UINT(bp),' ',_NFREEALLOC);
  202.         Dec(nblocks);
  203.   {$ENDIF}
  204.         if bp._size = _NFREEALLOC then
  205.         begin
  206.           //bpé═Å┴û┼é╖éΘ
  207.           p.next := bp.next;
  208.           del := True;
  209.         end
  210.         else begin
  211.           bp._size := bp._size - _NFREEALLOC;
  212.           del := False;
  213.         end; 
  214.  
  215.         UINT(core.heap.heap_left) := UINT(core.heap.heap_left) - _NFREEALLOC;
  216.         VirtualFree(core.heap.heap_left,_NFREEALLOC,MEM_DECOMMIT);
  217.  
  218.         if del then
  219.         begin
  220.           //if core = @cores[0] then
  221.             //core.free_p := p;
  222.  
  223.           Exit;
  224.         end;        
  225.       end;
  226. {$ENDIF}
  227.     end
  228.     else //É┌é╡é─éóé╚éóÅΩìçé═æ}ôⁿ
  229.       bp.next := p.next;
  230.  
  231.     //pé╞bpé¬É┌é╡é─éóéΘÅΩìç
  232.     if (UINT(p) + p._size) = UINT(bp) then
  233.     begin
  234.       //pé╞bpé≡ò╣ìç
  235.       p._size := p._size + bp._size;
  236.       p.next := bp.next;
  237.     end
  238.     else//É┌é╡é─éóé╚éóÅΩìçé═æ}ôⁿ
  239.       p.next := bp;
  240.  
  241. {$IFDEF HEAP_DECOMMIT}
  242.     if (not more) and (p._size > _NFREEALLOC) and
  243.        ((UINT(p) + p._size) = UINT(core.heap.heap_left)) then
  244.     begin
  245.       UINT(core.heap.heap_left) := UINT(core.heap.heap_left) - _NFREEALLOC;
  246.       p._size := p._size - _NFREEALLOC;
  247.       VirtualFree(core.heap.heap_left,_NFREEALLOC,MEM_DECOMMIT);
  248.  
  249.   {$IFDEF CONSOLE_TEST}
  250.       writeln('free: ',UINT(p),' ',_NFREEALLOC);
  251.       Dec(nblocks);
  252.   {$ENDIF}
  253.     end;
  254. {$ENDIF}
  255.     //if core = @cores[0] then
  256.       //core.free_p := p;
  257.   finally
  258.     LeaveCriticalSection(corelock);
  259.   end;
  260. end;
  261.  
  262. function morecore(size: UINT): PHeader;
  263. //virtualallocé⌐éτâüâéâèé≡commit
  264. var
  265.   p: PHeader;
  266.   n: UINT;
  267.   c: PCore;
  268. begin
  269.   c := selectcore(size);
  270.   //ì┼ÆßâTâCâYé╔æ╡éªéΘ
  271.   n := (size - 1) div _NALLOC + 1;
  272.   size := n * _NALLOC;    
  273.  
  274.   p := VirtualAlloc(c.heap.heap_left,size,MEM_COMMIT,PAGE_READWRITE);
  275.  
  276.   ASSERT(p = c.heap.heap_left);
  277.  
  278. {$IFDEF CONSOLE_TEST}
  279.   writeln(UINT(p),' ',size);
  280.   Inc(nblocks);
  281. {$ENDIF}
  282.  
  283.   //ì╢Æ[é≡ê┌ô«
  284.   UINT(c.heap.heap_left) := UINT(c.heap.heap_left) + size;
  285.  
  286.   p._size := size;
  287.   //âüâéâèé≡âèâXâgé╔æ}ôⁿ
  288.   _free(POINTER(UINT(p) + SizeOf(THeader)),c);
  289.   Result := p;
  290. end;
  291.  
  292. function malloc(nbytes: Integer): Pointer;
  293. var
  294.   p,prev_p: PHeader;
  295.   nu,size: UINT;
  296.   c: PCore;
  297. begin
  298.   EnterCriticalSection(corelock);
  299.   try
  300.     //âwâbâ_é≡è▄é▀é╜sizeé≡ô╛éΘ
  301.     nu := (nbytes + sizeOf(THeader) - 1) div _NALIGN + 1; //aligné≡æ╡éªéΘ
  302.     size := nu * _NALIGN;
  303.     if nu > pred(_NCORE) then
  304.       nu := 0;
  305.  
  306.     c := @cores[nu];
  307.     //c := selectcore(size);
  308. {$IFDEF HEAP_PROFILE}
  309.     Inc(ntotal[nu]);
  310. {$ENDIF}     
  311.  
  312.     prev_p := c.free_p;
  313.     p := prev_p.next;
  314.  
  315.     //first fit
  316.     while True do
  317.     begin
  318.       //Å\ò¬é╔æσé½éó
  319.       if p._size >= size then
  320.       begin
  321.         //é╥é┴é╜éΦ
  322.         if p._size = size then
  323.           prev_p.next := p.next //îJéΦÅπé░
  324.         else begin
  325.           //âüâéâèé╠ì╢é⌐éτÉ╪éΦÅoé╖
  326.           prev_p.next := POINTER(UINT(p) + size);
  327.           prev_p.next.next := p.next;
  328.           //âTâCâYÆ▓É«
  329.           prev_p.next._size := p._size - size;
  330.           p._size := size;
  331.         end;
  332.         //Ägùpâüâéâèé╠ɵô¬é≡ò╘é╖
  333.         //if c = @cores[0] then
  334.         //  c.free_p := prev_p;
  335.           
  336.         Result := Pointer(UINT(p) + SizeOf(THeader));
  337.         Exit;
  338.       end;
  339.  
  340.       if p = c.free_p then
  341.       begin
  342.         morecore(size);
  343.         p := c.free_p;
  344.       end;
  345.  
  346.       //ăé╓
  347.       prev_p := p;
  348.       p := p.next;
  349.     end;
  350.  
  351.   finally
  352.     LeaveCriticalSection(corelock);
  353.   end;
  354. end;
  355.  
  356. function free(ap: Pointer): Integer;
  357. begin
  358.   Result := _free(ap,nil);
  359. end;
  360.  
  361. function realloc(ap: Pointer; nbytes: Integer): Pointer;
  362. var
  363.   bp: PHeader;
  364.   nu,size: UINT;
  365. begin
  366.   EnterCriticalSection(corelock);
  367.   try
  368.     //nilé╠ÅΩìç
  369.     if ap = nil then
  370.     begin
  371.       if nbytes > 0 then
  372.         Result := malloc(nbytes)
  373.       else
  374.         Result := nil;
  375.  
  376.       Exit;
  377.     end
  378.     else if nbytes = 0 then
  379.     begin
  380.       free(ap);
  381.       Result := nil;
  382.       Exit;
  383.     end;   
  384.   
  385.     //âwâbâ_é≡è▄é▀é╜sizeé≡ô╛éΘ
  386.     nu := (nbytes + sizeOf(THeader) - 1) div _NALIGN + 1; //aligné≡æ╡éªéΘ
  387.     size := nu * _NALIGN;
  388.     //âwâbâ_é≡ô╛éΘ
  389.     bp := Pointer(UINT(ap) - SizeOf(THeader));
  390.     //î│é¬æσé½éóÅΩìçé═é╗é╠é▄é▄ò╘é╖
  391.     if bp._size >= size then
  392.       Result := ap
  393.     else begin
  394.       Result := malloc(nbytes);
  395.       //âwâbâ_ò¬é≡î╕éτé╡é─âRâsü[
  396.       move(ap^,Result^,bp._size - SizeOf(THeader));
  397.       free(ap);
  398.     end;
  399.   finally
  400.     LeaveCriticalSection(corelock);
  401.   end;
  402. end;
  403.  
  404. {$IFDEF REPLACE_MANAGER}
  405. var
  406.   oldmgr: TMemoryManager;
  407.   
  408. const
  409.   newmgr: TMemoryManager =
  410.   (
  411.     GetMem: malloc;
  412.     FreeMem: free;
  413.     ReAllocMem: realloc;
  414.   );
  415.  
  416. procedure memorymanager_init;
  417. begin
  418.   GetMemoryManager(oldmgr);
  419.   SetMemoryManager(newmgr);
  420. end;
  421.  
  422. procedure memorymanager_free;
  423. begin
  424.   SetMemoryManager(oldmgr);
  425. end;
  426. {$ENDIF}
  427.  
  428.  
  429. {$IFDEF CONSOLE_TEST}
  430. type
  431.   PItem = ^TItem;
  432.   TItem = record
  433.     next: PItem;
  434.     p: Pointer;
  435.   end;
  436.  
  437. procedure test6;
  438. var
  439.   x,y: Integer;
  440.   a,b,nxt: PItem;
  441. begin
  442.   writeln('test6');
  443.  
  444.   for x := 0 to 10000 div 2 do
  445.   begin
  446.     a := nil;
  447.  
  448.     for y := 0 to Random(2550) do
  449.     begin
  450.       b := malloc(SizeOf(TItem));
  451.       b.p := malloc(Random(2550));
  452.  
  453.       b.next := a;
  454.       a := b;
  455.  
  456.       b := malloc(SizeOf(TItem));
  457.       b.p := malloc(Random(128));
  458.  
  459.       b.next := a;
  460.       a := b;
  461.     end;
  462.  
  463.     while a <> nil do
  464.     begin
  465.       nxt := a.next;
  466.       free(a.p);
  467.       free(a);
  468.       a := nxt;
  469.     end;
  470.   end;
  471. end;
  472.  
  473.  
  474. procedure test5;
  475. var
  476.   a,b,c,d,e: pointer;
  477.   i: Integer;
  478. begin
  479.   writeln('test5');
  480.  
  481.   for i := 0 to 1000000 do
  482.   begin
  483.     a := malloc(8);
  484.     b := malloc(255);
  485.     c := malloc(65535);
  486.     //d := malloc(65535 * 2);
  487.     e := malloc(10);
  488.  
  489.     free(e);
  490.     //free(d);
  491.     free(c);
  492.     free(b);
  493.     free(a);
  494.   end;
  495. end;
  496.  
  497. procedure test;
  498. var
  499.   a,b,c,d,e: pointer;
  500.   i: Integer;
  501. begin
  502.   writeln('test');
  503.  
  504.   for i := 0 to 1000000 do
  505.   begin
  506.     a := malloc(Random(8));
  507.     b := malloc(Random(255));
  508.     c := malloc(Random(65535));
  509.     //d := malloc(Random(65535 * 2));
  510.     e := malloc(Random(10));
  511.  
  512.     a := realloc(a,10);
  513.  
  514.     free(e);
  515.     //free(d);
  516.     free(c);
  517.     free(b);
  518.     free(a);
  519.   end;
  520. end;
  521.  
  522. procedure test3;
  523. var
  524.   a,b,c,d,e: pointer;
  525.   i: Integer;
  526. begin
  527.   writeln('test3');
  528.  
  529.   for i := 0 to 1000000 do
  530.   begin
  531.     a := malloc(20);
  532.     b := malloc(20);
  533.     c := malloc(20);
  534.     d := malloc(20);
  535.     e := malloc(20);
  536.  
  537.     a := realloc(a,20);
  538.     b := realloc(b,10);
  539.     c := realloc(c,30);
  540.  
  541.     free(e);
  542.     free(d);
  543.     free(c);
  544.     free(b);
  545.     free(a);
  546.   end;
  547. end;
  548.  
  549. procedure test4;
  550. var
  551.   a,b,c,d,e: pointer;
  552.   i: Integer;
  553. begin
  554.   writeln('test4');
  555.  
  556.   for i := 0 to 1000000 do
  557.   begin
  558.     a := malloc(Random(65536));
  559.     free(a);
  560.  
  561.     b := malloc(Random(65536));
  562.     free(b);
  563.  
  564.     c := malloc(Random(65536));
  565.     free(c);
  566.  
  567.     d := malloc(Random(65536));
  568.     free(d);
  569.  
  570.     e := malloc(Random(65536));
  571.     free(e);
  572.  
  573.     //free(e);
  574.     //free(d);
  575.     //free(c);
  576.     //free(b);
  577.     //free(a);
  578.   end;
  579. end;
  580.  
  581. procedure test2;
  582. var
  583.   a,b,c,d,e: pointer;
  584.   i: Integer;
  585. begin
  586.   writeln('test2');
  587.  
  588.   for i := 0 to 1000000 do
  589.   begin
  590.     GetMem(a,8);
  591.     GetMem(b,255);
  592.     GetMem(c,65535);
  593.     GetMem(d,65535 * 2);
  594.     GetMem(e,10);
  595.  
  596.     freeMem(e);
  597.     freeMem(d);
  598.     freeMem(c);
  599.     freeMem(b);
  600.     freeMem(a);
  601.   end;
  602. end;
  603.  
  604. {$ENDIF}
  605.  
  606. initialization
  607.   InitializeCriticalSection(corelock);
  608. {$IFDEF REPLACE_MANAGER}
  609.   memorymanager_init;
  610. {$ENDIF}
  611.   malloc_init;
  612. finalization    
  613.   malloc_free;
  614. {$IFDEF REPLACE_MANAGER}
  615.   memorymanager_free;
  616. {$ENDIF}
  617.   DeleteCriticalSection(corelock);
  618.   
  619. end.