STORAGE.MOD 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. (* Release 3.10 *)
  2. (*-------------------------------------------------------------------------*
  3. * *
  4. * STORAGE.MOD - Dynamic memory allocation *
  5. * *
  6. * COPYRIGHT (C) 1987..1992 Clarion Software Corporation. *
  7. * All Rights Reserved *
  8. * *
  9. *--------------------------------------------------------------------------*)
  10. (*%F _fdata *)
  11. (*# call(seg_name=>null),data(seg_name=>null) *)
  12. (*%E *)
  13. (*%T _fdata *)
  14. (*# call(ds_entry=>null) *)
  15. (*%E *)
  16. (*# module(implementation=>off) *)
  17. (*# check(stack=>off,index=>off,range=>off,overflow=>off,nil_ptr=>off) *)
  18. IMPLEMENTATION MODULE Storage;
  19. (*
  20. N.B. See also MSTORAGE.MOD, which replaces this module in the
  21. DOS multi-language libraries, and in DOS overlay and DLL models
  22. *)
  23. IMPORT SYSTEM, Lib, CoreMain, CoreSig, ModCore;
  24. (*%T _OS2 *)
  25. IMPORT CoreMem, Dos;
  26. (*%T _mthread *)
  27. IMPORT Process;
  28. (*%E *)
  29. (*%E *)
  30. CONST
  31. EndMarker = 0FFFFH;
  32. Align = 4;
  33. (*%F _OS2 *)
  34. VAR
  35. NearHeapSetup : BOOLEAN;
  36. FarHeapSetup : BOOLEAN;
  37. LastBlock : FarHeapRecPtr;
  38. (*%E _OS2 *)
  39. (*%F _OS2 *)
  40. (*# save,call(reg_param=>(ax)) *)
  41. PROCEDURE FarHeapShrink():CARDINAL;
  42. VAR
  43. Curr,Prev,New : FarHeapRecPtr;
  44. BEGIN
  45. Curr := MainHeap;
  46. Prev := FarNIL;
  47. WHILE Curr^.size # EndMarker DO
  48. Prev := Curr;
  49. Curr := Curr^.next;
  50. END; (*WHILE*)
  51. New := [Seg(Prev^) + Prev^.size:0];
  52. LastBlock := Prev;
  53. IF (New = Curr) & (Prev^.size > 4) THEN (* Last free block is last block *)
  54. ModCore.AdjustMem(Seg(Prev^) + 4);
  55. RETURN 0;
  56. END; (*IF*)
  57. RETURN 1;
  58. END FarHeapShrink;
  59. (*# restore *)
  60. (*%E _OS2 *)
  61. (*%F _OS2 *)
  62. (*# save,call(reg_param=>(ax)) *)
  63. PROCEDURE FarHeapRestore;
  64. BEGIN
  65. ModCore.AdjustMem(0);
  66. LastBlock := LastBlock^.next;
  67. LastBlock^.size := EndMarker;
  68. LastBlock^.next := MainHeap;
  69. END FarHeapRestore;
  70. (*# restore *)
  71. (*%E _OS2 *)
  72. (*%F _OS2 *)
  73. (*# save,call(reg_param=>(ax)) *)
  74. PROCEDURE FarHeapFix(Space:CARDINAL);
  75. VAR
  76. Curr,Prev,New : FarHeapRecPtr;
  77. BEGIN
  78. Curr := MainHeap;
  79. Prev := FarNIL;
  80. WHILE Curr^.size # EndMarker DO
  81. Prev := Curr;
  82. Curr := Curr^.next;
  83. END; (*WHILE*)
  84. New := [Seg(Prev^) + Prev^.size:0];
  85. LastBlock := Prev;
  86. IF (New = Curr) & (Prev^.size > Space + 4) THEN (* Last free block is last block *)
  87. Prev^.size := Space;
  88. New := [Seg(Prev^) + Space:0];
  89. Prev^.next := New;
  90. New^.size := EndMarker;
  91. New^.next := MainHeap;
  92. ModCore.AdjustMem(Seg(Prev^)+Space+4);
  93. END; (*IF*)
  94. END FarHeapFix;
  95. (*# restore *)
  96. (*%E _OS2 *)
  97. (*%F _OS2 *)
  98. PROCEDURE InitFarHeap():FarHeapRecPtr;
  99. TYPE
  100. (*# save, data(near_ptr=>off) *)
  101. CPtr = POINTER TO CARDINAL;
  102. (*# restore *)
  103. VAR
  104. P : CPtr;
  105. Size,Start : CARDINAL;
  106. BEGIN
  107. FarHeapSetup := TRUE;
  108. CoreMain._shr_mem := FarHeapShrink;
  109. CoreMain._fix_mem := FarHeapFix;
  110. CoreMain._res_mem := FarHeapRestore;
  111. CoreMain._fmodmemsetup := TRUE;
  112. P := [Lib.PSP:2 CPtr];
  113. Start := ModCore._getheapmem();
  114. Size := P^ - Start;
  115. MainHeap:=FarMakeHeap(Start, Size);
  116. RETURN MainHeap;
  117. END InitFarHeap;
  118. (*%E _OS2 *)
  119. (*%F _OS2 *)
  120. PROCEDURE InitNearHeap(): NearHeapRecPtr;
  121. VAR
  122. Size, Start: CARDINAL;
  123. BEGIN
  124. NearHeapSetup := TRUE;
  125. Size := CoreMain._heap_size;
  126. Start := CARDINAL(ADR(CoreMain._near_heap_start));
  127. IF LONGCARD(Size) + LONGCARD(Start) > 0FFFEH THEN
  128. Size := 0FFFEH - Start;
  129. END;
  130. NearHeap := NearMakeHeap(NearADR(CoreMain._near_heap_start), Size);
  131. RETURN NearHeap;
  132. END InitNearHeap;
  133. (*%E _OS2 *)
  134. (*%F _OS2 *)
  135. PROCEDURE FarMakeHeap(Source:CARDINAL;Size:CARDINAL):FarHeapRecPtr;
  136. VAR
  137. storage,first,last: FarHeapRecPtr;
  138. ie : CARDINAL;
  139. BEGIN
  140. (*%T _mthread *)
  141. ie := SYSTEM.GetFlags();
  142. SYSTEM.DI;
  143. (*%E *)
  144. storage := [Source:0];
  145. first := [Source+1:0];
  146. last := [Source+Size-1:0];
  147. storage^.next := first;
  148. storage^.size := 0;
  149. first^.next := last;
  150. last^.next := storage;
  151. first^.size := Size-2;
  152. last^.size := EndMarker;
  153. (*%T _mthread *)
  154. SYSTEM.SetFlags(ie);;
  155. (*%E *)
  156. RETURN storage;
  157. END FarMakeHeap;
  158. (*%E _OS2 *)
  159. (*%F _OS2 *)
  160. PROCEDURE FarHeapAllocate(Source:FarHeapRecPtr;VAR A:FarADDRESS;Size:CARDINAL);
  161. VAR
  162. res,prev,split : FarHeapRecPtr;
  163. ie : CARDINAL;
  164. BEGIN
  165. (*%T _mthread *)
  166. ie := SYSTEM.GetFlags();
  167. SYSTEM.DI;
  168. (*%E *)
  169. IF ~FarHeapSetup & (Source = MainHeap) THEN
  170. Source := InitFarHeap();
  171. END; (*IF*)
  172. IF Size = 0 THEN
  173. INC(Size);
  174. END; (*IF*)
  175. prev := Source;
  176. WHILE prev^.next^.size < Size DO
  177. prev := prev^.next;
  178. END; (*WHILE *)
  179. res := prev^.next;
  180. IF res^.size = EndMarker THEN (* heap run out of space *)
  181. (*%T _mthread *)
  182. SYSTEM.EI;
  183. (*%E *)
  184. IF Check THEN
  185. Lib.RunTimeError(CoreSig._FatalErrorPos(),90H,'FarHeapAllocate : Out Of Space');
  186. END; (*IF*)
  187. A := FarNIL;
  188. (*%T _mthread *)
  189. SYSTEM.SetFlags(ie);;
  190. (*%E *)
  191. RETURN;
  192. END; (*IF*)
  193. IF res^.size = Size THEN (* block correct size *)
  194. prev^.next := res^.next;
  195. ELSE (* split block, bottom half returned, top half linked to free chain *)
  196. split := [Seg(res^) + Size:0];
  197. prev^.next := split;
  198. split^.next := res^.next;
  199. split^.size := res^.size - Size;
  200. END; (*IF*)
  201. (*%T _mthread *)
  202. SYSTEM.SetFlags(ie);;
  203. (*%E *)
  204. A := FarADR(res^);
  205. END FarHeapAllocate;
  206. (*%E _OS2 *)
  207. (*%F _OS2 *)
  208. PROCEDURE FarHeapAvail(Source: FarHeapRecPtr) : CARDINAL;
  209. (* returns the largest block size available for allocation in paragraphs *)
  210. VAR
  211. size : CARDINAL;
  212. p : FarHeapRecPtr;
  213. ie : CARDINAL;
  214. BEGIN
  215. (*%T _mthread *)
  216. ie := SYSTEM.GetFlags();
  217. SYSTEM.DI;
  218. (*%E *)
  219. IF ~FarHeapSetup & (Source = MainHeap) THEN
  220. Source := InitFarHeap();
  221. END; (*IF*)
  222. p := Source^.next;
  223. size := 0;
  224. WHILE p^.size # EndMarker DO
  225. IF p^.size > size THEN
  226. size := p^.size;
  227. END; (*IF*)
  228. p := p^.next;
  229. END; (*WHILE*)
  230. (*%T _mthread *)
  231. SYSTEM.SetFlags(ie);;
  232. (*%E *)
  233. RETURN size;
  234. END FarHeapAvail;
  235. (*%E _OS2 *)
  236. (*%F _OS2 *)
  237. PROCEDURE FarHeapTotalAvail(Source:FarHeapRecPtr):CARDINAL;
  238. (* Returns the total heap available for allocation in paragraphs *)
  239. VAR
  240. size : CARDINAL;
  241. p : FarHeapRecPtr;
  242. ie : CARDINAL;
  243. BEGIN
  244. (*%T _mthread *)
  245. ie := SYSTEM.GetFlags();
  246. SYSTEM.DI;
  247. (*%E *)
  248. IF ~FarHeapSetup & (Source = MainHeap) THEN
  249. Source := InitFarHeap();
  250. END; (*IF*)
  251. p := Source^.next;
  252. size := 0;
  253. WHILE p^.size # EndMarker DO
  254. INC(size,p^.size);
  255. p := p^.next;
  256. END; (*WHILE*)
  257. (*%T _mthread *)
  258. SYSTEM.SetFlags(ie);;
  259. (*%E *)
  260. RETURN size;
  261. END FarHeapTotalAvail;
  262. (*%E _OS2 *)
  263. (*%F _OS2 *)
  264. PROCEDURE FarHeapDeallocate(Source:FarHeapRecPtr;VAR A:FarADDRESS;Size:CARDINAL);
  265. VAR
  266. target,prev,split : FarHeapRecPtr;
  267. tseg : CARDINAL;
  268. ie : CARDINAL;
  269. BEGIN
  270. IF (Seg(A^) = 0) OR (Ofs(A^) # 0) THEN
  271. Lib.RunTimeError(CoreSig._FatalErrorPos(),91H,'FarHeapDeallocate : Invalid Argument');
  272. END; (*IF*)
  273. (*%T _mthread *)
  274. ie := SYSTEM.GetFlags();
  275. SYSTEM.DI;
  276. (*%E *)
  277. IF Size = 0 THEN
  278. INC(Size);
  279. END; (*IF*)
  280. target := A;
  281. prev := Source;
  282. tseg := Seg(target^);
  283. WHILE Seg(prev^.next^) < tseg DO
  284. prev := prev^.next;
  285. END; (*WHILE*)
  286. IF Seg(prev^) + prev^.size = tseg THEN (* amalgamate with prev *)
  287. prev^.size := prev^.size + Size;
  288. target := prev;
  289. ELSIF Seg(prev^) + prev^.size > tseg THEN (* Heap corrupt *)
  290. (*%T _mthread *)
  291. SYSTEM.EI;
  292. (*%E *)
  293. Lib.RunTimeError(CoreSig._FatalErrorPos(),92H,'FarHeapDeallocate : Heap Corrupt');
  294. ELSE (* link after prev *)
  295. target^.next := prev^.next;
  296. prev^.next := target;
  297. target^.size := Size;
  298. END; (*IF*)
  299. IF (target^.next^.size # EndMarker) & (Seg(target^.next^) = Seg(target^) + target^.size) THEN
  300. (* amalgamate with next block *)
  301. target^.size := target^.size+target^.next^.size;
  302. target^.next := target^.next^.next;
  303. END; (*IF*)
  304. A := SYSTEM.FarNIL;
  305. (*%T _mthread *)
  306. SYSTEM.SetFlags(ie);;
  307. (*%E *)
  308. END FarHeapDeallocate;
  309. (*%E _OS2 *)
  310. (*%F _OS2 *)
  311. PROCEDURE FarHeapChangeAlloc(Source : FarHeapRecPtr; (* source heap *)
  312. A : FarADDRESS; (* block to change *)
  313. OldSize, (* old size of block *)
  314. NewSize : CARDINAL) (* new size of block *)
  315. (* in paragraphs *)
  316. : BOOLEAN; (* if sucessful *)
  317. (* This procedure attempts to change the size of an allocated block
  318. It returns TRUE if succeeded (only expansion can fail)
  319. *)
  320. VAR
  321. target,prev,
  322. split : FarHeapRecPtr;
  323. tseg : CARDINAL;
  324. result : BOOLEAN;
  325. extendsize : CARDINAL;
  326. Res : FarADDRESS;
  327. ie: CARDINAL;
  328. BEGIN
  329. IF (CARDINAL(Seg(A^))=0)OR(CARDINAL(Ofs(A^))<>0) THEN
  330. Lib.RunTimeError(CoreSig._FatalErrorPos(), 93H, 'FarHeapChangeAlloc : Invalid Argument');
  331. END;
  332. IF OldSize = NewSize THEN RETURN TRUE END;
  333. IF OldSize > NewSize THEN
  334. target := [CARDINAL(Seg(A^))+NewSize:0];
  335. FarHeapDeallocate(Source,target,OldSize-NewSize);
  336. RETURN TRUE;
  337. END;
  338. extendsize := NewSize-OldSize;
  339. (*%T _mthread *)
  340. ie := SYSTEM.GetFlags(); SYSTEM.DI;
  341. (*%E *)
  342. target := A;
  343. prev := Source;
  344. tseg := Seg(target^);
  345. WHILE CARDINAL(Seg(prev^.next^)) < tseg DO
  346. prev := prev^.next;
  347. END;
  348. IF (prev^.next^.size <> EndMarker) AND
  349. (CARDINAL(Seg(prev^.next^)) = CARDINAL(Seg(target^))+OldSize) AND
  350. (extendsize <= prev^.next^.size) THEN
  351. IF (extendsize = prev^.next^.size) THEN
  352. prev^.next := prev^.next^.next
  353. ELSE
  354. split := [CARDINAL(Seg(target^))+NewSize:0];
  355. split^.next := prev^.next^.next;
  356. split^.size := prev^.next^.size - extendsize;
  357. prev^.next := split;
  358. END;
  359. result := TRUE;
  360. ELSE
  361. result := FALSE;
  362. END;
  363. (*%T _mthread *)
  364. SYSTEM.SetFlags(ie);;
  365. (*%E *)
  366. RETURN result;
  367. END FarHeapChangeAlloc;
  368. (*%E _OS2 *)
  369. (*%F _OS2 *)
  370. PROCEDURE FarHeapChangeSize(Source:FarHeapRecPtr;VAR A:FarADDRESS;OldSize,NewSize:CARDINAL);
  371. (* This procedure will change the size of an allocated block avoiding*)
  372. (* any copy of data if possible. Calls HeapChangeAlloc. *)
  373. VAR
  374. na : FarADDRESS;
  375. BEGIN
  376. IF ~FarHeapChangeAlloc(Source,A,OldSize,NewSize) THEN
  377. FarHeapAllocate(Source,na,NewSize);
  378. IF na # FarNIL THEN
  379. Lib.FarWordMove(A,na,OldSize * 8);
  380. FarHeapDeallocate(Source,A,OldSize);
  381. END; (*IF*)
  382. A := na;
  383. END; (*IF*)
  384. END FarHeapChangeSize;
  385. (*%E _OS2 *)
  386. (*%F _OS2 *)
  387. PROCEDURE FarAllocate(VAR a:FarADDRESS;size:CARDINAL);
  388. VAR
  389. ps : CARDINAL;
  390. BEGIN
  391. IF size > 0FFF0H THEN
  392. ps := 1000H;
  393. ELSE
  394. ps := (size + 15) DIV 16;
  395. END; (*IF*)
  396. FarHeapAllocate(MainHeap,a,ps);
  397. IF ClearOnAllocate & (a # FarNIL) THEN
  398. Lib.FarWordFill(a,ps*8,0);
  399. END; (*IF*)
  400. END FarAllocate;
  401. (*%E _OS2 *)
  402. (*%F _OS2 *)
  403. PROCEDURE FarDeallocate(VAR a:FarADDRESS;size:CARDINAL);
  404. VAR
  405. ps : CARDINAL;
  406. BEGIN
  407. IF size > 0FFF0H THEN
  408. ps := 1000H;
  409. ELSE
  410. ps := (size + 15) DIV 16;
  411. END; (*IF*)
  412. FarHeapDeallocate(MainHeap,a,ps);
  413. END FarDeallocate;
  414. (*%E _OS2 *)
  415. (*%F _OS2 *)
  416. PROCEDURE FarAvailable(size:CARDINAL):BOOLEAN;
  417. VAR
  418. ps : CARDINAL;
  419. BEGIN
  420. IF size = 0 THEN
  421. ps := 1;
  422. ELSIF size > 0FFF0H THEN
  423. ps := 1000H;
  424. ELSE
  425. ps := (size + 15) DIV 16;
  426. END; (*IF*)
  427. RETURN ps <= FarHeapAvail(MainHeap);
  428. END FarAvailable;
  429. (*%E _OS2 *)
  430. (*%T _OS2 *)
  431. PROCEDURE FarMakeHeap( Source : CARDINAL; (* base segment of heap *)
  432. Size : CARDINAL (* size in paragraphs *)
  433. ) : FarHeapRecPtr;
  434. BEGIN
  435. Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarMakeHeap : Not Supported Under OS2 *)');
  436. RETURN FarNIL;
  437. END FarMakeHeap;
  438. PROCEDURE FarHeapAllocate(Source : FarHeapRecPtr; (* source heap *)
  439. VAR A : FarADDRESS; (* result *)
  440. Size : CARDINAL); (* request size in paragraphs *)
  441. BEGIN
  442. Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarHeapAllocate : Not Supported Under OS2 *)');
  443. END FarHeapAllocate;
  444. PROCEDURE FarHeapAvail(Source: FarHeapRecPtr) : CARDINAL;
  445. (* returns the largest block size available for allocation in paragraphs *)
  446. BEGIN
  447. Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarHeapAvail : Not Supported Under OS2 *)');
  448. RETURN 0;
  449. END FarHeapAvail;
  450. PROCEDURE FarHeapTotalAvail(Source: FarHeapRecPtr) : CARDINAL;
  451. BEGIN
  452. Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarHeapTotalAvail : Not Supported Under OS2 *)');
  453. RETURN 0;
  454. END FarHeapTotalAvail;
  455. PROCEDURE FarHeapDeallocate(Source : FarHeapRecPtr; (* source heap *)
  456. VAR A: FarADDRESS;
  457. Size : CARDINAL ); (* size of block
  458. in paragraphs *)
  459. BEGIN
  460. Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarHeapDeallocate: Not Supported Under OS2 *)');
  461. END FarHeapDeallocate;
  462. PROCEDURE FarHeapChangeAlloc(Source : FarHeapRecPtr; (* source heap *)
  463. A : FarADDRESS; (* block to change *)
  464. OldSize, (* old size of block *)
  465. NewSize : CARDINAL) (* new size of block *)
  466. (* in paragraphs *)
  467. : BOOLEAN; (* if sucessful *)
  468. (* This procedure attempts to change the size of an allocated block
  469. It returns TRUE if succeeded (only expansion can fail)
  470. *)
  471. BEGIN
  472. Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarHeapChangeAlloc: Not Supported Under OS2 *)');
  473. RETURN FALSE;
  474. END FarHeapChangeAlloc;
  475. PROCEDURE FarHeapChangeSize(Source : FarHeapRecPtr; (* source heap *)
  476. VAR A : FarADDRESS; (* block to change *)
  477. OldSize, (* old size of block *)
  478. NewSize : CARDINAL ); (* new size of block
  479. in paragraphs *)
  480. (*
  481. This procedure will change the size of an allocated block
  482. avoiding any copy of data if possible
  483. calls HeapChangeAlloc
  484. *)
  485. BEGIN
  486. Lib.RunTimeError(CoreSig._FatalErrorPos(), 099H, 'FarHeapChangeSize: Not Supported Under OS2 *)');
  487. END FarHeapChangeSize;
  488. PROCEDURE FarAllocate(VAR a: FarADDRESS; size: CARDINAL);
  489. VAR
  490. Res: FarADDRESS;
  491. BEGIN
  492. IF size = 0 THEN size := 2 END;
  493. IF ClearOnAllocate THEN
  494. Res := CoreMem._fcalloc(1, size);
  495. ELSE
  496. Res := CoreMem._fmalloc(size);
  497. END;
  498. IF Res = FarNIL THEN
  499. IF Check THEN
  500. Lib.RunTimeError(CoreSig._FatalErrorPos(), 94H, 'FarAllocate: Out Of Memory');
  501. END;
  502. END;
  503. a := Res;
  504. END FarAllocate;
  505. PROCEDURE FarDeallocate(VAR a: FarADDRESS; size: CARDINAL);
  506. BEGIN
  507. CoreMem._ffree(a);
  508. a:= SYSTEM.FarNIL;
  509. END FarDeallocate;
  510. PROCEDURE FarAvailable(size: CARDINAL) : BOOLEAN;
  511. BEGIN
  512. RETURN TRUE;
  513. END FarAvailable;
  514. (*%E *)
  515. PROCEDURE NearMakeHeap(Source: NearADDRESS; Size: CARDINAL): NearHeapRecPtr;
  516. (* ========== *)
  517. VAR Storage, FirstFree: NearHeapRecPtr;
  518. BEGIN
  519. Size := (Size DIV Align) * Align;
  520. IF Size < Align*3 THEN
  521. Lib.RunTimeError(CoreSig._FatalErrorPos(), 95H, 'NearMakeHeap: Size Too Small');
  522. END;
  523. IF Source = SYSTEM.NearNIL THEN
  524. Lib.RunTimeError(CoreSig._FatalErrorPos(), 89H, 'NearMakeHeap: Invalid Argument');
  525. END;
  526. Storage := NearHeapRecPtr(Source);
  527. FirstFree := NearHeapRecPtr(CARDINAL(Source)+CARDINAL(Align));
  528. Storage^.size := Size;
  529. Storage^.next := FirstFree;
  530. FirstFree^.size := Size - Align;
  531. FirstFree^.next := SYSTEM.NearNIL;
  532. RETURN Storage;
  533. END NearMakeHeap;
  534. PROCEDURE NearHeapAllocate(Source: NearHeapRecPtr; VAR A: NearADDRESS; Size: CARDINAL);
  535. (* ======== *)
  536. VAR
  537. Base, Free, New: NearHeapRecPtr;
  538. (*%T _OS2 *)
  539. Res: NearADDRESS;
  540. (*%E *)
  541. BEGIN
  542. (*%F _OS2 *)
  543. (*%F _DLL *)
  544. IF (NOT NearHeapSetup) AND (Source = NearHeap) THEN
  545. Source := InitNearHeap();
  546. END;
  547. (*%E *)
  548. (*%E *)
  549. (*%T _OS2 *)
  550. IF Source = NearHeap THEN
  551. IF Size = 0 THEN Size := 2 END;
  552. IF ClearOnAllocate THEN
  553. Res := CoreMem._ncalloc(1, Size);
  554. ELSE
  555. Res := CoreMem._nmalloc(Size);
  556. END;
  557. IF Res = NearNIL THEN
  558. IF Check THEN
  559. Lib.RunTimeError(CoreSig._FatalErrorPos(), 98H, 'NearAllocate: Out Of Memory');
  560. END;
  561. END;
  562. A := Res;
  563. RETURN;
  564. END;
  565. (*%E *)
  566. IF Source = SYSTEM.NearNIL THEN
  567. Lib.RunTimeError(CoreSig._FatalErrorPos(), 8AH, 'NearHeapAllocate: Invalid Argument');
  568. END;
  569. IF Size < Align THEN
  570. Size := Align;
  571. ELSE
  572. Size := ( (Size+Align-1) DIV Align) * Align;
  573. IF Size = 0 THEN
  574. Size:=MAX(CARDINAL);
  575. END;
  576. END;
  577. Base := Source;
  578. LOOP
  579. Free := Base^.next;
  580. IF Free = SYSTEM.NearNIL THEN
  581. IF Check THEN
  582. Lib.RunTimeError(CoreSig._FatalErrorPos(), 96H, 'NearHeapAllocate: Out Of Memory');
  583. ELSE
  584. A := SYSTEM.NearNIL;
  585. RETURN;
  586. END;
  587. ELSIF Free^.size >= Size THEN
  588. EXIT;
  589. END;
  590. Base := Free;
  591. END;
  592. IF Free^.size = Size THEN
  593. Base^.next := Free^.next;
  594. ELSE
  595. New := NearHeapRecPtr(CARDINAL(Free)+Size);
  596. Base^.next := New;
  597. New^.size := Free^.size - Size;
  598. New^.next := Free^.next;
  599. END;
  600. IF ClearOnAllocate THEN
  601. Lib.WordFill ( ADR(Free^) , Size DIV 2 , 0 );
  602. END;
  603. A := NearADDRESS(Free);
  604. END NearHeapAllocate;
  605. PROCEDURE NearHeapDeallocate(Source: NearHeapRecPtr; VAR A: NearADDRESS; Size: CARDINAL );
  606. VAR
  607. Curr, Base, Free: NearHeapRecPtr;
  608. BEGIN
  609. IF (Source = SYSTEM.NearNIL) OR (A = SYSTEM.NearNIL) THEN
  610. Lib.RunTimeError(CoreSig._FatalErrorPos(), 8BH, 'NearHeapDeallocate: Invalid Argument');
  611. END;
  612. (*%T _OS2 *)
  613. IF Source = NearHeap THEN
  614. CoreMem._nfree(A);
  615. A:= NearADDRESS(NIL);
  616. RETURN;
  617. END;
  618. (*%E *)
  619. IF Size < Align THEN
  620. Size := Align;
  621. ELSE
  622. Size := ( (Size+Align-1) DIV Align) * Align;
  623. IF Size = 0 THEN
  624. Size:=MAX(CARDINAL);
  625. END;
  626. END;
  627. Curr := NearHeapRecPtr(A);
  628. A := SYSTEM.NearNIL;
  629. Base:=Source;
  630. LOOP
  631. Free := Base^.next;
  632. IF (Free = SYSTEM.NearNIL) OR (CARDINAL(Curr) < CARDINAL(Free)) THEN EXIT; END;
  633. Base := Free;
  634. END;
  635. IF CARDINAL(Base) + Base^.size = CARDINAL(Curr) THEN
  636. INC ( Base^.size , Size );
  637. Curr := Base;
  638. ELSE
  639. Base^.next := Curr;
  640. Curr^.next := Free;
  641. Curr^.size := Size;
  642. END;
  643. IF (Free # SYSTEM.NearNIL) AND (CARDINAL(Curr) + Curr^.size = CARDINAL(Free)) THEN
  644. INC ( Curr^.size, Free^.size);
  645. Curr^.next := Free^.next;
  646. END;
  647. END NearHeapDeallocate;
  648. PROCEDURE NearHeapAvail(Source: NearHeapRecPtr): CARDINAL;
  649. VAR
  650. Curr: NearHeapRecPtr;
  651. Size, av: CARDINAL;
  652. BEGIN
  653. (*%F _OS2 *)
  654. (*%F _DLL *)
  655. IF (NOT NearHeapSetup) AND (Source = NearHeap) THEN
  656. Source := InitNearHeap();
  657. END;
  658. (*%E *)
  659. (*%E *)
  660. (*%T _OS2 *)
  661. IF Source = NearHeap THEN
  662. av := CoreMem._memmax();
  663. IF av <= 4 THEN
  664. av := 0;
  665. ELSE
  666. DEC(av, 4);
  667. END;
  668. RETURN av;
  669. END;
  670. (*%E *)
  671. IF Source = SYSTEM.NearNIL THEN
  672. Lib.RunTimeError(CoreSig._FatalErrorPos(), 8CH, 'NearHeapAvail: Invalid Argument');
  673. END;
  674. Curr := Source^.next;
  675. Size := 0;
  676. WHILE Curr # SYSTEM.NearNIL DO
  677. IF Size < Curr^.size THEN
  678. Size := Curr^.size;
  679. END;
  680. Curr := Curr^.next;
  681. END;
  682. RETURN Size;
  683. END NearHeapAvail;
  684. PROCEDURE NearHeapTotalAvail(Source: NearHeapRecPtr): CARDINAL;
  685. VAR
  686. Curr: NearHeapRecPtr;
  687. Size: CARDINAL;
  688. BEGIN
  689. (*%F _OS2 *)
  690. (*%F _DLL *)
  691. IF (NOT NearHeapSetup) AND (Source = NearHeap) THEN
  692. Source := InitNearHeap();
  693. END;
  694. (*%E *)
  695. (*%E *)
  696. (*%T _OS2 *)
  697. IF Source = NearHeap THEN
  698. RETURN CoreMem.nearcoreleft();
  699. END;
  700. (*%E *)
  701. IF Source = SYSTEM.NearNIL THEN
  702. Lib.RunTimeError(CoreSig._FatalErrorPos(), 8DH, 'NearHeapTotalAvail: Invalid Argument');
  703. END;
  704. Curr := Source^.next;
  705. Size := 0;
  706. WHILE Curr # SYSTEM.NearNIL DO
  707. INC ( Size , Curr^.size );
  708. Curr := Curr^.next;
  709. END;
  710. RETURN Size;
  711. END NearHeapTotalAvail;
  712. PROCEDURE Merge(LowRec, HighRec: NearHeapRecPtr);
  713. BEGIN
  714. IF (LowRec = SYSTEM.NearNIL) AND (HighRec = SYSTEM.NearNIL) AND
  715. (NearHeapRecPtr(CARDINAL(LowRec)+LowRec^.size) = HighRec) THEN
  716. LowRec^.next:=HighRec^.next;
  717. INC(LowRec^.size, HighRec^.size);
  718. END;
  719. END Merge;
  720. PROCEDURE NearHeapChangeSize(Source: NearHeapRecPtr; VAR A: NearADDRESS;
  721. OldSize, NewSize : CARDINAL);
  722. VAR
  723. OldA: NearADDRESS;
  724. BEGIN
  725. IF (Source = SYSTEM.NearNIL) OR (A = SYSTEM.NearNIL) THEN
  726. Lib.RunTimeError(CoreSig._FatalErrorPos(), 8EH, 'NearHeapChangeSize: Invalid Argument');
  727. END;
  728. IF NearHeapChangeAlloc(Source, A, OldSize, NewSize) THEN
  729. RETURN;
  730. END;
  731. OldA := A;
  732. NearHeapAllocate(Source, A, NewSize);
  733. Lib.WordMove(ADR(OldA^), ADR(A^), OldSize DIV 2);
  734. NearHeapDeallocate(Source, OldA, OldSize);
  735. END NearHeapChangeSize;
  736. PROCEDURE NearHeapChangeAlloc(Source: NearHeapRecPtr; A: NearADDRESS;
  737. OldSize, NewSize : CARDINAL): BOOLEAN;
  738. VAR
  739. Curr, SplitRec, NextRec, PrevRec, NewRec: NearHeapRecPtr;
  740. Temp: NearHeapRec;
  741. SplitSize: CARDINAL;
  742. (*%T _OS2 *)
  743. T: NearADDRESS;
  744. (*%E *)
  745. BEGIN
  746. IF (Source = SYSTEM.NearNIL) OR (A = SYSTEM.NearNIL) THEN
  747. Lib.RunTimeError(CoreSig._FatalErrorPos(), 8FH, 'NearHeapChangeAlloc: Invalid Argument');
  748. END;
  749. (*%T _OS2 *)
  750. IF Source = NearHeap THEN
  751. T := CoreMem._nexpand(A, NewSize);
  752. RETURN T # NearNIL;
  753. END;
  754. (*%E *)
  755. IF NewSize < Align THEN
  756. NewSize := Align;
  757. ELSE
  758. NewSize := ( (NewSize+Align-1) DIV Align) * Align;
  759. IF NewSize = 0 THEN
  760. NewSize:=MAX(CARDINAL);
  761. END;
  762. END;
  763. IF OldSize < Align THEN
  764. OldSize := Align;
  765. ELSE
  766. OldSize := ( (OldSize+Align-1) DIV Align) * Align;
  767. IF OldSize = 0 THEN
  768. OldSize:=MAX(CARDINAL);
  769. END;
  770. END;
  771. IF OldSize = NewSize THEN RETURN TRUE END;
  772. Curr:=NearHeapRecPtr(A);
  773. NextRec:=Source;
  774. LOOP
  775. PrevRec:=NextRec;
  776. NextRec:=NextRec^.next;
  777. IF (NextRec = SYSTEM.NearNIL) OR (CARDINAL(NextRec) > CARDINAL(Curr)) THEN EXIT END;
  778. END;
  779. IF OldSize > NewSize THEN
  780. SplitSize:=OldSize-NewSize;
  781. SplitRec:=NearHeapRecPtr(CARDINAL(Curr)+NewSize);
  782. SplitRec^.size:=SplitSize;
  783. SplitRec^.next:=NextRec;
  784. PrevRec^.next:=SplitRec;
  785. Merge(SplitRec, NextRec);
  786. RETURN TRUE;
  787. END;
  788. IF (NextRec # SYSTEM.NearNIL) AND (NearHeapRecPtr(CARDINAL(Curr)+OldSize) = NextRec) THEN (* Next Block is free *)
  789. Temp.size := OldSize+NextRec^.size;
  790. Temp.next := NextRec^.next;
  791. IF Temp.size = NewSize THEN
  792. PrevRec^.next := Temp.next;
  793. ELSE
  794. NewRec := NearHeapRecPtr(CARDINAL(Curr)+NewSize);
  795. PrevRec^.next := NewRec;
  796. NewRec^.size := Temp.size-NewSize;
  797. NewRec^.next := Temp.next;
  798. END;
  799. RETURN TRUE;
  800. ELSE
  801. RETURN FALSE;
  802. END;
  803. END NearHeapChangeAlloc;
  804. (*%F _DLL *)
  805. PROCEDURE NearAllocate(VAR a: NearADDRESS; size: CARDINAL);
  806. BEGIN
  807. NearHeapAllocate(NearHeap,a,size);
  808. END NearAllocate;
  809. PROCEDURE NearDeallocate(VAR a: NearADDRESS; size: CARDINAL);
  810. BEGIN
  811. NearHeapDeallocate(NearHeap,a,size);
  812. END NearDeallocate;
  813. PROCEDURE NearAvailable(size: CARDINAL) : BOOLEAN;
  814. BEGIN
  815. RETURN size <= NearHeapAvail(NearHeap);
  816. END NearAvailable;
  817. (*%E *)
  818. (*%T _DLL *)
  819. PROCEDURE NearAllocate(VAR a: NearADDRESS; size: CARDINAL);
  820. BEGIN
  821. a := NearNIL;
  822. END NearAllocate;
  823. PROCEDURE NearDeallocate(VAR a: NearADDRESS; size: CARDINAL);
  824. BEGIN
  825. END NearDeallocate;
  826. PROCEDURE NearAvailable(size: CARDINAL) : BOOLEAN;
  827. BEGIN
  828. RETURN FALSE;
  829. END NearAvailable;
  830. (*%E *)
  831. (*%F _OS2 *)
  832. PROCEDURE SegAllocate(Size: CARDINAL): CARDINAL;
  833. VAR
  834. S: FarADDRESS;
  835. BEGIN
  836. FarAllocate(S, Size);
  837. RETURN Seg(S^);
  838. END SegAllocate;
  839. PROCEDURE SegDeallocate(Sel: CARDINAL; Size: CARDINAL);
  840. VAR
  841. S: FarADDRESS;
  842. BEGIN
  843. S := [Sel: 0];
  844. FarDeallocate(S, Size);
  845. END SegDeallocate;
  846. (*%E *)
  847. (*%T _OS2 *)
  848. PROCEDURE SegAllocate(Size: CARDINAL): CARDINAL;
  849. VAR
  850. S: CARDINAL;
  851. BEGIN
  852. IF Dos.AllocSeg(Size, S, 0) = 0 THEN
  853. RETURN S;
  854. END;
  855. RETURN 0;
  856. END SegAllocate;
  857. PROCEDURE SegDeallocate(Sel: CARDINAL; Size: CARDINAL);
  858. BEGIN
  859. IF Dos.FreeSeg(Sel) # 0 THEN END;
  860. END SegDeallocate;
  861. (*%E *)
  862. BEGIN
  863. Check := TRUE;
  864. ClearOnAllocate := FALSE;
  865. NearHeap := NearHeapRecPtr(0FFFFH);
  866. (*%F _OS2 *)
  867. MainHeap := [SYSTEM.HeapBase: 0];
  868. NearHeapSetup := FALSE;
  869. FarHeapSetup := FALSE;
  870. (*%E *)
  871. END Storage.
  872.