tinyheap.inc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2011 by the Free Pascal development team.
  4. Tiny heap manager for the i8086 near heap, embedded targets, etc.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. { The heap, implemented here is TP7-compatible in the i8086 far data memory
  12. models. It's basically a linked list of free blocks, which are kept ordered by
  13. start address. The FreeList variable points to the start of the list. Each
  14. free block, except the last one, contains a TTinyHeapBlock structure, which
  15. holds the block size and a pointer to the next free block. The HeapPtr
  16. variable points to the last free block, indicating the end of the list. The
  17. last block is special in that it doesn't contain a TTinyHeapBlock structure.
  18. Instead its size is determined by the pointer difference (HeapEnd-HeapPtr).
  19. It *can* become zero sized, when all the memory inside of it is allocated, in
  20. which case, HeapPtr will become equal to HeapEnd. }
  21. {$ifdef FPC_TINYHEAP_HUGE}
  22. {$HugePointerArithmeticNormalization On}
  23. {$HugePointerComparisonNormalization On}
  24. {$endif FPC_TINYHEAP_HUGE}
  25. type
  26. { TTinyHeapMemBlockSize holds the size of an *allocated* memory block,
  27. and is written at position:
  28. memblockstart-sizeof(TTinyHeapMemBlockSize) }
  29. PTinyHeapMemBlockSize = ^TTinyHeapMemBlockSize; {$ifdef FPC_TINYHEAP_HUGE}huge;{$endif}
  30. TTinyHeapMemBlockSize = PtrUInt;
  31. { TTinyHeapFreeBlockSize holds the size of a *free* memory block, as a
  32. part of the TTinyHeapBlock structure }
  33. {$ifdef FPC_TINYHEAP_HUGE}
  34. TTinyHeapFreeBlockSize = record
  35. OfsSize: Word;
  36. SegSize: Word;
  37. end;
  38. {$else FPC_TINYHEAP_HUGE}
  39. TTinyHeapFreeBlockSize = PtrUInt;
  40. {$endif FPC_TINYHEAP_HUGE}
  41. TTinyHeapPointerArithmeticType = ^Byte; {$ifdef FPC_TINYHEAP_HUGE}huge;{$endif}
  42. const
  43. TinyHeapMinBlock = 4*sizeof(pointer);
  44. type
  45. PTinyHeapBlock = ^TTinyHeapBlock;
  46. TTinyHeapBlock = record
  47. Size: TTinyHeapFreeBlockSize;
  48. Next: PTinyHeapBlock;
  49. end;
  50. TinyHeapAllocGranularity = sizeof(TTinyHeapBlock);
  51. function EncodeTinyHeapFreeBlockSize(Size: PtrUInt): TTinyHeapFreeBlockSize; inline;
  52. begin
  53. {$ifdef FPC_TINYHEAP_HUGE}
  54. EncodeTinyHeapFreeBlockSize.OfsSize := Size and 15;
  55. EncodeTinyHeapFreeBlockSize.SegSize := Size shr 4;
  56. {$else FPC_TINYHEAP_HUGE}
  57. EncodeTinyHeapFreeBlockSize := Size;
  58. {$endif FPC_TINYHEAP_HUGE}
  59. end;
  60. function DecodeTinyHeapFreeBlockSize(Size: TTinyHeapFreeBlockSize): PtrUInt; inline;
  61. begin
  62. {$ifdef FPC_TINYHEAP_HUGE}
  63. DecodeTinyHeapFreeBlockSize := (PtrUInt(Size.SegSize) shl 4) + Size.OfsSize;
  64. {$else FPC_TINYHEAP_HUGE}
  65. DecodeTinyHeapFreeBlockSize := Size;
  66. {$endif FPC_TINYHEAP_HUGE}
  67. end;
  68. procedure InternalTinyFreeMem(Addr: Pointer; Size: PtrUInt); forward;
  69. function FindSize(p: pointer): TTinyHeapMemBlockSize;
  70. begin
  71. FindSize := PTinyHeapMemBlockSize(p)[-1];
  72. end;
  73. function SysTinyGetMem(Size: ptruint): pointer;
  74. var
  75. p, prev, p2: PTinyHeapBlock;
  76. AllocSize, RestSize: ptruint;
  77. begin
  78. {$ifdef DEBUG_TINY_HEAP}
  79. Write('SysTinyGetMem(', Size, ')=');
  80. {$endif DEBUG_TINY_HEAP}
  81. AllocSize := align(size+sizeof(TTinyHeapMemBlockSize), TinyHeapAllocGranularity);
  82. p := FreeList;
  83. prev := nil;
  84. while (p<>HeapPtr) and (DecodeTinyHeapFreeBlockSize(p^.Size) < AllocSize) do
  85. begin
  86. prev := p;
  87. p := p^.Next;
  88. end;
  89. if p<>HeapPtr then
  90. begin
  91. result := @PTinyHeapMemBlockSize(p)[1];
  92. if DecodeTinyHeapFreeBlockSize(p^.Size)-AllocSize >= TinyHeapMinBlock then
  93. RestSize := DecodeTinyHeapFreeBlockSize(p^.Size)-AllocSize
  94. else
  95. begin
  96. AllocSize := DecodeTinyHeapFreeBlockSize(p^.Size);
  97. RestSize := 0;
  98. end;
  99. if RestSize > 0 then
  100. begin
  101. p2 := pointer(TTinyHeapPointerArithmeticType(p)+AllocSize);
  102. p2^.Next := p^.Next;
  103. p2^.Size := EncodeTinyHeapFreeBlockSize(RestSize);
  104. if prev = nil then
  105. FreeList := p2
  106. else
  107. prev^.next := p2;
  108. end
  109. else
  110. begin
  111. if prev = nil then
  112. FreeList := p^.Next
  113. else
  114. prev^.next := p^.next;
  115. end;
  116. PTinyHeapMemBlockSize(p)^ := size;
  117. end
  118. else
  119. begin
  120. { p=HeapPtr }
  121. if PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr))<AllocSize then
  122. if ReturnNilIfGrowHeapFails then
  123. Result := nil
  124. else
  125. HandleError(203);
  126. result := @PTinyHeapMemBlockSize(HeapPtr)[1];
  127. PTinyHeapMemBlockSize(HeapPtr)^ := size;
  128. HeapPtr := pointer(TTinyHeapPointerArithmeticType(HeapPtr)+AllocSize);
  129. if prev = nil then
  130. FreeList := HeapPtr
  131. else
  132. prev^.next := HeapPtr;
  133. end;
  134. {$ifdef DEBUG_TINY_HEAP}
  135. Writeln(HexStr(Result));
  136. {$endif DEBUG_TINY_HEAP}
  137. end;
  138. function TinyGetAlignedMem(Size, Alignment: ptruint): pointer;
  139. var
  140. mem: Pointer;
  141. memp: ptruint;
  142. begin
  143. if alignment <= sizeof(pointer) then
  144. result := GetMem(size)
  145. else
  146. begin
  147. mem := GetMem(Size+Alignment-1);
  148. memp := align(ptruint(mem), Alignment);
  149. InternalTinyFreeMem(mem, TTinyHeapPointerArithmeticType(memp)-TTinyHeapPointerArithmeticType(mem));
  150. result := pointer(memp);
  151. end;
  152. end;
  153. procedure InternalTinyFreeMem(Addr: Pointer; Size: PtrUInt);
  154. var
  155. p, prev: PTinyHeapBlock;
  156. begin
  157. p := FreeList;
  158. prev := nil;
  159. while (p<>HeapPtr) and (TTinyHeapPointerArithmeticType(p) < TTinyHeapPointerArithmeticType(Addr)) do
  160. begin
  161. prev := p;
  162. p := p^.Next;
  163. end;
  164. { join with previous block? }
  165. if assigned(prev) and ((TTinyHeapPointerArithmeticType(prev)+DecodeTinyHeapFreeBlockSize(prev^.Size)) = TTinyHeapPointerArithmeticType(Addr)) then
  166. begin
  167. Addr:=prev;
  168. Size:=DecodeTinyHeapFreeBlockSize(prev^.size)+Size;
  169. end
  170. else
  171. if assigned(prev) then
  172. prev^.Next := Addr
  173. else
  174. FreeList := Addr;
  175. { join with next block? }
  176. if TTinyHeapPointerArithmeticType(p)=(TTinyHeapPointerArithmeticType(Addr)+Size) then
  177. begin
  178. if p=HeapPtr then
  179. HeapPtr:=Addr
  180. else
  181. begin
  182. PTinyHeapBlock(Addr)^.Next:=p^.Next;
  183. PTinyHeapBlock(Addr)^.Size:=EncodeTinyHeapFreeBlockSize(Size+DecodeTinyHeapFreeBlockSize(p^.Size));
  184. end;
  185. end
  186. else
  187. begin
  188. PTinyHeapBlock(Addr)^.Next:=p;
  189. PTinyHeapBlock(Addr)^.Size:=EncodeTinyHeapFreeBlockSize(Size);
  190. end;
  191. end;
  192. function SysTinyFreeMem(Addr: Pointer): ptruint;
  193. var
  194. sz: ptruint;
  195. begin
  196. {$ifdef DEBUG_TINY_HEAP}
  197. Writeln('SysTinyFreeMem(', HexStr(Addr), ')');
  198. {$endif DEBUG_TINY_HEAP}
  199. if addr=nil then
  200. begin
  201. result:=0;
  202. exit;
  203. end;
  204. if (TTinyHeapPointerArithmeticType(addr) < TTinyHeapPointerArithmeticType(HeapOrg)) or
  205. (TTinyHeapPointerArithmeticType(addr) >= TTinyHeapPointerArithmeticType(HeapPtr)) then
  206. HandleError(204);
  207. sz := Align(FindSize(addr)+SizeOf(TTinyHeapMemBlockSize), TinyHeapAllocGranularity);
  208. InternalTinyFreeMem(@PTinyHeapMemBlockSize(addr)[-1], sz);
  209. result := sz;
  210. end;
  211. function SysTinyFreeMemSize(Addr: Pointer; Size: Ptruint): ptruint;
  212. begin
  213. result := SysTinyFreeMem(addr);
  214. end;
  215. function SysTinyMemSize(p: pointer): ptruint;
  216. begin
  217. result := findsize(p);
  218. end;
  219. function SysTinyAllocMem(size: ptruint): pointer;
  220. begin
  221. result := SysTinyGetMem(size);
  222. if result<>nil then
  223. FillChar(result^,SysTinyMemSize(result),0);
  224. end;
  225. function SysTinyReAllocMem(var p: pointer; size: ptruint):pointer;
  226. var
  227. oldsize, OldAllocSize, NewAllocSize: ptruint;
  228. after_block, before_block, before_before_block: PTinyHeapBlock;
  229. after_block_size, before_block_size: PtrUInt;
  230. new_after_block: PTinyHeapBlock;
  231. begin
  232. {$ifdef DEBUG_TINY_HEAP}
  233. Write('SysTinyReAllocMem(', HexStr(p), ',', size, ')=');
  234. {$endif DEBUG_TINY_HEAP}
  235. if size=0 then
  236. begin
  237. SysTinyFreeMem(p);
  238. result := nil;
  239. p := nil;
  240. end
  241. else if p=nil then
  242. begin
  243. result := AllocMem(size);
  244. p := result;
  245. end
  246. else
  247. begin
  248. if (TTinyHeapPointerArithmeticType(p) < TTinyHeapPointerArithmeticType(HeapOrg)) or
  249. (TTinyHeapPointerArithmeticType(p) >= TTinyHeapPointerArithmeticType(HeapPtr)) then
  250. HandleError(204);
  251. oldsize := FindSize(p);
  252. OldAllocSize := align(oldsize+sizeof(TTinyHeapMemBlockSize), TinyHeapAllocGranularity);
  253. NewAllocSize := align(size+sizeof(TTinyHeapMemBlockSize), TinyHeapAllocGranularity);
  254. if OldAllocSize = NewAllocSize then
  255. begin
  256. { old and new size are the same after alignment, so the memory block is already allocated }
  257. { we just need to update the size }
  258. PTinyHeapMemBlockSize(p)[-1] := size;
  259. if size > oldsize then
  260. FillChar((TTinyHeapPointerArithmeticType(p)+oldsize)^, size-oldsize, 0);
  261. end
  262. else if OldAllocSize > NewAllocSize then
  263. begin
  264. { we're decreasing the memory block size, so we can just free the remaining memory at the end }
  265. PTinyHeapMemBlockSize(p)[-1] := size;
  266. InternalTinyFreeMem(Pointer(TTinyHeapPointerArithmeticType(p)+(NewAllocSize-PtrUInt(SizeOf(TTinyHeapMemBlockSize)))), OldAllocSize-NewAllocSize);
  267. end
  268. else
  269. begin
  270. { we're increasing the memory block size. First, find if there are free memory blocks immediately
  271. before and after our memory block. }
  272. after_block := FreeList;
  273. before_block := nil;
  274. before_before_block := nil;
  275. while (after_block<>HeapPtr) and (TTinyHeapPointerArithmeticType(after_block) < TTinyHeapPointerArithmeticType(p)) do
  276. begin
  277. before_before_block := before_block;
  278. before_block := after_block;
  279. after_block := after_block^.Next;
  280. end;
  281. { is after_block immediately after our block? }
  282. if after_block=Pointer(TTinyHeapPointerArithmeticType(p)+(OldAllocSize-PtrUInt(SizeOf(TTinyHeapMemBlockSize)))) then
  283. begin
  284. if after_block = HeapPtr then
  285. after_block_size := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr))
  286. else
  287. after_block_size := DecodeTinyHeapFreeBlockSize(after_block^.size);
  288. end
  289. else
  290. after_block_size := 0;
  291. { is there enough room after the block? }
  292. if (OldAllocSize+after_block_size)>=NewAllocSize then
  293. begin
  294. if after_block = HeapPtr then
  295. begin
  296. HeapPtr:=Pointer(TTinyHeapPointerArithmeticType(HeapPtr)+(NewAllocSize-OldAllocSize));
  297. if assigned(before_block) then
  298. before_block^.Next := HeapPtr
  299. else
  300. FreeList := HeapPtr;
  301. end
  302. else
  303. begin
  304. if (NewAllocSize-OldAllocSize)=after_block_size then
  305. begin
  306. if assigned(before_block) then
  307. before_block^.Next := after_block^.Next
  308. else
  309. FreeList := after_block^.Next;
  310. end
  311. else
  312. begin
  313. new_after_block := PTinyHeapBlock(TTinyHeapPointerArithmeticType(after_block)+(NewAllocSize-OldAllocSize));
  314. new_after_block^.Next:=after_block^.Next;
  315. new_after_block^.Size:=EncodeTinyHeapFreeBlockSize(after_block_size-(NewAllocSize-OldAllocSize));
  316. if assigned(before_block) then
  317. before_block^.Next := new_after_block
  318. else
  319. FreeList := new_after_block;
  320. end;
  321. end;
  322. PTinyHeapMemBlockSize(p)[-1] := size;
  323. FillChar((TTinyHeapPointerArithmeticType(p)+oldsize)^, size-oldsize, 0);
  324. end
  325. else
  326. begin
  327. { is before_block immediately before our block? }
  328. if assigned(before_block) and (Pointer(TTinyHeapPointerArithmeticType(before_block)+DecodeTinyHeapFreeBlockSize(before_block^.Size))=Pointer(TTinyHeapPointerArithmeticType(p)-SizeOf(TTinyHeapMemBlockSize))) then
  329. before_block_size := DecodeTinyHeapFreeBlockSize(before_block^.Size)
  330. else
  331. before_block_size := 0;
  332. { if there's enough space, we can slide our current block back and reclaim before_block }
  333. if (before_block_size<NewAllocSize) and ((before_block_size+OldAllocSize+after_block_size)>=NewAllocSize) and
  334. { todo: implement this also for after_block_size>0 }
  335. (after_block_size>0) then
  336. begin
  337. if (before_block_size+OldAllocSize+after_block_size)=NewAllocSize then
  338. begin
  339. if after_block=HeapPtr then
  340. begin
  341. HeapPtr := HeapEnd;
  342. if assigned(before_before_block) then
  343. before_before_block^.Next := HeapPtr
  344. else
  345. FreeList := HeapPtr;
  346. end
  347. else
  348. if assigned(before_before_block) then
  349. before_before_block^.Next := after_block^.Next
  350. else
  351. FreeList := after_block^.Next;
  352. end;
  353. Result := Pointer(TTinyHeapPointerArithmeticType(before_block)+SizeOf(TTinyHeapMemBlockSize));
  354. Move(p^, Result^, oldsize);
  355. PTinyHeapMemBlockSize(before_block)^ := size;
  356. if (before_block_size+OldAllocSize+after_block_size)>NewAllocSize then
  357. begin
  358. new_after_block := PTinyHeapBlock(TTinyHeapPointerArithmeticType(before_block)+NewAllocSize);
  359. new_after_block^.Next:=after_block^.Next;
  360. new_after_block^.Size:=EncodeTinyHeapFreeBlockSize(before_block_size+after_block_size-(NewAllocSize-OldAllocSize));
  361. if assigned(before_before_block) then
  362. before_before_block^.Next := new_after_block
  363. else
  364. FreeList := new_after_block;
  365. end;
  366. FillChar((TTinyHeapPointerArithmeticType(Result)+oldsize)^, size-oldsize, 0);
  367. p := Result;
  368. end
  369. else
  370. begin
  371. result := AllocMem(size);
  372. if result <> nil then
  373. begin
  374. if oldsize > size then
  375. oldsize := size;
  376. move(pbyte(p)^, pbyte(result)^, oldsize);
  377. end;
  378. SysTinyFreeMem(p);
  379. p := result;
  380. end;
  381. end;
  382. end;
  383. end;
  384. {$ifdef DEBUG_TINY_HEAP}
  385. Writeln(HexStr(result));
  386. {$endif DEBUG_TINY_HEAP}
  387. end;
  388. function MemAvail: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif};
  389. var
  390. p: PTinyHeapBlock;
  391. begin
  392. MemAvail := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr));
  393. if MemAvail > 0 then
  394. Dec(MemAvail, SizeOf(TTinyHeapMemBlockSize));
  395. p := FreeList;
  396. while p <> HeapPtr do
  397. begin
  398. Inc(MemAvail, DecodeTinyHeapFreeBlockSize(p^.Size)-SizeOf(TTinyHeapMemBlockSize));
  399. p := p^.Next;
  400. end;
  401. end;
  402. function MaxAvail: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif};
  403. var
  404. p: PTinyHeapBlock;
  405. begin
  406. MaxAvail := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr));
  407. p := FreeList;
  408. while p <> HeapPtr do
  409. begin
  410. if DecodeTinyHeapFreeBlockSize(p^.Size) > MaxAvail then
  411. MaxAvail := DecodeTinyHeapFreeBlockSize(p^.Size);
  412. p := p^.Next;
  413. end;
  414. if MaxAvail > 0 then
  415. Dec(MaxAvail, SizeOf(TTinyHeapMemBlockSize));
  416. end;
  417. procedure Mark(var p: Pointer);
  418. begin
  419. p := HeapPtr;
  420. end;
  421. procedure Release(var p: Pointer);
  422. begin
  423. HeapPtr := p;
  424. FreeList := p;
  425. end;
  426. procedure InternalTinyAlign(var AAddress: Pointer; ASize: PtrUInt);
  427. var
  428. alignment_inc: smallint;
  429. begin
  430. alignment_inc := TTinyHeapPointerArithmeticType(align(AAddress,TinyHeapAllocGranularity))-TTinyHeapPointerArithmeticType(AAddress);
  431. Inc(AAddress,alignment_inc);
  432. Dec(ASize,alignment_inc);
  433. Dec(ASize,ASize mod TinyHeapAllocGranularity);
  434. end;
  435. { Strongly simplified version of RegisterTinyHeapBlock, which can be used when
  436. the heap is only a single contiguous memory block. If you want to add
  437. multiple blocks to the heap, you should use RegisterTinyHeapBlock instead. }
  438. procedure RegisterTinyHeapBlock_Simple(AAddress: Pointer; ASize: PtrUInt);
  439. begin
  440. {$ifdef DEBUG_TINY_HEAP}
  441. Writeln('RegisterTinyHeapBlock_Simple(', HexStr(AAddress), ',', ASize, ')');
  442. {$endif DEBUG_TINY_HEAP}
  443. InternalTinyAlign(AAddress, ASize);
  444. HeapOrg:=AAddress;
  445. HeapPtr:=AAddress;
  446. FreeList:=AAddress;
  447. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize);
  448. end;
  449. { Strongly simplified version of RegisterTinyHeapBlock, which can be used when
  450. the heap is only a single contiguous memory block and the address and size
  451. are already aligned on a TinyHeapAllocGranularity boundary. }
  452. procedure RegisterTinyHeapBlock_Simple_Prealigned(AAddress: Pointer; ASize: PtrUInt);
  453. begin
  454. {$ifdef DEBUG_TINY_HEAP}
  455. Writeln('RegisterTinyHeapBlock_Simple_Prealigned(', HexStr(AAddress), ',', ASize, ')');
  456. {$endif DEBUG_TINY_HEAP}
  457. HeapOrg:=AAddress;
  458. HeapPtr:=AAddress;
  459. FreeList:=AAddress;
  460. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize);
  461. end;
  462. procedure RegisterTinyHeapBlock(AAddress: pointer; ASize: ptruint);
  463. var
  464. alignment_inc: smallint;
  465. p: PTinyHeapBlock;
  466. begin
  467. {$ifdef DEBUG_TINY_HEAP}
  468. Writeln('RegisterTinyHeapBlock(', HexStr(AAddress), ',', ASize, ')');
  469. {$endif DEBUG_TINY_HEAP}
  470. InternalTinyAlign(AAddress, ASize);
  471. if HeapOrg=nil then
  472. begin
  473. HeapOrg:=AAddress;
  474. HeapPtr:=AAddress;
  475. FreeList:=AAddress;
  476. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize);
  477. end
  478. else
  479. begin
  480. if (TTinyHeapPointerArithmeticType(HeapOrg) > TTinyHeapPointerArithmeticType(AAddress)) then
  481. HeapOrg:=AAddress;
  482. if TTinyHeapPointerArithmeticType(AAddress) > TTinyHeapPointerArithmeticType(HeapEnd) then
  483. begin
  484. if TTinyHeapPointerArithmeticType(HeapPtr) = TTinyHeapPointerArithmeticType(HeapEnd) then
  485. begin
  486. if FreeList=HeapPtr then
  487. FreeList:=AAddress
  488. else
  489. begin
  490. p:=FreeList;
  491. while p^.Next<>HeapPtr do
  492. p:=p^.Next;
  493. PTinyHeapBlock(HeapPtr)^.Next:=AAddress;
  494. end;
  495. end
  496. else
  497. begin
  498. PTinyHeapBlock(HeapPtr)^.Size:=EncodeTinyHeapFreeBlockSize(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr));
  499. PTinyHeapBlock(HeapPtr)^.Next:=AAddress;
  500. end;
  501. HeapPtr:=AAddress;
  502. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize);
  503. end
  504. else if TTinyHeapPointerArithmeticType(AAddress) = TTinyHeapPointerArithmeticType(HeapEnd) then
  505. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize)
  506. else
  507. InternalTinyFreeMem(AAddress, ASize);
  508. end;
  509. end;
  510. const
  511. TinyHeapMemoryManager: TMemoryManager = (
  512. NeedLock: false; // Obsolete
  513. GetMem: @SysTinyGetMem;
  514. FreeMem: @SysTinyFreeMem;
  515. FreeMemSize: @SysTinyFreeMemSize;
  516. AllocMem: @SysTinyAllocMem;
  517. ReAllocMem: @SysTinyReAllocMem;
  518. MemSize: @SysTinyMemSize;
  519. InitThread: nil;
  520. DoneThread: nil;
  521. RelocateHeap: nil;
  522. GetHeapStatus: nil;
  523. GetFPCHeapStatus: nil;
  524. );