WSTORAGE.MOD 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. (* Release 3.00 *)
  2. (* Copyright (C) 1987..1991 Jensen & Partners International *)
  3. (*%F _fdata *)
  4. (*# call(seg_name => null) *)
  5. (*%E *)
  6. (*# data(seg_name => null) *)
  7. (*# check(stack=>off,
  8. index=>off,
  9. range=>off,
  10. overflow=>off,
  11. nil_ptr=>off) *)
  12. (*# module(implementation=>off) *)
  13. IMPLEMENTATION MODULE Storage;
  14. IMPORT SYSTEM, Lib, Windows, CoreSig;
  15. (*%T _mthread *)
  16. IMPORT Process;
  17. (*%E *)
  18. CONST
  19. EndMarker = 0FFFFH;
  20. Align = 4;
  21. (* This is DOS ONLY *)
  22. PROCEDURE FarMakeHeap( Source : CARDINAL; (* base segment of heap *)
  23. Size : CARDINAL (* size in paragraphs *)
  24. ) : FarHeapRecPtr;
  25. VAR
  26. storage,first,last : FarHeapRecPtr;
  27. BEGIN
  28. (*%T _mthread *)
  29. Process.Lock;
  30. (*%E *)
  31. storage := [Source:0];
  32. first := [Source+1:0];
  33. last := [Source+Size-1:0];
  34. storage^.next := first;
  35. storage^.size := 0;
  36. first^.next := last;
  37. last^.next := storage;
  38. first^.size := Size-2;
  39. last^.size := EndMarker;
  40. (*%T _mthread *)
  41. Process.Unlock;
  42. (*%E *)
  43. RETURN storage;
  44. END FarMakeHeap;
  45. PROCEDURE FarHeapAllocate(Source : FarHeapRecPtr; (* source heap *)
  46. VAR A : FarADDRESS; (* result *)
  47. Size : CARDINAL); (* request size in paragraphs *)
  48. VAR
  49. res,prev,split : FarHeapRecPtr;
  50. BEGIN
  51. IF Source = MainHeap THEN
  52. Lib.RunTimeError(CoreSig._FatalErrorPos(), 90H, 'FarHeapAllocate : Out Of Space');
  53. RETURN;
  54. END;
  55. (*%T _mthread *)
  56. Process.Lock;
  57. (*%E *)
  58. IF Size=0 THEN INC(Size) END ;
  59. prev := Source;
  60. WHILE prev^.next^.size < Size DO
  61. prev := prev^.next;
  62. END;
  63. res := prev^.next;
  64. IF res^.size = EndMarker THEN (* heap run out of space *)
  65. SYSTEM.EI ;
  66. Lib.RunTimeError(CoreSig._FatalErrorPos(), 90H, 'FarHeapAllocate : Out Of Space');
  67. END;
  68. IF res^.size = Size THEN (* block correct size *)
  69. prev^.next := res^.next;
  70. ELSE (* split block, bottom half returned, top half linked to free chain *)
  71. split := [CARDINAL(Seg(res^))+Size:0];
  72. prev^.next := split;
  73. split^.next := res^.next;
  74. split^.size := res^.size - Size;
  75. END;
  76. (*%T _mthread *)
  77. Process.Unlock;
  78. (*%E *)
  79. A := FarADR(res^);
  80. END FarHeapAllocate;
  81. PROCEDURE FarHeapAvail(Source: FarHeapRecPtr) : CARDINAL;
  82. (* returns the largest block size available for allocation in paragraphs *)
  83. VAR
  84. size : CARDINAL;
  85. p : FarHeapRecPtr;
  86. BEGIN
  87. IF Source = MainHeap THEN
  88. RETURN 0;
  89. END;
  90. (*%T _mthread *)
  91. Process.Lock;
  92. (*%E *)
  93. p := Source^.next;
  94. size := 0;
  95. WHILE p^.size <> EndMarker DO
  96. IF p^.size>size THEN size := p^.size END;
  97. p := p^.next;
  98. END;
  99. (*%T _mthread *)
  100. Process.Unlock;
  101. (*%E *)
  102. RETURN size;
  103. END FarHeapAvail;
  104. PROCEDURE FarHeapTotalAvail(Source: FarHeapRecPtr) : CARDINAL;
  105. (* returns the total block size available for allocation in paragraphs *)
  106. VAR
  107. size : CARDINAL;
  108. p : FarHeapRecPtr;
  109. BEGIN
  110. IF Source = MainHeap THEN
  111. RETURN 0;
  112. END;
  113. (*%T _mthread *)
  114. Process.Lock;
  115. (*%E *)
  116. p := Source^.next;
  117. size := 0;
  118. WHILE p^.size <> EndMarker DO
  119. INC(size,p^.size);
  120. p := p^.next;
  121. END;
  122. (*%T _mthread *)
  123. Process.Unlock;
  124. (*%E *)
  125. RETURN size;
  126. END FarHeapTotalAvail;
  127. PROCEDURE FarHeapDeallocate(Source : FarHeapRecPtr; (* source heap *)
  128. VAR A: FarADDRESS;
  129. Size : CARDINAL ); (* size of block
  130. in paragraphs *)
  131. VAR
  132. target,prev,split : FarHeapRecPtr;
  133. tseg : CARDINAL;
  134. BEGIN
  135. IF Source = MainHeap THEN
  136. RETURN;
  137. END;
  138. IF (CARDINAL(Seg(A^))=0)OR(CARDINAL(Ofs(A^))<>0) THEN
  139. Lib.RunTimeError(CoreSig._FatalErrorPos(), 91H, 'FarHeapDeallocate : Invalid Argument');
  140. END;
  141. (*%T _mthread *)
  142. Process.Lock;
  143. (*%E *)
  144. IF Size=0 THEN INC(Size) END ;
  145. target := A;
  146. prev := Source;
  147. tseg := Seg(target^);
  148. WHILE CARDINAL(Seg(prev^.next^)) < tseg DO
  149. prev := prev^.next;
  150. END;
  151. IF CARDINAL(Seg(prev^))+prev^.size = tseg THEN (* amalgamate with prev *)
  152. prev^.size := prev^.size + Size;
  153. target := prev;
  154. ELSIF CARDINAL(Seg(prev^))+prev^.size > tseg THEN (* Heap corrupt *)
  155. SYSTEM.EI;
  156. Lib.RunTimeError(CoreSig._FatalErrorPos(), 92H, 'FarHeapDeallocate : Heap Corrupt');
  157. ELSE
  158. (* link after prev *)
  159. target^.next := prev^.next;
  160. prev^.next := target;
  161. target^.size := Size;
  162. END;
  163. IF (target^.next^.size <> EndMarker)
  164. AND (CARDINAL(Seg(target^.next^)) = CARDINAL(Seg(target^))+target^.size) THEN
  165. (* amalgamate with next block *)
  166. target^.size := target^.size+target^.next^.size;
  167. target^.next := target^.next^.next;
  168. END;
  169. A := SYSTEM.FarNIL;
  170. (*%T _mthread *)
  171. Process.Unlock;
  172. (*%E *)
  173. END FarHeapDeallocate;
  174. PROCEDURE FarHeapChangeAlloc(Source : FarHeapRecPtr; (* source heap *)
  175. A : FarADDRESS; (* block to change *)
  176. OldSize, (* old size of block *)
  177. NewSize : CARDINAL) (* new size of block *)
  178. (* in paragraphs *)
  179. : BOOLEAN; (* if sucessful *)
  180. (* This procedure attempts to change the size of an allocated block
  181. It returns TRUE if succeeded (only expansion can fail)
  182. *)
  183. VAR
  184. target,prev,
  185. split : FarHeapRecPtr;
  186. tseg : CARDINAL;
  187. result : BOOLEAN;
  188. extendsize : CARDINAL;
  189. Res : FarADDRESS;
  190. BEGIN
  191. IF Source = MainHeap THEN
  192. RETURN FALSE;
  193. END;
  194. IF (CARDINAL(Seg(A^))=0)OR(CARDINAL(Ofs(A^))<>0) THEN
  195. Lib.RunTimeError(CoreSig._FatalErrorPos(), 93H, 'FarHeapChangeAlloc : Invalid Argument');
  196. END;
  197. IF OldSize = NewSize THEN RETURN TRUE END;
  198. IF OldSize > NewSize THEN
  199. target := [CARDINAL(Seg(A^))+NewSize:0];
  200. FarHeapDeallocate(Source,target,OldSize-NewSize);
  201. RETURN TRUE;
  202. END;
  203. extendsize := NewSize-OldSize;
  204. (*%T _mthread *)
  205. Process.Lock;
  206. (*%E *)
  207. target := A;
  208. prev := Source;
  209. tseg := Seg(target^);
  210. WHILE CARDINAL(Seg(prev^.next^)) < tseg DO
  211. prev := prev^.next;
  212. END;
  213. IF (prev^.next^.size <> EndMarker) AND
  214. (CARDINAL(Seg(prev^.next^)) = CARDINAL(Seg(target^))+OldSize) AND
  215. (extendsize <= prev^.next^.size) THEN
  216. IF (extendsize = prev^.next^.size) THEN
  217. prev^.next := prev^.next^.next
  218. ELSE
  219. split := [CARDINAL(Seg(target^))+NewSize:0];
  220. split^.next := prev^.next^.next;
  221. split^.size := prev^.next^.size - extendsize;
  222. prev^.next := split;
  223. END;
  224. result := TRUE;
  225. ELSE
  226. result := FALSE;
  227. END;
  228. (*%T _mthread *)
  229. Process.Unlock;
  230. (*%E *)
  231. RETURN result;
  232. END FarHeapChangeAlloc;
  233. PROCEDURE FarHeapChangeSize(Source : FarHeapRecPtr; (* source heap *)
  234. VAR A : FarADDRESS; (* block to change *)
  235. OldSize, (* old size of block *)
  236. NewSize : CARDINAL ); (* new size of block
  237. in paragraphs *)
  238. (*
  239. This procedure will change the size of an allocated block
  240. avoiding any copy of data if possible
  241. calls HeapChangeAlloc
  242. *)
  243. VAR
  244. na : FarADDRESS;
  245. BEGIN
  246. IF Source = MainHeap THEN
  247. Lib.RunTimeError(CoreSig._FatalErrorPos(), 94H, 'FarHeapChangeSize : Out Of Memory');
  248. RETURN;
  249. END;
  250. IF NOT FarHeapChangeAlloc ( Source, A, OldSize, NewSize ) THEN
  251. FarHeapAllocate(Source,na,NewSize);
  252. Lib.FarWordMove(A, na, OldSize*8);
  253. FarHeapDeallocate(Source,A,OldSize);
  254. A := na;
  255. END;
  256. END FarHeapChangeSize;
  257. PROCEDURE NearMakeHeap(Source: NearADDRESS; Size: CARDINAL): NearHeapRecPtr;
  258. (* ========== *)
  259. VAR Storage, FirstFree: NearHeapRecPtr;
  260. BEGIN
  261. Size := (Size DIV Align) * Align;
  262. IF Size < 10 THEN
  263. Lib.RunTimeError(CoreSig._FatalErrorPos(), 95H, 'NearMakeHeap: Size Too Small');
  264. END;
  265. Storage := NearHeapRecPtr(Source);
  266. Storage^.next := NearHeapRecPtr(CARDINAL(Source)+Align);
  267. Storage^.size :=4;
  268. FirstFree := Storage^.next;
  269. FirstFree^.size := Size - Align;
  270. FirstFree^.next := SYSTEM.NearNIL;
  271. RETURN Storage;
  272. END NearMakeHeap;
  273. PROCEDURE NearHeapAllocate(Source: NearHeapRecPtr; VAR A: NearADDRESS; Size: CARDINAL);
  274. (* ======== *)
  275. VAR Base, Free, New: NearHeapRecPtr;
  276. BEGIN
  277. IF Size = 0 THEN INC(Size) END;
  278. Size := (( (Size+Align-1) DIV Align) * Align) + Align;
  279. IF Size = 0 THEN
  280. Size:=MAX(CARDINAL);
  281. END;
  282. Base := Source;
  283. LOOP
  284. Free := Base^.next;
  285. IF Free = SYSTEM.NearNIL THEN
  286. IF Check THEN
  287. Lib.RunTimeError(CoreSig._FatalErrorPos(), 96H, 'NearHeapAllocate: Out Of Memory');
  288. ELSE
  289. A := SYSTEM.NearNIL;
  290. RETURN;
  291. END;
  292. ELSIF Free^.size >= Size THEN
  293. EXIT;
  294. END;
  295. Base := Free;
  296. END;
  297. IF Free^.size = Size THEN
  298. Base^.next := Free^.next;
  299. ELSE
  300. New := NearHeapRecPtr(CARDINAL(Free)+Size);
  301. Base^.next := New;
  302. New^.size := Free^.size - Size;
  303. New^.next := Free^.next;
  304. END;
  305. IF ClearOnAllocate THEN
  306. Lib.WordFill ( ADDRESS(CARDINAL(Free)+Align) , (Size-Align) DIV 2 , 0 );
  307. END;
  308. A := NearADDRESS(CARDINAL(Free)+Align);
  309. END NearHeapAllocate;
  310. PROCEDURE Merge(PrevRec, LowRec, HighRec, Source: NearHeapRecPtr);
  311. BEGIN
  312. IF (LowRec = SYSTEM.NearNIL) OR (HighRec = SYSTEM.NearNIL) THEN RETURN END;
  313. IF (LowRec = Source) THEN RETURN END;
  314. IF NearHeapRecPtr(CARDINAL(LowRec)+LowRec^.size) # HighRec THEN RETURN END;
  315. INC(LowRec^.size, HighRec^.size);
  316. LowRec^.next:=HighRec^.next;
  317. PrevRec^.next:=LowRec;
  318. RETURN;
  319. END Merge;
  320. PROCEDURE NearHeapDeallocate(Source: NearHeapRecPtr; VAR A: NearADDRESS; Size: CARDINAL );
  321. VAR
  322. Curr, Base, Free: NearHeapRecPtr;
  323. BEGIN
  324. Size := (( (Size+Align-1) DIV Align) * Align) + Align;
  325. Curr := NearHeapRecPtr(CARDINAL(A) - Align);
  326. A := SYSTEM.NearNIL;
  327. IF Curr = SYSTEM.NearNIL THEN
  328. Lib.RunTimeError(CoreSig._FatalErrorPos(), 97H, 'NearHeapDeallocate: Invalid Argument');
  329. END;
  330. Base:=Source;
  331. LOOP
  332. Free := Base^.next;
  333. IF (Free = SYSTEM.NearNIL) OR (CARDINAL(Curr) < CARDINAL(Free)) THEN EXIT; END;
  334. Base := Free;
  335. END;
  336. IF (CARDINAL(Base) + Base^.size = CARDINAL(Curr)) AND (Base # Source) THEN
  337. INC ( Base^.size , Size );
  338. Curr := Base;
  339. ELSE
  340. Base^.next := Curr;
  341. Curr^.next := Free;
  342. Curr^.size := Size;
  343. END;
  344. IF CARDINAL(Curr) + Curr^.size = CARDINAL(Free) THEN
  345. INC ( Curr^.size, Free^.size);
  346. Curr^.next := Free^.next;
  347. END;
  348. END NearHeapDeallocate;
  349. PROCEDURE NearHeapAvail(Source: NearHeapRecPtr): CARDINAL;
  350. VAR
  351. Curr: NearHeapRecPtr;
  352. Size: CARDINAL;
  353. BEGIN
  354. Curr := Source;
  355. Size := 0;
  356. WHILE Curr # SYSTEM.NearNIL DO
  357. IF Size < Curr^.size THEN
  358. Size := Curr^.size;
  359. END;
  360. Curr := Curr^.next;
  361. END;
  362. RETURN Size - Align;
  363. END NearHeapAvail;
  364. PROCEDURE NearHeapTotalAvail(Source: NearHeapRecPtr): CARDINAL;
  365. VAR
  366. Curr: NearHeapRecPtr;
  367. Size: CARDINAL;
  368. BEGIN
  369. Curr := Source^.next;
  370. Size := 0;
  371. WHILE Curr # SYSTEM.NearNIL DO
  372. INC ( Size , Curr^.size - Align);
  373. Curr := Curr^.next;
  374. END;
  375. RETURN Size;
  376. END NearHeapTotalAvail;
  377. PROCEDURE NearHeapChangeSize(Source: NearHeapRecPtr; VAR A: NearADDRESS;
  378. OldSize, NewSize : CARDINAL);
  379. VAR
  380. Curr, NextRec, PrevRec, NewRec: NearHeapRecPtr;
  381. SplitSize: CARDINAL;
  382. OldA: NearADDRESS;
  383. BEGIN
  384. NewSize := (( (NewSize+Align-1) DIV Align) * Align) + Align;
  385. OldSize := (( (OldSize+Align-1) DIV Align) * Align) + Align;
  386. IF OldSize = NewSize THEN RETURN END;
  387. Curr:=NearHeapRecPtr(CARDINAL(A)-Align);
  388. NextRec:=Source;
  389. PrevRec:=Source;
  390. LOOP
  391. IF NextRec = SYSTEM.NearNIL THEN EXIT END;
  392. IF CARDINAL(NextRec) > CARDINAL(Curr) THEN EXIT END;
  393. PrevRec:=NextRec;
  394. NextRec:=NextRec^.next;
  395. END;
  396. IF OldSize > NewSize THEN
  397. SplitSize:=OldSize-NewSize;
  398. Curr^.size:=NewSize;
  399. NewRec:=NearHeapRecPtr(CARDINAL(Curr)+NewSize);
  400. NewRec^.size:=SplitSize;
  401. NewRec^.next:=PrevRec^.next;
  402. PrevRec^.next:=NewRec;
  403. Merge(PrevRec, NewRec, NextRec, Source);
  404. RETURN ;
  405. END;
  406. IF NearHeapRecPtr(CARDINAL(Curr)+OldSize) = NextRec THEN (* Next Block is free *)
  407. Curr^.size := OldSize;
  408. Merge(PrevRec, Curr, NextRec, Source);
  409. IF OldSize = NewSize THEN
  410. PrevRec^.next := Curr^.next;
  411. RETURN;
  412. ELSE
  413. NewRec := NearHeapRecPtr(CARDINAL(Curr)+NewSize);
  414. NewRec^.size := Curr^.size-NewSize;
  415. NewRec^.next := Curr^.next;
  416. PrevRec^.next := NewRec;
  417. RETURN;
  418. END;
  419. END;
  420. OldA:=A;
  421. NearHeapDeallocate(Source, A, OldSize);
  422. NearHeapAllocate(Source, A, NewSize);
  423. Lib.WordMove(ADR(OldA), ADR(A), OldSize DIV 2);
  424. RETURN;
  425. END NearHeapChangeSize;
  426. PROCEDURE NearHeapChangeAlloc(Source: NearHeapRecPtr; A: NearADDRESS;
  427. OldSize, NewSize : CARDINAL): BOOLEAN;
  428. VAR
  429. Curr, NextRec, PrevRec, NewRec: NearHeapRecPtr;
  430. SplitSize: CARDINAL;
  431. BEGIN
  432. NewSize := (( (NewSize+Align-1) DIV Align) * Align) + Align;
  433. OldSize := (( (OldSize+Align-1) DIV Align) * Align) + Align;
  434. IF OldSize = NewSize THEN RETURN TRUE END;
  435. Curr:=NearHeapRecPtr(CARDINAL(A)-Align);
  436. PrevRec:=Source;
  437. NextRec:=Source;
  438. LOOP
  439. IF NextRec = SYSTEM.NearNIL THEN EXIT END;
  440. IF CARDINAL(NextRec) > CARDINAL(Curr) THEN EXIT END;
  441. PrevRec:=NextRec;
  442. NextRec:=NextRec^.next;
  443. END;
  444. IF OldSize > NewSize THEN
  445. SplitSize:=OldSize-NewSize;
  446. Curr^.size:=NewSize;
  447. NewRec:=NearHeapRecPtr(CARDINAL(Curr)+NewSize);
  448. NewRec^.size:=SplitSize;
  449. NewRec^.next:=PrevRec^.next;
  450. PrevRec^.next:=NewRec;
  451. Merge(PrevRec, NewRec, NextRec, Source);
  452. RETURN TRUE;
  453. END;
  454. IF NearHeapRecPtr(CARDINAL(Curr)+OldSize) = NextRec THEN (* Next Block is free *)
  455. Curr^.size := OldSize;
  456. Merge(PrevRec, Curr, NextRec, Source);
  457. IF OldSize = NewSize THEN
  458. PrevRec^.next := Curr^.next;
  459. ELSE
  460. NewRec := NearHeapRecPtr(CARDINAL(Curr)+NewSize);
  461. NewRec^.size := OldSize-NewSize;
  462. NewRec^.next := Curr^.next;
  463. PrevRec^.next := NewRec;
  464. END;
  465. RETURN TRUE;
  466. ELSE
  467. RETURN FALSE;
  468. END;
  469. END NearHeapChangeAlloc;
  470. TYPE
  471. HANDLEPtr = POINTER TO Windows.HANDLE;
  472. PROCEDURE NearDeallocate(VAR a: NearADDRESS; size: CARDINAL);
  473. BEGIN
  474. IF ORD(Windows.LocalFree(Windows.HANDLE(a))) # 0 THEN END;
  475. a:= NearADDRESS(NIL);
  476. END NearDeallocate;
  477. PROCEDURE NearAllocate(VAR a: NearADDRESS; size: CARDINAL);
  478. VAR
  479. mode: CARDINAL;
  480. h: Windows.HANDLE;
  481. BEGIN
  482. IF size = 0 THEN size := 2 END;
  483. mode := Windows.LMEM_FIXED;
  484. IF ClearOnAllocate THEN
  485. mode := mode + Windows.LMEM_ZEROINIT;
  486. END;
  487. h := Windows.LocalAlloc(mode, size);
  488. IF ORD(h) = 0 THEN
  489. Lib.RunTimeError(CoreSig._FatalErrorPos(), 98H, 'NearAllocate: Out Of Memory');
  490. END;
  491. a := NearADDRESS(h);
  492. END NearAllocate;
  493. PROCEDURE NearAvailable(size: CARDINAL) : BOOLEAN;
  494. BEGIN
  495. RETURN TRUE;
  496. END NearAvailable;
  497. PROCEDURE FarAllocate (VAR a: FarADDRESS; size: CARDINAL);
  498. BEGIN
  499. END FarAllocate;
  500. PROCEDURE FarDeallocate(VAR a: FarADDRESS; size: CARDINAL);
  501. BEGIN
  502. END FarDeallocate;
  503. PROCEDURE FarAvailable(size: CARDINAL ): BOOLEAN;
  504. BEGIN
  505. RETURN TRUE;
  506. END FarAvailable;
  507. PROCEDURE SegAllocate(Size: CARDINAL): CARDINAL;
  508. BEGIN
  509. RETURN 0;
  510. END SegAllocate;
  511. PROCEDURE SegDeallocate(Sel: CARDINAL; Size: CARDINAL);
  512. BEGIN
  513. END SegDeallocate;
  514. BEGIN
  515. MainHeap:=[0FFFFH:0FFFFH];
  516. END Storage.
  517.