| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971 |
- (* Release 3.10 *)
- (*-------------------------------------------------------------------------*
- * *
- * STORAGE.MOD - Dynamic memory allocation *
- * *
- * COPYRIGHT (C) 1987..1992 Clarion Software Corporation. *
- * All Rights Reserved *
- * *
- *--------------------------------------------------------------------------*)
- (*%F _fdata *)
- (*# call(seg_name=>null),data(seg_name=>null) *)
- (*%E *)
- (*%T _fdata *)
- (*# call(ds_entry=>null) *)
- (*%E *)
- (*# module(implementation=>off) *)
- (*# check(stack=>off,index=>off,range=>off,overflow=>off,nil_ptr=>off) *)
- IMPLEMENTATION MODULE Storage;
- (*
- N.B. See also MSTORAGE.MOD, which replaces this module in the
- DOS multi-language libraries, and in DOS overlay and DLL models
- *)
- IMPORT SYSTEM, Lib, CoreMain, CoreSig, ModCore;
- (*%T _OS2 *)
- IMPORT CoreMem, Dos;
- (*%T _mthread *)
- IMPORT Process;
- (*%E *)
- (*%E *)
- CONST
- EndMarker = 0FFFFH;
- Align = 4;
- (*%F _OS2 *)
- VAR
- NearHeapSetup : BOOLEAN;
- FarHeapSetup : BOOLEAN;
- LastBlock : FarHeapRecPtr;
- (*%E _OS2 *)
- (*%F _OS2 *)
- (*# save,call(reg_param=>(ax)) *)
- PROCEDURE FarHeapShrink():CARDINAL;
- VAR
- Curr,Prev,New : FarHeapRecPtr;
- BEGIN
- Curr := MainHeap;
- Prev := FarNIL;
- WHILE Curr^.size # EndMarker DO
- Prev := Curr;
- Curr := Curr^.next;
- END; (*WHILE*)
- New := [Seg(Prev^) + Prev^.size:0];
- LastBlock := Prev;
- IF (New = Curr) & (Prev^.size > 4) THEN (* Last free block is last block *)
- ModCore.AdjustMem(Seg(Prev^) + 4);
- RETURN 0;
- END; (*IF*)
- RETURN 1;
- END FarHeapShrink;
- (*# restore *)
- (*%E _OS2 *)
- (*%F _OS2 *)
- (*# save,call(reg_param=>(ax)) *)
- PROCEDURE FarHeapRestore;
- BEGIN
- ModCore.AdjustMem(0);
- LastBlock := LastBlock^.next;
- LastBlock^.size := EndMarker;
- LastBlock^.next := MainHeap;
- END FarHeapRestore;
- (*# restore *)
- (*%E _OS2 *)
- (*%F _OS2 *)
- (*# save,call(reg_param=>(ax)) *)
- PROCEDURE FarHeapFix(Space:CARDINAL);
- VAR
- Curr,Prev,New : FarHeapRecPtr;
- BEGIN
- Curr := MainHeap;
- Prev := FarNIL;
- WHILE Curr^.size # EndMarker DO
- Prev := Curr;
- Curr := Curr^.next;
- END; (*WHILE*)
- New := [Seg(Prev^) + Prev^.size:0];
- LastBlock := Prev;
- IF (New = Curr) & (Prev^.size > Space + 4) THEN (* Last free block is last block *)
- Prev^.size := Space;
- New := [Seg(Prev^) + Space:0];
- Prev^.next := New;
- New^.size := EndMarker;
- New^.next := MainHeap;
- ModCore.AdjustMem(Seg(Prev^)+Space+4);
- END; (*IF*)
- END FarHeapFix;
- (*# restore *)
- (*%E _OS2 *)
- (*%F _OS2 *)
- PROCEDURE InitFarHeap():FarHeapRecPtr;
- TYPE
- (*# save, data(near_ptr=>off) *)
- CPtr = POINTER TO CARDINAL;
- (*# restore *)
- VAR
- P : CPtr;
- Size,Start : CARDINAL;
- BEGIN
- FarHeapSetup := TRUE;
- CoreMain._shr_mem := FarHeapShrink;
- CoreMain._fix_mem := FarHeapFix;
- CoreMain._res_mem := FarHeapRestore;
- CoreMain._fmodmemsetup := TRUE;
- P := [Lib.PSP:2 CPtr];
- Start := ModCore._getheapmem();
- Size := P^ - Start;
- MainHeap:=FarMakeHeap(Start, Size);
- RETURN MainHeap;
- END InitFarHeap;
- (*%E _OS2 *)
- (*%F _OS2 *)
- PROCEDURE InitNearHeap(): NearHeapRecPtr;
- VAR
- Size, Start: CARDINAL;
- BEGIN
- NearHeapSetup := TRUE;
- Size := CoreMain._heap_size;
- Start := CARDINAL(ADR(CoreMain._near_heap_start));
- IF LONGCARD(Size) + LONGCARD(Start) > 0FFFEH THEN
- Size := 0FFFEH - Start;
- END;
- NearHeap := NearMakeHeap(NearADR(CoreMain._near_heap_start), Size);
- RETURN NearHeap;
- END InitNearHeap;
- (*%E _OS2 *)
- (*%F _OS2 *)
- PROCEDURE FarMakeHeap(Source:CARDINAL;Size:CARDINAL):FarHeapRecPtr;
- VAR
- storage,first,last: FarHeapRecPtr;
- ie : CARDINAL;
- BEGIN
- (*%T _mthread *)
- ie := SYSTEM.GetFlags();
- SYSTEM.DI;
- (*%E *)
- storage := [Source:0];
- first := [Source+1:0];
- last := [Source+Size-1:0];
- storage^.next := first;
- storage^.size := 0;
- first^.next := last;
- last^.next := storage;
- first^.size := Size-2;
- last^.size := EndMarker;
- (*%T _mthread *)
- SYSTEM.SetFlags(ie);;
- (*%E *)
- RETURN storage;
- END FarMakeHeap;
- (*%E _OS2 *)
- (*%F _OS2 *)
- PROCEDURE FarHeapAllocate(Source:FarHeapRecPtr;VAR A:FarADDRESS;Size:CARDINAL);
- VAR
- res,prev,split : FarHeapRecPtr;
- ie : CARDINAL;
- BEGIN
- (*%T _mthread *)
- ie := SYSTEM.GetFlags();
- SYSTEM.DI;
- (*%E *)
- IF ~FarHeapSetup & (Source = MainHeap) THEN
- Source := InitFarHeap();
- END; (*IF*)
- IF Size = 0 THEN
- INC(Size);
- END; (*IF*)
- prev := Source;
- WHILE prev^.next^.size < Size DO
- prev := prev^.next;
- END; (*WHILE *)
- res := prev^.next;
- IF res^.size = EndMarker THEN (* heap run out of space *)
- (*%T _mthread *)
- SYSTEM.EI;
- (*%E *)
- IF Check THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(),90H,'FarHeapAllocate : Out Of Space');
- END; (*IF*)
- A := FarNIL;
- (*%T _mthread *)
- SYSTEM.SetFlags(ie);;
- (*%E *)
- RETURN;
- END; (*IF*)
- IF res^.size = Size THEN (* block correct size *)
- prev^.next := res^.next;
- ELSE (* split block, bottom half returned, top half linked to free chain *)
- split := [Seg(res^) + Size:0];
- prev^.next := split;
- split^.next := res^.next;
- split^.size := res^.size - Size;
- END; (*IF*)
- (*%T _mthread *)
- SYSTEM.SetFlags(ie);;
- (*%E *)
- A := FarADR(res^);
- END FarHeapAllocate;
- (*%E _OS2 *)
- (*%F _OS2 *)
- PROCEDURE FarHeapAvail(Source: FarHeapRecPtr) : CARDINAL;
- (* returns the largest block size available for allocation in paragraphs *)
- VAR
- size : CARDINAL;
- p : FarHeapRecPtr;
- ie : CARDINAL;
- BEGIN
- (*%T _mthread *)
- ie := SYSTEM.GetFlags();
- SYSTEM.DI;
- (*%E *)
- IF ~FarHeapSetup & (Source = MainHeap) THEN
- Source := InitFarHeap();
- END; (*IF*)
- p := Source^.next;
- size := 0;
- WHILE p^.size # EndMarker DO
- IF p^.size > size THEN
- size := p^.size;
- END; (*IF*)
- p := p^.next;
- END; (*WHILE*)
- (*%T _mthread *)
- SYSTEM.SetFlags(ie);;
- (*%E *)
- RETURN size;
- END FarHeapAvail;
- (*%E _OS2 *)
- (*%F _OS2 *)
- PROCEDURE FarHeapTotalAvail(Source:FarHeapRecPtr):CARDINAL;
- (* Returns the total heap available for allocation in paragraphs *)
- VAR
- size : CARDINAL;
- p : FarHeapRecPtr;
- ie : CARDINAL;
- BEGIN
- (*%T _mthread *)
- ie := SYSTEM.GetFlags();
- SYSTEM.DI;
- (*%E *)
- IF ~FarHeapSetup & (Source = MainHeap) THEN
- Source := InitFarHeap();
- END; (*IF*)
- p := Source^.next;
- size := 0;
- WHILE p^.size # EndMarker DO
- INC(size,p^.size);
- p := p^.next;
- END; (*WHILE*)
- (*%T _mthread *)
- SYSTEM.SetFlags(ie);;
- (*%E *)
- RETURN size;
- END FarHeapTotalAvail;
- (*%E _OS2 *)
- (*%F _OS2 *)
- PROCEDURE FarHeapDeallocate(Source:FarHeapRecPtr;VAR A:FarADDRESS;Size:CARDINAL);
- VAR
- target,prev,split : FarHeapRecPtr;
- tseg : CARDINAL;
- ie : CARDINAL;
- BEGIN
- IF (Seg(A^) = 0) OR (Ofs(A^) # 0) THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(),91H,'FarHeapDeallocate : Invalid Argument');
- END; (*IF*)
- (*%T _mthread *)
- ie := SYSTEM.GetFlags();
- SYSTEM.DI;
- (*%E *)
- IF Size = 0 THEN
- INC(Size);
- END; (*IF*)
- target := A;
- prev := Source;
- tseg := Seg(target^);
- WHILE Seg(prev^.next^) < tseg DO
- prev := prev^.next;
- END; (*WHILE*)
- IF Seg(prev^) + prev^.size = tseg THEN (* amalgamate with prev *)
- prev^.size := prev^.size + Size;
- target := prev;
- ELSIF Seg(prev^) + prev^.size > tseg THEN (* Heap corrupt *)
- (*%T _mthread *)
- SYSTEM.EI;
- (*%E *)
- Lib.RunTimeError(CoreSig._FatalErrorPos(),92H,'FarHeapDeallocate : Heap Corrupt');
- ELSE (* link after prev *)
- target^.next := prev^.next;
- prev^.next := target;
- target^.size := Size;
- END; (*IF*)
- IF (target^.next^.size # EndMarker) & (Seg(target^.next^) = Seg(target^) + target^.size) THEN
- (* amalgamate with next block *)
- target^.size := target^.size+target^.next^.size;
- target^.next := target^.next^.next;
- END; (*IF*)
- A := SYSTEM.FarNIL;
- (*%T _mthread *)
- SYSTEM.SetFlags(ie);;
- (*%E *)
- END FarHeapDeallocate;
- (*%E _OS2 *)
- (*%F _OS2 *)
- PROCEDURE FarHeapChangeAlloc(Source : FarHeapRecPtr; (* source heap *)
- A : FarADDRESS; (* block to change *)
- OldSize, (* old size of block *)
- NewSize : CARDINAL) (* new size of block *)
- (* in paragraphs *)
- : BOOLEAN; (* if sucessful *)
- (* This procedure attempts to change the size of an allocated block
- It returns TRUE if succeeded (only expansion can fail)
- *)
- VAR
- target,prev,
- split : FarHeapRecPtr;
- tseg : CARDINAL;
- result : BOOLEAN;
- extendsize : CARDINAL;
- Res : FarADDRESS;
- ie: CARDINAL;
- BEGIN
- IF (CARDINAL(Seg(A^))=0)OR(CARDINAL(Ofs(A^))<>0) THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 93H, 'FarHeapChangeAlloc : Invalid Argument');
- END;
- IF OldSize = NewSize THEN RETURN TRUE END;
- IF OldSize > NewSize THEN
- target := [CARDINAL(Seg(A^))+NewSize:0];
- FarHeapDeallocate(Source,target,OldSize-NewSize);
- RETURN TRUE;
- END;
- extendsize := NewSize-OldSize;
- (*%T _mthread *)
- ie := SYSTEM.GetFlags(); SYSTEM.DI;
- (*%E *)
- target := A;
- prev := Source;
- tseg := Seg(target^);
- WHILE CARDINAL(Seg(prev^.next^)) < tseg DO
- prev := prev^.next;
- END;
- IF (prev^.next^.size <> EndMarker) AND
- (CARDINAL(Seg(prev^.next^)) = CARDINAL(Seg(target^))+OldSize) AND
- (extendsize <= prev^.next^.size) THEN
- IF (extendsize = prev^.next^.size) THEN
- prev^.next := prev^.next^.next
- ELSE
- split := [CARDINAL(Seg(target^))+NewSize:0];
- split^.next := prev^.next^.next;
- split^.size := prev^.next^.size - extendsize;
- prev^.next := split;
- END;
- result := TRUE;
- ELSE
- result := FALSE;
- END;
- (*%T _mthread *)
- SYSTEM.SetFlags(ie);;
- (*%E *)
- RETURN result;
- END FarHeapChangeAlloc;
- (*%E _OS2 *)
- (*%F _OS2 *)
- PROCEDURE FarHeapChangeSize(Source:FarHeapRecPtr;VAR A:FarADDRESS;OldSize,NewSize:CARDINAL);
- (* This procedure will change the size of an allocated block avoiding*)
- (* any copy of data if possible. Calls HeapChangeAlloc. *)
- VAR
- na : FarADDRESS;
- BEGIN
- IF ~FarHeapChangeAlloc(Source,A,OldSize,NewSize) THEN
- FarHeapAllocate(Source,na,NewSize);
- IF na # FarNIL THEN
- Lib.FarWordMove(A,na,OldSize * 8);
- FarHeapDeallocate(Source,A,OldSize);
- END; (*IF*)
- A := na;
- END; (*IF*)
- END FarHeapChangeSize;
- (*%E _OS2 *)
- (*%F _OS2 *)
- PROCEDURE FarAllocate(VAR a:FarADDRESS;size:CARDINAL);
- VAR
- ps : CARDINAL;
- BEGIN
- IF size > 0FFF0H THEN
- ps := 1000H;
- ELSE
- ps := (size + 15) DIV 16;
- END; (*IF*)
- FarHeapAllocate(MainHeap,a,ps);
- IF ClearOnAllocate & (a # FarNIL) THEN
- Lib.FarWordFill(a,ps*8,0);
- END; (*IF*)
- END FarAllocate;
- (*%E _OS2 *)
- (*%F _OS2 *)
- PROCEDURE FarDeallocate(VAR a:FarADDRESS;size:CARDINAL);
- VAR
- ps : CARDINAL;
- BEGIN
- IF size > 0FFF0H THEN
- ps := 1000H;
- ELSE
- ps := (size + 15) DIV 16;
- END; (*IF*)
- FarHeapDeallocate(MainHeap,a,ps);
- END FarDeallocate;
- (*%E _OS2 *)
- (*%F _OS2 *)
- PROCEDURE FarAvailable(size:CARDINAL):BOOLEAN;
- VAR
- ps : CARDINAL;
- BEGIN
- IF size = 0 THEN
- ps := 1;
- ELSIF size > 0FFF0H THEN
- ps := 1000H;
- ELSE
- ps := (size + 15) DIV 16;
- END; (*IF*)
- RETURN ps <= FarHeapAvail(MainHeap);
- END FarAvailable;
- (*%E _OS2 *)
- (*%T _OS2 *)
- PROCEDURE FarMakeHeap( Source : CARDINAL; (* base segment of heap *)
- Size : CARDINAL (* size in paragraphs *)
- ) : FarHeapRecPtr;
- BEGIN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarMakeHeap : Not Supported Under OS2 *)');
- RETURN FarNIL;
- END FarMakeHeap;
- PROCEDURE FarHeapAllocate(Source : FarHeapRecPtr; (* source heap *)
- VAR A : FarADDRESS; (* result *)
- Size : CARDINAL); (* request size in paragraphs *)
- BEGIN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarHeapAllocate : Not Supported Under OS2 *)');
- END FarHeapAllocate;
- PROCEDURE FarHeapAvail(Source: FarHeapRecPtr) : CARDINAL;
- (* returns the largest block size available for allocation in paragraphs *)
- BEGIN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarHeapAvail : Not Supported Under OS2 *)');
- RETURN 0;
- END FarHeapAvail;
- PROCEDURE FarHeapTotalAvail(Source: FarHeapRecPtr) : CARDINAL;
- BEGIN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarHeapTotalAvail : Not Supported Under OS2 *)');
- RETURN 0;
- END FarHeapTotalAvail;
- PROCEDURE FarHeapDeallocate(Source : FarHeapRecPtr; (* source heap *)
- VAR A: FarADDRESS;
- Size : CARDINAL ); (* size of block
- in paragraphs *)
- BEGIN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarHeapDeallocate: Not Supported Under OS2 *)');
- END FarHeapDeallocate;
- PROCEDURE FarHeapChangeAlloc(Source : FarHeapRecPtr; (* source heap *)
- A : FarADDRESS; (* block to change *)
- OldSize, (* old size of block *)
- NewSize : CARDINAL) (* new size of block *)
- (* in paragraphs *)
- : BOOLEAN; (* if sucessful *)
- (* This procedure attempts to change the size of an allocated block
- It returns TRUE if succeeded (only expansion can fail)
- *)
- BEGIN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarHeapChangeAlloc: Not Supported Under OS2 *)');
- RETURN FALSE;
- END FarHeapChangeAlloc;
- PROCEDURE FarHeapChangeSize(Source : FarHeapRecPtr; (* source heap *)
- VAR A : FarADDRESS; (* block to change *)
- OldSize, (* old size of block *)
- NewSize : CARDINAL ); (* new size of block
- in paragraphs *)
- (*
- This procedure will change the size of an allocated block
- avoiding any copy of data if possible
- calls HeapChangeAlloc
- *)
- BEGIN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarHeapChangeSize: Not Supported Under OS2 *)');
- END FarHeapChangeSize;
- PROCEDURE FarAllocate(VAR a: FarADDRESS; size: CARDINAL);
- VAR
- Res: FarADDRESS;
- BEGIN
- IF size = 0 THEN size := 2 END;
- IF ClearOnAllocate THEN
- Res := CoreMem._fcalloc(1, size);
- ELSE
- Res := CoreMem._fmalloc(size);
- END;
- IF Res = FarNIL THEN
- IF Check THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 94H, 'FarAllocate: Out Of Memory');
- END;
- END;
- a := Res;
- END FarAllocate;
- PROCEDURE FarDeallocate(VAR a: FarADDRESS; size: CARDINAL);
- BEGIN
- CoreMem._ffree(a);
- a:= SYSTEM.FarNIL;
- END FarDeallocate;
- PROCEDURE FarAvailable(size: CARDINAL) : BOOLEAN;
- BEGIN
- RETURN TRUE;
- END FarAvailable;
- (*%E *)
- PROCEDURE NearMakeHeap(Source: NearADDRESS; Size: CARDINAL): NearHeapRecPtr;
- (* ========== *)
- VAR Storage, FirstFree: NearHeapRecPtr;
- BEGIN
- Size := (Size DIV Align) * Align;
- IF Size < Align*3 THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 95H, 'NearMakeHeap: Size Too Small');
- END;
- IF Source = SYSTEM.NearNIL THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 89H, 'NearMakeHeap: Invalid Argument');
- END;
- Storage := NearHeapRecPtr(Source);
- FirstFree := NearHeapRecPtr(CARDINAL(Source)+CARDINAL(Align));
- Storage^.size := Size;
- Storage^.next := FirstFree;
- FirstFree^.size := Size - Align;
- FirstFree^.next := SYSTEM.NearNIL;
- RETURN Storage;
- END NearMakeHeap;
- PROCEDURE NearHeapAllocate(Source: NearHeapRecPtr; VAR A: NearADDRESS; Size: CARDINAL);
- (* ======== *)
- VAR
- Base, Free, New: NearHeapRecPtr;
- (*%T _OS2 *)
- Res: NearADDRESS;
- (*%E *)
- BEGIN
- (*%F _OS2 *)
- (*%F _DLL *)
- IF (NOT NearHeapSetup) AND (Source = NearHeap) THEN
- Source := InitNearHeap();
- END;
- (*%E *)
- (*%E *)
- (*%T _OS2 *)
- IF Source = NearHeap THEN
- IF Size = 0 THEN Size := 2 END;
- IF ClearOnAllocate THEN
- Res := CoreMem._ncalloc(1, Size);
- ELSE
- Res := CoreMem._nmalloc(Size);
- END;
- IF Res = NearNIL THEN
- IF Check THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 98H, 'NearAllocate: Out Of Memory');
- END;
- END;
- A := Res;
- RETURN;
- END;
- (*%E *)
- IF Source = SYSTEM.NearNIL THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 8AH, 'NearHeapAllocate: Invalid Argument');
- END;
- IF Size < Align THEN
- Size := Align;
- ELSE
- Size := ( (Size+Align-1) DIV Align) * Align;
- IF Size = 0 THEN
- Size:=MAX(CARDINAL);
- END;
- END;
- Base := Source;
- LOOP
- Free := Base^.next;
- IF Free = SYSTEM.NearNIL THEN
- IF Check THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 96H, 'NearHeapAllocate: Out Of Memory');
- ELSE
- A := SYSTEM.NearNIL;
- RETURN;
- END;
- ELSIF Free^.size >= Size THEN
- EXIT;
- END;
- Base := Free;
- END;
- IF Free^.size = Size THEN
- Base^.next := Free^.next;
- ELSE
- New := NearHeapRecPtr(CARDINAL(Free)+Size);
- Base^.next := New;
- New^.size := Free^.size - Size;
- New^.next := Free^.next;
- END;
- IF ClearOnAllocate THEN
- Lib.WordFill ( ADR(Free^) , Size DIV 2 , 0 );
- END;
- A := NearADDRESS(Free);
- END NearHeapAllocate;
- PROCEDURE NearHeapDeallocate(Source: NearHeapRecPtr; VAR A: NearADDRESS; Size: CARDINAL );
- VAR
- Curr, Base, Free: NearHeapRecPtr;
- BEGIN
- IF (Source = SYSTEM.NearNIL) OR (A = SYSTEM.NearNIL) THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 8BH, 'NearHeapDeallocate: Invalid Argument');
- END;
- (*%T _OS2 *)
- IF Source = NearHeap THEN
- CoreMem._nfree(A);
- A:= NearADDRESS(NIL);
- RETURN;
- END;
- (*%E *)
- IF Size < Align THEN
- Size := Align;
- ELSE
- Size := ( (Size+Align-1) DIV Align) * Align;
- IF Size = 0 THEN
- Size:=MAX(CARDINAL);
- END;
- END;
- Curr := NearHeapRecPtr(A);
- A := SYSTEM.NearNIL;
- Base:=Source;
- LOOP
- Free := Base^.next;
- IF (Free = SYSTEM.NearNIL) OR (CARDINAL(Curr) < CARDINAL(Free)) THEN EXIT; END;
- Base := Free;
- END;
- IF CARDINAL(Base) + Base^.size = CARDINAL(Curr) THEN
- INC ( Base^.size , Size );
- Curr := Base;
- ELSE
- Base^.next := Curr;
- Curr^.next := Free;
- Curr^.size := Size;
- END;
- IF (Free # SYSTEM.NearNIL) AND (CARDINAL(Curr) + Curr^.size = CARDINAL(Free)) THEN
- INC ( Curr^.size, Free^.size);
- Curr^.next := Free^.next;
- END;
- END NearHeapDeallocate;
- PROCEDURE NearHeapAvail(Source: NearHeapRecPtr): CARDINAL;
- VAR
- Curr: NearHeapRecPtr;
- Size, av: CARDINAL;
- BEGIN
- (*%F _OS2 *)
- (*%F _DLL *)
- IF (NOT NearHeapSetup) AND (Source = NearHeap) THEN
- Source := InitNearHeap();
- END;
- (*%E *)
- (*%E *)
- (*%T _OS2 *)
- IF Source = NearHeap THEN
- av := CoreMem._memmax();
- IF av <= 4 THEN
- av := 0;
- ELSE
- DEC(av, 4);
- END;
- RETURN av;
- END;
- (*%E *)
- IF Source = SYSTEM.NearNIL THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 8CH, 'NearHeapAvail: Invalid Argument');
- END;
- Curr := Source^.next;
- Size := 0;
- WHILE Curr # SYSTEM.NearNIL DO
- IF Size < Curr^.size THEN
- Size := Curr^.size;
- END;
- Curr := Curr^.next;
- END;
- RETURN Size;
- END NearHeapAvail;
- PROCEDURE NearHeapTotalAvail(Source: NearHeapRecPtr): CARDINAL;
- VAR
- Curr: NearHeapRecPtr;
- Size: CARDINAL;
- BEGIN
- (*%F _OS2 *)
- (*%F _DLL *)
- IF (NOT NearHeapSetup) AND (Source = NearHeap) THEN
- Source := InitNearHeap();
- END;
- (*%E *)
- (*%E *)
- (*%T _OS2 *)
- IF Source = NearHeap THEN
- RETURN CoreMem.nearcoreleft();
- END;
- (*%E *)
- IF Source = SYSTEM.NearNIL THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 8DH, 'NearHeapTotalAvail: Invalid Argument');
- END;
- Curr := Source^.next;
- Size := 0;
- WHILE Curr # SYSTEM.NearNIL DO
- INC ( Size , Curr^.size );
- Curr := Curr^.next;
- END;
- RETURN Size;
- END NearHeapTotalAvail;
- PROCEDURE Merge(LowRec, HighRec: NearHeapRecPtr);
- BEGIN
- IF (LowRec = SYSTEM.NearNIL) AND (HighRec = SYSTEM.NearNIL) AND
- (NearHeapRecPtr(CARDINAL(LowRec)+LowRec^.size) = HighRec) THEN
- LowRec^.next:=HighRec^.next;
- INC(LowRec^.size, HighRec^.size);
- END;
- END Merge;
- PROCEDURE NearHeapChangeSize(Source: NearHeapRecPtr; VAR A: NearADDRESS;
- OldSize, NewSize : CARDINAL);
- VAR
- OldA: NearADDRESS;
- BEGIN
- IF (Source = SYSTEM.NearNIL) OR (A = SYSTEM.NearNIL) THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 8EH, 'NearHeapChangeSize: Invalid Argument');
- END;
- IF NearHeapChangeAlloc(Source, A, OldSize, NewSize) THEN
- RETURN;
- END;
- OldA := A;
- NearHeapAllocate(Source, A, NewSize);
- Lib.WordMove(ADR(OldA^), ADR(A^), OldSize DIV 2);
- NearHeapDeallocate(Source, OldA, OldSize);
- END NearHeapChangeSize;
- PROCEDURE NearHeapChangeAlloc(Source: NearHeapRecPtr; A: NearADDRESS;
- OldSize, NewSize : CARDINAL): BOOLEAN;
- VAR
- Curr, SplitRec, NextRec, PrevRec, NewRec: NearHeapRecPtr;
- Temp: NearHeapRec;
- SplitSize: CARDINAL;
- (*%T _OS2 *)
- T: NearADDRESS;
- (*%E *)
- BEGIN
- IF (Source = SYSTEM.NearNIL) OR (A = SYSTEM.NearNIL) THEN
- Lib.RunTimeError(CoreSig._FatalErrorPos(), 8FH, 'NearHeapChangeAlloc: Invalid Argument');
- END;
- (*%T _OS2 *)
- IF Source = NearHeap THEN
- T := CoreMem._nexpand(A, NewSize);
- RETURN T # NearNIL;
- END;
- (*%E *)
- IF NewSize < Align THEN
- NewSize := Align;
- ELSE
- NewSize := ( (NewSize+Align-1) DIV Align) * Align;
- IF NewSize = 0 THEN
- NewSize:=MAX(CARDINAL);
- END;
- END;
- IF OldSize < Align THEN
- OldSize := Align;
- ELSE
- OldSize := ( (OldSize+Align-1) DIV Align) * Align;
- IF OldSize = 0 THEN
- OldSize:=MAX(CARDINAL);
- END;
- END;
- IF OldSize = NewSize THEN RETURN TRUE END;
- Curr:=NearHeapRecPtr(A);
- NextRec:=Source;
- LOOP
- PrevRec:=NextRec;
- NextRec:=NextRec^.next;
- IF (NextRec = SYSTEM.NearNIL) OR (CARDINAL(NextRec) > CARDINAL(Curr)) THEN EXIT END;
- END;
- IF OldSize > NewSize THEN
- SplitSize:=OldSize-NewSize;
- SplitRec:=NearHeapRecPtr(CARDINAL(Curr)+NewSize);
- SplitRec^.size:=SplitSize;
- SplitRec^.next:=NextRec;
- PrevRec^.next:=SplitRec;
- Merge(SplitRec, NextRec);
- RETURN TRUE;
- END;
- IF (NextRec # SYSTEM.NearNIL) AND (NearHeapRecPtr(CARDINAL(Curr)+OldSize) = NextRec) THEN (* Next Block is free *)
- Temp.size := OldSize+NextRec^.size;
- Temp.next := NextRec^.next;
- IF Temp.size = NewSize THEN
- PrevRec^.next := Temp.next;
- ELSE
- NewRec := NearHeapRecPtr(CARDINAL(Curr)+NewSize);
- PrevRec^.next := NewRec;
- NewRec^.size := Temp.size-NewSize;
- NewRec^.next := Temp.next;
- END;
- RETURN TRUE;
- ELSE
- RETURN FALSE;
- END;
- END NearHeapChangeAlloc;
- (*%F _DLL *)
- PROCEDURE NearAllocate(VAR a: NearADDRESS; size: CARDINAL);
- BEGIN
- NearHeapAllocate(NearHeap,a,size);
- END NearAllocate;
- PROCEDURE NearDeallocate(VAR a: NearADDRESS; size: CARDINAL);
- BEGIN
- NearHeapDeallocate(NearHeap,a,size);
- END NearDeallocate;
- PROCEDURE NearAvailable(size: CARDINAL) : BOOLEAN;
- BEGIN
- RETURN size <= NearHeapAvail(NearHeap);
- END NearAvailable;
- (*%E *)
- (*%T _DLL *)
- PROCEDURE NearAllocate(VAR a: NearADDRESS; size: CARDINAL);
- BEGIN
- a := NearNIL;
- END NearAllocate;
- PROCEDURE NearDeallocate(VAR a: NearADDRESS; size: CARDINAL);
- BEGIN
- END NearDeallocate;
- PROCEDURE NearAvailable(size: CARDINAL) : BOOLEAN;
- BEGIN
- RETURN FALSE;
- END NearAvailable;
- (*%E *)
- (*%F _OS2 *)
- PROCEDURE SegAllocate(Size: CARDINAL): CARDINAL;
- VAR
- S: FarADDRESS;
- BEGIN
- FarAllocate(S, Size);
- RETURN Seg(S^);
- END SegAllocate;
- PROCEDURE SegDeallocate(Sel: CARDINAL; Size: CARDINAL);
- VAR
- S: FarADDRESS;
- BEGIN
- S := [Sel: 0];
- FarDeallocate(S, Size);
- END SegDeallocate;
- (*%E *)
- (*%T _OS2 *)
- PROCEDURE SegAllocate(Size: CARDINAL): CARDINAL;
- VAR
- S: CARDINAL;
- BEGIN
- IF Dos.AllocSeg(Size, S, 0) = 0 THEN
- RETURN S;
- END;
- RETURN 0;
- END SegAllocate;
- PROCEDURE SegDeallocate(Sel: CARDINAL; Size: CARDINAL);
- BEGIN
- IF Dos.FreeSeg(Sel) # 0 THEN END;
- END SegDeallocate;
- (*%E *)
- BEGIN
- Check := TRUE;
- ClearOnAllocate := FALSE;
- NearHeap := NearHeapRecPtr(0FFFFH);
- (*%F _OS2 *)
- MainHeap := [SYSTEM.HeapBase: 0];
- NearHeapSetup := FALSE;
- FarHeapSetup := FALSE;
- (*%E *)
- END Storage.
|