home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 9 / 09.iso / l / l040 / 13.ddi / RTLTV.ZIP / MEMORY.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-10-28  |  11.1 KB  |  585 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Turbo Pascal Version 7.0                        }
  5. {       Turbo Vision Unit                               }
  6. {                                                       }
  7. {       Copyright (c) 1992 Borland International        }
  8. {                                                       }
  9. {*******************************************************}
  10.  
  11. unit Memory;
  12.  
  13. {$O+,F+,X+,I-,S-,Q-}
  14.  
  15. interface
  16.  
  17. const
  18.   MaxHeapSize: Word = 655360 div 16;    { 640K }
  19.   LowMemSize: Word = 4096 div 16;       {   4K }
  20.   MaxBufMem: Word = 65536 div 16;       {  64K }
  21.  
  22. procedure InitMemory;
  23. procedure DoneMemory;
  24. procedure InitDosMem;
  25. procedure DoneDosMem;
  26. function LowMemory: Boolean;
  27. function MemAlloc(Size: Word): Pointer;
  28. function MemAllocSeg(Size: Word): Pointer;
  29. procedure NewCache(var P: Pointer; Size: Word);
  30. procedure DisposeCache(P: Pointer);
  31. procedure NewBuffer(var P: Pointer; Size: Word);
  32. procedure DisposeBuffer(P: Pointer);
  33. function GetBufferSize(P: Pointer): Word;
  34. function SetBufferSize(P: Pointer; Size: Word): Boolean;
  35.  
  36. {$IFNDEF DPMI}
  37.  
  38. procedure GetBufMem(var P: Pointer; Size: Word);
  39. procedure FreeBufMem(P: Pointer);
  40. procedure SetMemTop(MemTop: Pointer);
  41.  
  42. {$ENDIF}
  43.  
  44. implementation
  45.  
  46. type
  47.   PtrRec = record
  48.     Ofs, Seg: Word;
  49.   end;
  50.  
  51. {$IFDEF DPMI}
  52.  
  53. type
  54.   PCache = ^TCache;
  55.   TCache = record
  56.     Next: PCache;
  57.     Master: ^Pointer;
  58.     Data: record end;
  59.   end;
  60.  
  61. const
  62.   CacheList: PCache = nil;
  63.   SafetyPool: Pointer = nil;
  64.   SafetyPoolSize: Word = 0;
  65.   DisablePool: Boolean = False;
  66.  
  67. function MemAllocateBlock(HeapHandle, Size, Attributes: Word;
  68.   EventProc: Pointer; var Selector: Word): Integer; far;
  69. external 'RTM' index $0005;
  70.  
  71. function MemFreeBlock(Selector: Word): Integer; far;
  72. external 'RTM' index $0006;
  73.  
  74. function MemResizeBlock(Selector: Word; Size: Word): Integer; far;
  75. external 'RTM' index $0007;
  76.  
  77. function MemGetBlockSize(Selector: Word; var Size: Longint): Integer; far;
  78. external 'RTM' index $0014;
  79.  
  80. function FreeCache: Boolean;
  81. begin
  82.   FreeCache := False;
  83.   if CacheList <> nil then
  84.   begin
  85.     DisposeCache(CacheList^.Next^.Master^);
  86.     FreeCache := True;
  87.   end;
  88. end;
  89.  
  90. function FreeSafetyPool: Boolean;
  91. begin
  92.   FreeSafetyPool := False;
  93.   if SafetyPool <> nil then
  94.   begin
  95.     FreeMem(SafetyPool, SafetyPoolSize);
  96.     SafetyPool := nil;
  97.     FreeSafetyPool := True;
  98.   end;
  99. end;
  100.  
  101. function HeapNotify(Size: Word): Integer; far;
  102. begin
  103.   if FreeCache then HeapNotify := 2 else
  104.     if DisablePool then HeapNotify := 1 else
  105.       if FreeSafetyPool then HeapNotify := 2 else HeapNotify := 0;
  106. end;
  107.  
  108. procedure InitMemory;
  109. begin
  110.   HeapError := @HeapNotify;
  111.   SafetyPoolSize := LowMemSize * 16;
  112.   LowMemory;
  113. end;
  114.  
  115. procedure DoneMemory;
  116. begin
  117.   while FreeCache do;
  118.   FreeSafetyPool;
  119. end;
  120.  
  121. procedure InitDosMem;
  122. begin
  123. end;
  124.  
  125. procedure DoneDosMem;
  126. begin
  127. end;
  128.  
  129. function LowMemory: Boolean;
  130. begin
  131.   LowMemory := False;
  132.   if SafetyPool = nil then
  133.   begin
  134.     SafetyPool := MemAlloc(SafetyPoolSize);
  135.     if SafetyPool = nil then LowMemory := True;
  136.   end;
  137. end;
  138.  
  139. function MemAlloc(Size: Word): Pointer;
  140. var
  141.   P: Pointer;
  142. begin
  143.   DisablePool := True;
  144.   GetMem(P, Size);
  145.   DisablePool := False;
  146.   MemAlloc := P;
  147. end;
  148.  
  149. function MemAllocSeg(Size: Word): Pointer;
  150. var
  151.   Selector: Word;
  152. begin
  153.   Selector := 0;
  154.   if Size <> 0 then
  155.     repeat
  156.       if MemAllocateBlock(0, Size, 2, nil, Selector) <> 0 then
  157.         Selector := 0;
  158.     until (Selector <> 0) or not FreeCache;
  159.   MemAllocSeg := Ptr(Selector, 0);
  160. end;
  161.  
  162. procedure NewCache(var P: Pointer; Size: Word);
  163. var
  164.   Cache: PCache;
  165. begin
  166.   Inc(Size, SizeOf(TCache));
  167.   PtrRec(Cache).Ofs := 0;
  168.   if MemAllocateBlock(0, Size, 4, nil, PtrRec(Cache).Seg) <> 0 then
  169.     PtrRec(Cache).Seg := 0;
  170.   if Cache <> nil then
  171.   begin
  172.     if CacheList = nil then Cache^.Next := Cache else
  173.     begin
  174.       Cache^.Next := CacheList^.Next;
  175.       CacheList^.Next := Cache;
  176.     end;
  177.     CacheList := Cache;
  178.     Cache^.Master := @P;
  179.     Inc(PtrRec(Cache).Ofs, SizeOf(TCache));
  180.   end;
  181.   P := Cache;
  182. end;
  183.  
  184. procedure DisposeCache(P: Pointer);
  185. var
  186.   Cache, C: PCache;
  187. begin
  188.   PtrRec(Cache).Ofs := PtrRec(P).Ofs - SizeOf(TCache);
  189.   PtrRec(Cache).Seg := PtrRec(P).Seg;
  190.   C := CacheList;
  191.   while (C^.Next <> Cache) and (C^.Next <> CacheList) do C := C^.Next;
  192.   if C^.Next = Cache then
  193.   begin
  194.     if C = Cache then CacheList := nil else
  195.     begin
  196.       if CacheList = Cache then CacheList := C;
  197.       C^.Next := Cache^.Next;
  198.     end;
  199.     Cache^.Master^ := nil;
  200.     MemFreeBlock(PtrRec(Cache).Seg);
  201.   end;
  202. end;
  203.  
  204. procedure NewBuffer(var P: Pointer; Size: Word);
  205. begin
  206.   P := MemAllocSeg(Size);
  207. end;
  208.  
  209. procedure DisposeBuffer(P: Pointer);
  210. begin
  211.   MemFreeBlock(PtrRec(P).Seg);
  212. end;
  213.  
  214. function GetBufferSize(P: Pointer): Word;
  215. var
  216.   Size: Longint;
  217. begin
  218.   if MemGetBlockSize(PtrRec(P).Seg, Size) <> 0 then Size := 0;
  219.   GetBufferSize := Size;
  220. end;
  221.  
  222. function SetBufferSize(P: Pointer; Size: Word): Boolean;
  223. begin
  224.   SetBufferSize := MemResizeBlock(PtrRec(P).Seg, Size) = 0;
  225. end;
  226.  
  227. {$ELSE}
  228.  
  229. type
  230.   PCache = ^TCache;
  231.   TCache = record
  232.     Size: Word;
  233.     Master: ^Pointer;
  234.     Data: record end;
  235.   end;
  236.  
  237. type
  238.   PBuffer = ^TBuffer;
  239.   TBuffer = record
  240.     Size: Word;
  241.     Master: ^Word;
  242.   end;
  243.  
  244. const
  245.   CachePtr: Pointer = nil;
  246.   HeapResult: Integer = 0;
  247.   BufHeapPtr: Word = 0;
  248.   BufHeapEnd: Word = 0;
  249.  
  250. function HeapNotify(Size: Word): Integer; far; assembler;
  251. asm
  252.     CMP    Size,0
  253.     JNE    @@3
  254. @@1:    MOV    AX,CachePtr.Word[2]
  255.     CMP    AX,HeapPtr.Word[2]
  256.     JA    @@3
  257.     JB    @@2
  258.     MOV    AX,CachePtr.Word[0]
  259.     CMP    AX,HeapPtr.Word[0]
  260.     JAE    @@3
  261. @@2:    XOR    AX,AX
  262.     PUSH    AX
  263.     PUSH    AX
  264.     CALL    DisposeCache
  265.     JMP    @@1
  266. @@3:    MOV    AX,HeapResult
  267. end;
  268.  
  269. procedure FreeCacheMem;
  270. begin
  271.   while CachePtr <> HeapEnd do DisposeCache(CachePtr);
  272. end;
  273.  
  274. procedure InitMemory;
  275. var
  276.   HeapSize: Word;
  277. begin
  278.   HeapError := @HeapNotify;
  279.   if BufHeapPtr = 0 then
  280.   begin
  281.     HeapSize := PtrRec(HeapEnd).Seg - PtrRec(HeapOrg).Seg;
  282.     if HeapSize > MaxHeapSize then HeapSize := MaxHeapSize;
  283.     BufHeapEnd := PtrRec(HeapEnd).Seg;
  284.     PtrRec(HeapEnd).Seg := PtrRec(HeapOrg).Seg + HeapSize;
  285.     BufHeapPtr := PtrRec(HeapEnd).Seg;
  286.   end;
  287.   CachePtr := HeapEnd;
  288. end;
  289.  
  290. procedure DoneMemory;
  291. begin
  292.   FreeCacheMem;
  293. end;
  294.  
  295. procedure InitDosMem;
  296. begin
  297.   SetMemTop(Ptr(BufHeapEnd, 0));
  298. end;
  299.  
  300. procedure DoneDosMem;
  301. var
  302.   MemTop: Pointer;
  303. begin
  304.   MemTop := Ptr(BufHeapPtr, 0);
  305.   if BufHeapPtr = PtrRec(HeapEnd).Seg then
  306.   begin
  307.     FreeCacheMem;
  308.     MemTop := HeapPtr;
  309.   end;
  310.   SetMemTop(MemTop);
  311. end;
  312.  
  313. function LowMemory: Boolean; assembler;
  314. asm
  315.     MOV    AX,HeapEnd.Word[2]
  316.     SUB    AX,HeapPtr.Word[2]
  317.     SUB    AX,LowMemSize
  318.     SBB    AX,AX
  319.     NEG    AX
  320. end;
  321.  
  322. function MemAlloc(Size: Word): Pointer;
  323. var
  324.   P: Pointer;
  325. begin
  326.   HeapResult := 1;
  327.   GetMem(P, Size);
  328.   HeapResult := 0;
  329.   if (P <> nil) and LowMemory then
  330.   begin
  331.     FreeMem(P, Size);
  332.     P := nil;
  333.   end;
  334.   MemAlloc := P;
  335. end;
  336.  
  337. function MemAllocSeg(Size: Word): Pointer;
  338. var
  339.   P, T: Pointer;
  340. begin
  341.   Size := (Size + 7) and $FFF8;
  342.   P := MemAlloc(Size + 8);
  343.   if P <> nil then
  344.   begin
  345.     if PtrRec(P).Ofs = 0 then
  346.     begin
  347.       PtrRec(T).Ofs := Size and 15;
  348.       PtrRec(T).Seg := PtrRec(P).Seg + Size shr 4;
  349.     end else
  350.     begin
  351.       T := P;
  352.       PtrRec(P).Ofs := 0;
  353.       Inc(PtrRec(P).Seg);
  354.     end;
  355.     FreeMem(T, 8);
  356.   end;
  357.   MemAllocSeg := P;
  358. end;
  359.  
  360. procedure NewCache(var P: Pointer; Size: Word); assembler;
  361. asm
  362.     LES    DI,P
  363.     MOV    AX,Size
  364.     ADD    AX,(TYPE TCache)+15
  365.     MOV    CL,4
  366.     SHR    AX,CL
  367.     MOV    DX,CachePtr.Word[2]
  368.     SUB    DX,AX
  369.     JC    @@1
  370.     CMP    DX,HeapPtr.Word[2]
  371.     JBE    @@1
  372.     MOV     CX,HeapEnd.Word[2]
  373.     SUB    CX,DX
  374.     CMP    CX,MaxBufMem
  375.     JA    @@1
  376.     MOV    CachePtr.Word[2],DX
  377.     PUSH    DS
  378.     MOV    DS,DX
  379.     XOR    SI,SI
  380.     MOV    DS:[SI].TCache.Size,AX
  381.     MOV    DS:[SI].TCache.Master.Word[0],DI
  382.     MOV    DS:[SI].TCache.Master.Word[2],ES
  383.     POP    DS
  384.     MOV    AX,OFFSET TCache.Data
  385.     JMP    @@2
  386. @@1:    XOR    AX,AX
  387.     CWD
  388. @@2:    CLD
  389.     STOSW
  390.     XCHG    AX,DX
  391.     STOSW
  392. end;
  393.  
  394. procedure DisposeCache(P: Pointer); assembler;
  395. asm
  396.     MOV    AX,CachePtr.Word[2]
  397.     XOR    BX,BX
  398.     XOR    CX,CX
  399.     MOV    DX,P.Word[2]
  400. @@1:    MOV    ES,AX
  401.     CMP    AX,DX
  402.     JE    @@2
  403.     ADD    AX,ES:[BX].TCache.Size
  404.     CMP    AX,HeapEnd.Word[2]
  405.     JE    @@2
  406.     PUSH    ES
  407.     INC    CX
  408.     JMP    @@1
  409. @@2:    PUSH    ES
  410.     LES    DI,ES:[BX].TCache.Master
  411.     XOR    AX,AX
  412.     CLD
  413.     STOSW
  414.     STOSW
  415.     POP    ES
  416.     MOV    AX,ES:[BX].TCache.Size
  417.     JCXZ    @@4
  418. @@3:    POP    DX
  419.     PUSH    DS
  420.     PUSH    CX
  421.     MOV    DS,DX
  422.     ADD    DX,AX
  423.     MOV    ES,DX
  424.     MOV    SI,DS:[BX].TCache.Size
  425.     MOV    CL,3
  426.     SHL    SI,CL
  427.     MOV    CX,SI
  428.     SHL    SI,1
  429.     DEC    SI
  430.     DEC    SI
  431.     MOV    DI,SI
  432.     STD
  433.     REP    MOVSW
  434.     LDS    SI,ES:[BX].TCache.Master
  435.     MOV    DS:[SI].Word[2],ES
  436.     POP    CX
  437.     POP    DS
  438.     LOOP    @@3
  439. @@4:    ADD    CachePtr.Word[2],AX
  440. end;
  441.  
  442. procedure MoveSeg(Source, Dest, Size: Word); near; assembler;
  443. asm
  444.     PUSH    DS
  445.     MOV    AX,Source
  446.     MOV    DX,Dest
  447.     MOV    BX,Size
  448.     CMP    AX,DX
  449.     JB    @@3
  450.     CLD
  451. @@1:    MOV    CX,0FFFH
  452.     CMP    CX,BX
  453.     JB    @@2
  454.     MOV    CX,BX
  455. @@2:    MOV    DS,AX
  456.     MOV    ES,DX
  457.     ADD    AX,CX
  458.     ADD    DX,CX
  459.     SUB    BX,CX
  460.     SHL    CX,1
  461.     SHL    CX,1
  462.     SHL    CX,1
  463.     XOR    SI,SI
  464.     XOR    DI,DI
  465.     REP    MOVSW
  466.     OR    BX,BX
  467.     JNE    @@1
  468.     JMP    @@6
  469. @@3:    ADD    AX,BX
  470.     ADD    DX,BX
  471.     STD
  472. @@4:    MOV    CX,0FFFH
  473.     CMP    CX,BX
  474.     JB    @@5
  475.     MOV    CX,BX
  476. @@5:    SUB    AX,CX
  477.     SUB    DX,CX
  478.     SUB    BX,CX
  479.     MOV    DS,AX
  480.     MOV    ES,DX
  481.     SHL    CX,1
  482.     SHL    CX,1
  483.     SHL    CX,1
  484.     MOV    SI,CX
  485.     DEC    SI
  486.     SHL    SI,1
  487.     MOV    DI,SI
  488.     REP    MOVSW
  489.     OR    BX,BX
  490.     JNE    @@4
  491. @@6:    POP    DS
  492. end;
  493.  
  494. function GetBufSize(P: PBuffer): Word;
  495. begin
  496.   GetBufSize := (P^.Size + 15) shr 4 + 1;
  497. end;
  498.  
  499. procedure SetBufSize(P: PBuffer; NewSize: Word);
  500. var
  501.   CurSize: Word;
  502. begin
  503.   CurSize := GetBufSize(P);
  504.   MoveSeg(PtrRec(P).Seg + CurSize, PtrRec(P).Seg + NewSize,
  505.     BufHeapPtr - PtrRec(P).Seg - CurSize);
  506.   Inc(BufHeapPtr, NewSize - CurSize);
  507.   Inc(PtrRec(P).Seg, NewSize);
  508.   while PtrRec(P).Seg < BufHeapPtr do
  509.   begin
  510.     Inc(P^.Master^, NewSize - CurSize);
  511.     Inc(PtrRec(P).Seg, (P^.Size + 15) shr 4 + 1);
  512.   end;
  513. end;
  514.  
  515. procedure NewBuffer(var P: Pointer; Size: Word);
  516. var
  517.   BufSize: Word;
  518.   Buffer: PBuffer;
  519. begin
  520.   BufSize := (Size + 15) shr 4 + 1;
  521.   if BufHeapPtr + BufSize > BufHeapEnd then P := nil else
  522.   begin
  523.     Buffer := Ptr(BufHeapPtr, 0);
  524.     Buffer^.Size := Size;
  525.     Buffer^.Master := @PtrRec(P).Seg;
  526.     P := Ptr(BufHeapPtr + 1, 0);
  527.     Inc(BufHeapPtr, BufSize);
  528.   end;
  529. end;
  530.  
  531. procedure DisposeBuffer(P: Pointer);
  532. begin
  533.   Dec(PtrRec(P).Seg);
  534.   SetBufSize(P, 0);
  535. end;
  536.  
  537. function GetBufferSize(P: Pointer): Word;
  538. begin
  539.   Dec(PtrRec(P).Seg);
  540.   GetBufferSize := PBuffer(P)^.Size;
  541. end;
  542.  
  543. function SetBufferSize(P: Pointer; Size: Word): Boolean;
  544. var
  545.   NewSize: Word;
  546. begin
  547.   Dec(PtrRec(P).Seg);
  548.   NewSize := (Size + 15) shr 4 + 1;
  549.   SetBufferSize := False;
  550.   if BufHeapPtr + NewSize - GetBufSize(P) <= BufHeapEnd then
  551.   begin
  552.     SetBufSize(P, NewSize);
  553.     PBuffer(P)^.Size := Size;
  554.     SetBufferSize := True;
  555.   end;
  556. end;
  557.  
  558. procedure GetBufMem(var P: Pointer; Size: Word);
  559. begin
  560.   NewCache(P, Size);
  561. end;
  562.  
  563. procedure FreeBufMem(P: Pointer);
  564. begin
  565.   DisposeCache(P);
  566. end;
  567.  
  568. procedure SetMemTop(MemTop: Pointer); assembler;
  569. asm
  570.     MOV    BX,MemTop.Word[0]
  571.     ADD    BX,15
  572.     MOV    CL,4
  573.     SHR    BX,CL
  574.     ADD    BX,MemTop.Word[2]
  575.     MOV    AX,PrefixSeg
  576.     SUB    BX,AX
  577.     MOV    ES,AX
  578.     MOV    AH,4AH
  579.     INT    21H
  580. end;
  581.  
  582. {$ENDIF}
  583.  
  584. end.
  585.