home *** CD-ROM | disk | FTP | other *** search
-
- {*******************************************************}
- { }
- { Turbo Pascal Version 7.0 }
- { Turbo Vision Unit }
- { }
- { Copyright (c) 1992 Borland International }
- { }
- {*******************************************************}
-
- unit Memory;
-
- {$O+,F+,X+,I-,S-,Q-}
-
- interface
-
- const
- MaxHeapSize: Word = 655360 div 16; { 640K }
- LowMemSize: Word = 4096 div 16; { 4K }
- MaxBufMem: Word = 65536 div 16; { 64K }
-
- procedure InitMemory;
- procedure DoneMemory;
- procedure InitDosMem;
- procedure DoneDosMem;
- function LowMemory: Boolean;
- function MemAlloc(Size: Word): Pointer;
- function MemAllocSeg(Size: Word): Pointer;
- procedure NewCache(var P: Pointer; Size: Word);
- procedure DisposeCache(P: Pointer);
- procedure NewBuffer(var P: Pointer; Size: Word);
- procedure DisposeBuffer(P: Pointer);
- function GetBufferSize(P: Pointer): Word;
- function SetBufferSize(P: Pointer; Size: Word): Boolean;
-
- {$IFNDEF DPMI}
-
- procedure GetBufMem(var P: Pointer; Size: Word);
- procedure FreeBufMem(P: Pointer);
- procedure SetMemTop(MemTop: Pointer);
-
- {$ENDIF}
-
- implementation
-
- type
- PtrRec = record
- Ofs, Seg: Word;
- end;
-
- {$IFDEF DPMI}
-
- type
- PCache = ^TCache;
- TCache = record
- Next: PCache;
- Master: ^Pointer;
- Data: record end;
- end;
-
- const
- CacheList: PCache = nil;
- SafetyPool: Pointer = nil;
- SafetyPoolSize: Word = 0;
- DisablePool: Boolean = False;
-
- function MemAllocateBlock(HeapHandle, Size, Attributes: Word;
- EventProc: Pointer; var Selector: Word): Integer; far;
- external 'RTM' index $0005;
-
- function MemFreeBlock(Selector: Word): Integer; far;
- external 'RTM' index $0006;
-
- function MemResizeBlock(Selector: Word; Size: Word): Integer; far;
- external 'RTM' index $0007;
-
- function MemGetBlockSize(Selector: Word; var Size: Longint): Integer; far;
- external 'RTM' index $0014;
-
- function FreeCache: Boolean;
- begin
- FreeCache := False;
- if CacheList <> nil then
- begin
- DisposeCache(CacheList^.Next^.Master^);
- FreeCache := True;
- end;
- end;
-
- function FreeSafetyPool: Boolean;
- begin
- FreeSafetyPool := False;
- if SafetyPool <> nil then
- begin
- FreeMem(SafetyPool, SafetyPoolSize);
- SafetyPool := nil;
- FreeSafetyPool := True;
- end;
- end;
-
- function HeapNotify(Size: Word): Integer; far;
- begin
- if FreeCache then HeapNotify := 2 else
- if DisablePool then HeapNotify := 1 else
- if FreeSafetyPool then HeapNotify := 2 else HeapNotify := 0;
- end;
-
- procedure InitMemory;
- begin
- HeapError := @HeapNotify;
- SafetyPoolSize := LowMemSize * 16;
- LowMemory;
- end;
-
- procedure DoneMemory;
- begin
- while FreeCache do;
- FreeSafetyPool;
- end;
-
- procedure InitDosMem;
- begin
- end;
-
- procedure DoneDosMem;
- begin
- end;
-
- function LowMemory: Boolean;
- begin
- LowMemory := False;
- if SafetyPool = nil then
- begin
- SafetyPool := MemAlloc(SafetyPoolSize);
- if SafetyPool = nil then LowMemory := True;
- end;
- end;
-
- function MemAlloc(Size: Word): Pointer;
- var
- P: Pointer;
- begin
- DisablePool := True;
- GetMem(P, Size);
- DisablePool := False;
- MemAlloc := P;
- end;
-
- function MemAllocSeg(Size: Word): Pointer;
- var
- Selector: Word;
- begin
- Selector := 0;
- if Size <> 0 then
- repeat
- if MemAllocateBlock(0, Size, 2, nil, Selector) <> 0 then
- Selector := 0;
- until (Selector <> 0) or not FreeCache;
- MemAllocSeg := Ptr(Selector, 0);
- end;
-
- procedure NewCache(var P: Pointer; Size: Word);
- var
- Cache: PCache;
- begin
- Inc(Size, SizeOf(TCache));
- PtrRec(Cache).Ofs := 0;
- if MemAllocateBlock(0, Size, 4, nil, PtrRec(Cache).Seg) <> 0 then
- PtrRec(Cache).Seg := 0;
- if Cache <> nil then
- begin
- if CacheList = nil then Cache^.Next := Cache else
- begin
- Cache^.Next := CacheList^.Next;
- CacheList^.Next := Cache;
- end;
- CacheList := Cache;
- Cache^.Master := @P;
- Inc(PtrRec(Cache).Ofs, SizeOf(TCache));
- end;
- P := Cache;
- end;
-
- procedure DisposeCache(P: Pointer);
- var
- Cache, C: PCache;
- begin
- PtrRec(Cache).Ofs := PtrRec(P).Ofs - SizeOf(TCache);
- PtrRec(Cache).Seg := PtrRec(P).Seg;
- C := CacheList;
- while (C^.Next <> Cache) and (C^.Next <> CacheList) do C := C^.Next;
- if C^.Next = Cache then
- begin
- if C = Cache then CacheList := nil else
- begin
- if CacheList = Cache then CacheList := C;
- C^.Next := Cache^.Next;
- end;
- Cache^.Master^ := nil;
- MemFreeBlock(PtrRec(Cache).Seg);
- end;
- end;
-
- procedure NewBuffer(var P: Pointer; Size: Word);
- begin
- P := MemAllocSeg(Size);
- end;
-
- procedure DisposeBuffer(P: Pointer);
- begin
- MemFreeBlock(PtrRec(P).Seg);
- end;
-
- function GetBufferSize(P: Pointer): Word;
- var
- Size: Longint;
- begin
- if MemGetBlockSize(PtrRec(P).Seg, Size) <> 0 then Size := 0;
- GetBufferSize := Size;
- end;
-
- function SetBufferSize(P: Pointer; Size: Word): Boolean;
- begin
- SetBufferSize := MemResizeBlock(PtrRec(P).Seg, Size) = 0;
- end;
-
- {$ELSE}
-
- type
- PCache = ^TCache;
- TCache = record
- Size: Word;
- Master: ^Pointer;
- Data: record end;
- end;
-
- type
- PBuffer = ^TBuffer;
- TBuffer = record
- Size: Word;
- Master: ^Word;
- end;
-
- const
- CachePtr: Pointer = nil;
- HeapResult: Integer = 0;
- BufHeapPtr: Word = 0;
- BufHeapEnd: Word = 0;
-
- function HeapNotify(Size: Word): Integer; far; assembler;
- asm
- CMP Size,0
- JNE @@3
- @@1: MOV AX,CachePtr.Word[2]
- CMP AX,HeapPtr.Word[2]
- JA @@3
- JB @@2
- MOV AX,CachePtr.Word[0]
- CMP AX,HeapPtr.Word[0]
- JAE @@3
- @@2: XOR AX,AX
- PUSH AX
- PUSH AX
- CALL DisposeCache
- JMP @@1
- @@3: MOV AX,HeapResult
- end;
-
- procedure FreeCacheMem;
- begin
- while CachePtr <> HeapEnd do DisposeCache(CachePtr);
- end;
-
- procedure InitMemory;
- var
- HeapSize: Word;
- begin
- HeapError := @HeapNotify;
- if BufHeapPtr = 0 then
- begin
- HeapSize := PtrRec(HeapEnd).Seg - PtrRec(HeapOrg).Seg;
- if HeapSize > MaxHeapSize then HeapSize := MaxHeapSize;
- BufHeapEnd := PtrRec(HeapEnd).Seg;
- PtrRec(HeapEnd).Seg := PtrRec(HeapOrg).Seg + HeapSize;
- BufHeapPtr := PtrRec(HeapEnd).Seg;
- end;
- CachePtr := HeapEnd;
- end;
-
- procedure DoneMemory;
- begin
- FreeCacheMem;
- end;
-
- procedure InitDosMem;
- begin
- SetMemTop(Ptr(BufHeapEnd, 0));
- end;
-
- procedure DoneDosMem;
- var
- MemTop: Pointer;
- begin
- MemTop := Ptr(BufHeapPtr, 0);
- if BufHeapPtr = PtrRec(HeapEnd).Seg then
- begin
- FreeCacheMem;
- MemTop := HeapPtr;
- end;
- SetMemTop(MemTop);
- end;
-
- function LowMemory: Boolean; assembler;
- asm
- MOV AX,HeapEnd.Word[2]
- SUB AX,HeapPtr.Word[2]
- SUB AX,LowMemSize
- SBB AX,AX
- NEG AX
- end;
-
- function MemAlloc(Size: Word): Pointer;
- var
- P: Pointer;
- begin
- HeapResult := 1;
- GetMem(P, Size);
- HeapResult := 0;
- if (P <> nil) and LowMemory then
- begin
- FreeMem(P, Size);
- P := nil;
- end;
- MemAlloc := P;
- end;
-
- function MemAllocSeg(Size: Word): Pointer;
- var
- P, T: Pointer;
- begin
- Size := (Size + 7) and $FFF8;
- P := MemAlloc(Size + 8);
- if P <> nil then
- begin
- if PtrRec(P).Ofs = 0 then
- begin
- PtrRec(T).Ofs := Size and 15;
- PtrRec(T).Seg := PtrRec(P).Seg + Size shr 4;
- end else
- begin
- T := P;
- PtrRec(P).Ofs := 0;
- Inc(PtrRec(P).Seg);
- end;
- FreeMem(T, 8);
- end;
- MemAllocSeg := P;
- end;
-
- procedure NewCache(var P: Pointer; Size: Word); assembler;
- asm
- LES DI,P
- MOV AX,Size
- ADD AX,(TYPE TCache)+15
- MOV CL,4
- SHR AX,CL
- MOV DX,CachePtr.Word[2]
- SUB DX,AX
- JC @@1
- CMP DX,HeapPtr.Word[2]
- JBE @@1
- MOV CX,HeapEnd.Word[2]
- SUB CX,DX
- CMP CX,MaxBufMem
- JA @@1
- MOV CachePtr.Word[2],DX
- PUSH DS
- MOV DS,DX
- XOR SI,SI
- MOV DS:[SI].TCache.Size,AX
- MOV DS:[SI].TCache.Master.Word[0],DI
- MOV DS:[SI].TCache.Master.Word[2],ES
- POP DS
- MOV AX,OFFSET TCache.Data
- JMP @@2
- @@1: XOR AX,AX
- CWD
- @@2: CLD
- STOSW
- XCHG AX,DX
- STOSW
- end;
-
- procedure DisposeCache(P: Pointer); assembler;
- asm
- MOV AX,CachePtr.Word[2]
- XOR BX,BX
- XOR CX,CX
- MOV DX,P.Word[2]
- @@1: MOV ES,AX
- CMP AX,DX
- JE @@2
- ADD AX,ES:[BX].TCache.Size
- CMP AX,HeapEnd.Word[2]
- JE @@2
- PUSH ES
- INC CX
- JMP @@1
- @@2: PUSH ES
- LES DI,ES:[BX].TCache.Master
- XOR AX,AX
- CLD
- STOSW
- STOSW
- POP ES
- MOV AX,ES:[BX].TCache.Size
- JCXZ @@4
- @@3: POP DX
- PUSH DS
- PUSH CX
- MOV DS,DX
- ADD DX,AX
- MOV ES,DX
- MOV SI,DS:[BX].TCache.Size
- MOV CL,3
- SHL SI,CL
- MOV CX,SI
- SHL SI,1
- DEC SI
- DEC SI
- MOV DI,SI
- STD
- REP MOVSW
- LDS SI,ES:[BX].TCache.Master
- MOV DS:[SI].Word[2],ES
- POP CX
- POP DS
- LOOP @@3
- @@4: ADD CachePtr.Word[2],AX
- end;
-
- procedure MoveSeg(Source, Dest, Size: Word); near; assembler;
- asm
- PUSH DS
- MOV AX,Source
- MOV DX,Dest
- MOV BX,Size
- CMP AX,DX
- JB @@3
- CLD
- @@1: MOV CX,0FFFH
- CMP CX,BX
- JB @@2
- MOV CX,BX
- @@2: MOV DS,AX
- MOV ES,DX
- ADD AX,CX
- ADD DX,CX
- SUB BX,CX
- SHL CX,1
- SHL CX,1
- SHL CX,1
- XOR SI,SI
- XOR DI,DI
- REP MOVSW
- OR BX,BX
- JNE @@1
- JMP @@6
- @@3: ADD AX,BX
- ADD DX,BX
- STD
- @@4: MOV CX,0FFFH
- CMP CX,BX
- JB @@5
- MOV CX,BX
- @@5: SUB AX,CX
- SUB DX,CX
- SUB BX,CX
- MOV DS,AX
- MOV ES,DX
- SHL CX,1
- SHL CX,1
- SHL CX,1
- MOV SI,CX
- DEC SI
- SHL SI,1
- MOV DI,SI
- REP MOVSW
- OR BX,BX
- JNE @@4
- @@6: POP DS
- end;
-
- function GetBufSize(P: PBuffer): Word;
- begin
- GetBufSize := (P^.Size + 15) shr 4 + 1;
- end;
-
- procedure SetBufSize(P: PBuffer; NewSize: Word);
- var
- CurSize: Word;
- begin
- CurSize := GetBufSize(P);
- MoveSeg(PtrRec(P).Seg + CurSize, PtrRec(P).Seg + NewSize,
- BufHeapPtr - PtrRec(P).Seg - CurSize);
- Inc(BufHeapPtr, NewSize - CurSize);
- Inc(PtrRec(P).Seg, NewSize);
- while PtrRec(P).Seg < BufHeapPtr do
- begin
- Inc(P^.Master^, NewSize - CurSize);
- Inc(PtrRec(P).Seg, (P^.Size + 15) shr 4 + 1);
- end;
- end;
-
- procedure NewBuffer(var P: Pointer; Size: Word);
- var
- BufSize: Word;
- Buffer: PBuffer;
- begin
- BufSize := (Size + 15) shr 4 + 1;
- if BufHeapPtr + BufSize > BufHeapEnd then P := nil else
- begin
- Buffer := Ptr(BufHeapPtr, 0);
- Buffer^.Size := Size;
- Buffer^.Master := @PtrRec(P).Seg;
- P := Ptr(BufHeapPtr + 1, 0);
- Inc(BufHeapPtr, BufSize);
- end;
- end;
-
- procedure DisposeBuffer(P: Pointer);
- begin
- Dec(PtrRec(P).Seg);
- SetBufSize(P, 0);
- end;
-
- function GetBufferSize(P: Pointer): Word;
- begin
- Dec(PtrRec(P).Seg);
- GetBufferSize := PBuffer(P)^.Size;
- end;
-
- function SetBufferSize(P: Pointer; Size: Word): Boolean;
- var
- NewSize: Word;
- begin
- Dec(PtrRec(P).Seg);
- NewSize := (Size + 15) shr 4 + 1;
- SetBufferSize := False;
- if BufHeapPtr + NewSize - GetBufSize(P) <= BufHeapEnd then
- begin
- SetBufSize(P, NewSize);
- PBuffer(P)^.Size := Size;
- SetBufferSize := True;
- end;
- end;
-
- procedure GetBufMem(var P: Pointer; Size: Word);
- begin
- NewCache(P, Size);
- end;
-
- procedure FreeBufMem(P: Pointer);
- begin
- DisposeCache(P);
- end;
-
- procedure SetMemTop(MemTop: Pointer); assembler;
- asm
- MOV BX,MemTop.Word[0]
- ADD BX,15
- MOV CL,4
- SHR BX,CL
- ADD BX,MemTop.Word[2]
- MOV AX,PrefixSeg
- SUB BX,AX
- MOV ES,AX
- MOV AH,4AH
- INT 21H
- end;
-
- {$ENDIF}
-
- end.
-