heap.inc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team.
  5. functions for heap management in the data segment
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {****************************************************************************}
  13. { Reuse bigger blocks instead of allocating a new block at freelist/heapptr.
  14. the tried bigger blocks are always multiple sizes of the current block }
  15. {$define REUSEBIGGER}
  16. { Allocate small blocks at heapptr instead of walking the freelist }
  17. {$define SMALLATHEAPPTR}
  18. { Try to find the best matching block in general freelist }
  19. {$define BESTMATCH}
  20. { DEBUG: Dump info when the heap needs to grow }
  21. { define DUMPGROW}
  22. { Default heap settings }
  23. const
  24. blocksize = 16; { at least size of freerecord }
  25. blockshr = 4; { shr value for blocksize=2^blockshr}
  26. maxblocksize = 512+blocksize; { 1024+8 needed for heaprecord }
  27. maxblock = maxblocksize div blocksize;
  28. maxreusebigger = 8; { max reuse bigger tries }
  29. usedmask = 1; { flag if the block is used or not }
  30. beforeheapendmask = 2; { flag if the block is just before a heapptr }
  31. sizemask = not(blocksize-1);
  32. {****************************************************************************}
  33. {$ifdef DUMPGROW}
  34. {$define DUMPBLOCKS}
  35. {$endif}
  36. { Memory manager }
  37. const
  38. MemoryManager: TMemoryManager = (
  39. GetMem: SysGetMem;
  40. FreeMem: SysFreeMem;
  41. FreeMemSize: SysFreeMemSize;
  42. AllocMem: SysAllocMem;
  43. ReAllocMem: SysReAllocMem;
  44. MemSize: SysMemSize;
  45. MemAvail: SysMemAvail;
  46. MaxAvail: SysMaxAvail;
  47. HeapSize: SysHeapSize;
  48. );
  49. type
  50. ppfreerecord = ^pfreerecord;
  51. pfreerecord = ^tfreerecord;
  52. tfreerecord = record
  53. size : longint;
  54. next,
  55. prev : pfreerecord;
  56. end; { 12 bytes }
  57. pheaprecord = ^theaprecord;
  58. theaprecord = record
  59. { this should overlap with tfreerecord }
  60. size : longint;
  61. end; { 4 bytes }
  62. tfreelists = array[0..maxblock] of pfreerecord;
  63. pfreelists = ^tfreelists;
  64. var
  65. internal_memavail : longint;
  66. internal_heapsize : longint;
  67. freelists : tfreelists;
  68. {*****************************************************************************
  69. Memory Manager
  70. *****************************************************************************}
  71. procedure GetMemoryManager(var MemMgr:TMemoryManager);
  72. begin
  73. MemMgr:=MemoryManager;
  74. end;
  75. procedure SetMemoryManager(const MemMgr:TMemoryManager);
  76. begin
  77. MemoryManager:=MemMgr;
  78. end;
  79. function IsMemoryManagerSet:Boolean;
  80. begin
  81. IsMemoryManagerSet:=(MemoryManager.GetMem<>@SysGetMem) or
  82. (MemoryManager.FreeMem<>@SysFreeMem);
  83. end;
  84. procedure GetMem(Var p:pointer;Size:Longint);{$ifndef NEWMM}[public,alias:'FPC_GETMEM'];{$endif}
  85. begin
  86. p:=MemoryManager.GetMem(Size);
  87. end;
  88. procedure FreeMem(Var p:pointer;Size:Longint);{$ifndef NEWMM}[public,alias:'FPC_FREEMEM'];{$endif}
  89. begin
  90. MemoryManager.FreeMemSize(p,Size);
  91. p:=nil;
  92. end;
  93. function MaxAvail:Longint;
  94. begin
  95. MaxAvail:=MemoryManager.MaxAvail();
  96. end;
  97. function MemAvail:Longint;
  98. begin
  99. MemAvail:=MemoryManager.MemAvail();
  100. end;
  101. { FPC Additions }
  102. function HeapSize:Longint;
  103. begin
  104. HeapSize:=MemoryManager.HeapSize();
  105. end;
  106. function MemSize(p:pointer):Longint;
  107. begin
  108. MemSize:=MemoryManager.MemSize(p);
  109. end;
  110. { Delphi style }
  111. function FreeMem(var p:pointer):Longint;
  112. begin
  113. Freemem:=MemoryManager.FreeMem(p);
  114. end;
  115. function GetMem(size:longint):pointer;
  116. begin
  117. GetMem:=MemoryManager.GetMem(Size);
  118. end;
  119. function AllocMem(Size:Longint):pointer;
  120. begin
  121. AllocMem:=MemoryManager.AllocMem(size);
  122. end;
  123. function ReAllocMem(var p:pointer;Size:Longint):pointer;
  124. begin
  125. ReAllocMem:=MemoryManager.ReAllocMem(p,size);
  126. end;
  127. { Needed for calls from Assembler }
  128. procedure AsmGetMem(var p:pointer;size:longint);{$ifdef NEWMM}[public,alias:'FPC_GETMEM'];{$endif}
  129. begin
  130. p:=MemoryManager.GetMem(size);
  131. end;
  132. procedure AsmFreeMem(var p:pointer);{$ifdef NEWMM}[public,alias:'FPC_FREEMEM'];{$endif}
  133. begin
  134. if p <> nil then
  135. begin
  136. MemoryManager.FreeMem(p);
  137. p:=nil;
  138. end;
  139. end;
  140. {*****************************************************************************
  141. Heapsize,Memavail,MaxAvail
  142. *****************************************************************************}
  143. function SysHeapsize : longint;
  144. begin
  145. Sysheapsize:=internal_heapsize;
  146. end;
  147. function SysMemavail : longint;
  148. begin
  149. Sysmemavail:=internal_memavail;
  150. end;
  151. function SysMaxavail : longint;
  152. var
  153. hp : pfreerecord;
  154. begin
  155. Sysmaxavail:=heapend-heapptr;
  156. hp:=freelists[0];
  157. while assigned(hp) do
  158. begin
  159. if hp^.size>Sysmaxavail then
  160. Sysmaxavail:=hp^.size;
  161. hp:=hp^.next;
  162. end;
  163. end;
  164. {$ifdef DUMPBLOCKS}
  165. procedure DumpBlocks;
  166. var
  167. s,i,j : longint;
  168. hp : pfreerecord;
  169. begin
  170. for i:=1 to maxblock do
  171. begin
  172. hp:=freelists[i];
  173. j:=0;
  174. while assigned(hp) do
  175. begin
  176. inc(j);
  177. hp:=hp^.next;
  178. end;
  179. writeln('Block ',i*blocksize,': ',j);
  180. end;
  181. { freelist 0 }
  182. hp:=freelists[0];
  183. j:=0;
  184. s:=0;
  185. while assigned(hp) do
  186. begin
  187. inc(j);
  188. if hp^.size>s then
  189. s:=hp^.size;
  190. hp:=hp^.next;
  191. end;
  192. writeln('Main: ',j,' maxsize: ',s);
  193. end;
  194. {$endif}
  195. {*****************************************************************************
  196. SysGetMem
  197. *****************************************************************************}
  198. function SysGetMem(size : longint):pointer;
  199. type
  200. heaperrorproc=function(size:longint):integer;
  201. var
  202. proc : heaperrorproc;
  203. pcurr : pfreerecord;
  204. again : boolean;
  205. s,s1,i,
  206. sizeleft : longint;
  207. {$ifdef BESTMATCH}
  208. pbest : pfreerecord;
  209. {$endif}
  210. begin
  211. { Something to allocate ? }
  212. if size<=0 then
  213. begin
  214. { give an error for < 0 }
  215. if size<0 then
  216. HandleError(204);
  217. { we always need to allocate something, using heapend is not possible,
  218. because heappend can be changed by growheap (PFV) }
  219. size:=1;
  220. end;
  221. { calc to multiply of 16 after adding the needed 8 bytes heaprecord }
  222. size:=(size+sizeof(theaprecord)+(blocksize-1)) and (not (blocksize-1));
  223. dec(internal_memavail,size);
  224. { try to find a block in one of the freelists per size }
  225. s:=size shr blockshr;
  226. if s<=maxblock then
  227. begin
  228. pcurr:=freelists[s];
  229. { correct size match ? }
  230. if assigned(pcurr) then
  231. begin
  232. { create the block we should return }
  233. sysgetmem:=pointer(pcurr)+sizeof(theaprecord);
  234. { fix size }
  235. pcurr^.size:=pcurr^.size or usedmask;
  236. { update freelist }
  237. freelists[s]:=pcurr^.next;
  238. if assigned(freelists[s]) then
  239. freelists[s]^.prev:=nil;
  240. exit;
  241. end;
  242. {$ifdef SMALLATHEAPPTR}
  243. if heapend-heapptr>size then
  244. begin
  245. sysgetmem:=heapptr;
  246. if (heapptr+size=heapend) then
  247. pheaprecord(sysgetmem)^.size:=size or (usedmask or beforeheapendmask)
  248. else
  249. pheaprecord(sysgetmem)^.size:=size or usedmask;
  250. inc(sysgetmem,sizeof(theaprecord));
  251. inc(heapptr,size);
  252. exit;
  253. end;
  254. {$endif}
  255. {$ifdef REUSEBIGGER}
  256. { try a bigger block }
  257. s1:=s+s;
  258. i:=0;
  259. while (s1<=maxblock) and (i<maxreusebigger) do
  260. begin
  261. pcurr:=freelists[s1];
  262. if assigned(pcurr) then
  263. begin
  264. s:=s1;
  265. break;
  266. end;
  267. inc(s1);
  268. inc(i);
  269. end;
  270. {$endif}
  271. end
  272. else
  273. pcurr:=nil;
  274. { not found, then check the main freelist for the first match }
  275. if not(assigned(pcurr)) then
  276. begin
  277. s:=0;
  278. {$ifdef BESTMATCH}
  279. pbest:=nil;
  280. {$endif}
  281. pcurr:=freelists[0];
  282. while assigned(pcurr) do
  283. begin
  284. {$ifdef BESTMATCH}
  285. if pcurr^.size=size then
  286. break
  287. else
  288. begin
  289. if (pcurr^.size>size) then
  290. begin
  291. if (not assigned(pbest)) or
  292. (pcurr^.size<pbest^.size) then
  293. pbest:=pcurr;
  294. end;
  295. end;
  296. {$else}
  297. if pcurr^.size>=size then
  298. break;
  299. {$endif}
  300. pcurr:=pcurr^.next;
  301. end;
  302. {$ifdef BESTMATCH}
  303. if not assigned(pcurr) then
  304. pcurr:=pbest;
  305. {$endif}
  306. end;
  307. { have we found a block, then get it and free up the other left part,
  308. if no blocks are found then allocated at the heapptr or grow the heap }
  309. if assigned(pcurr) then
  310. begin
  311. { get pointer of the block we should return }
  312. sysgetmem:=pointer(pcurr);
  313. { remove the current block from the freelist }
  314. if assigned(pcurr^.next) then
  315. pcurr^.next^.prev:=pcurr^.prev;
  316. if assigned(pcurr^.prev) then
  317. pcurr^.prev^.next:=pcurr^.next
  318. else
  319. freelists[s]:=pcurr^.next;
  320. { create the left over freelist block, if at least 16 bytes are free }
  321. sizeleft:=pcurr^.size-size;
  322. if sizeleft>sizeof(tfreerecord) then
  323. begin
  324. pcurr:=pfreerecord(pointer(pcurr)+size);
  325. { inherit the beforeheapendmask }
  326. pcurr^.size:=sizeleft or (pheaprecord(sysgetmem)^.size and beforeheapendmask);
  327. { insert the block in the freelist }
  328. pcurr^.prev:=nil;
  329. s1:=sizeleft shr blockshr;
  330. if s1>maxblock then
  331. s1:=0;
  332. pcurr^.next:=freelists[s1];
  333. if assigned(freelists[s1]) then
  334. freelists[s1]^.prev:=pcurr;
  335. freelists[s1]:=pcurr;
  336. { create the block we need to return }
  337. pheaprecord(sysgetmem)^.size:=size or usedmask;
  338. end
  339. else
  340. begin
  341. { create the block we need to return }
  342. pheaprecord(sysgetmem)^.size:=size or usedmask or (pheaprecord(sysgetmem)^.size and beforeheapendmask);
  343. end;
  344. inc(sysgetmem,sizeof(theaprecord));
  345. exit;
  346. end;
  347. { Lastly, the top of the heap is checked, to see if there is }
  348. { still memory available. }
  349. repeat
  350. again:=false;
  351. if heapend-heapptr>size then
  352. begin
  353. sysgetmem:=heapptr;
  354. if (heapptr+size=heapend) then
  355. pheaprecord(sysgetmem)^.size:=size or (usedmask or beforeheapendmask)
  356. else
  357. pheaprecord(sysgetmem)^.size:=size or usedmask;
  358. inc(sysgetmem,sizeof(theaprecord));
  359. inc(heapptr,size);
  360. exit;
  361. end;
  362. { Call the heaperror proc }
  363. if assigned(heaperror) then
  364. begin
  365. proc:=heaperrorproc(heaperror);
  366. case proc(size) of
  367. 0 : HandleError(203);
  368. 1 : sysgetmem:=nil;
  369. 2 : again:=true;
  370. end;
  371. end
  372. else
  373. HandleError(203);
  374. until not again;
  375. end;
  376. {*****************************************************************************
  377. SysFreeMem
  378. *****************************************************************************}
  379. Function SysFreeMem(var p : pointer):Longint;
  380. var
  381. pcurrsize,s : longint;
  382. pcurr : pfreerecord;
  383. begin
  384. if p=nil then
  385. HandleError(204);
  386. { fix p to point to the heaprecord }
  387. pcurr:=pfreerecord(pointer(p)-sizeof(theaprecord));
  388. pcurrsize:=pcurr^.size and sizemask;
  389. inc(internal_memavail,pcurrsize);
  390. { insert the block in it's freelist }
  391. pcurr^.size:=pcurr^.size and (not usedmask);
  392. pcurr^.prev:=nil;
  393. s:=pcurrsize shr blockshr;
  394. if s>maxblock then
  395. s:=0;
  396. pcurr^.next:=freelists[s];
  397. if assigned(pcurr^.next) then
  398. pcurr^.next^.prev:=pcurr;
  399. freelists[s]:=pcurr;
  400. p:=nil;
  401. SysFreeMem:=pcurrsize;
  402. end;
  403. {*****************************************************************************
  404. SysFreeMemSize
  405. *****************************************************************************}
  406. Function SysFreeMemSize(var p : pointer;size : longint):longint;
  407. var
  408. pcurrsize,s : longint;
  409. pcurr : pfreerecord;
  410. begin
  411. SysFreeMemSize:=0;
  412. if size<=0 then
  413. begin
  414. if size<0 then
  415. HandleError(204);
  416. p:=nil;
  417. exit;
  418. end;
  419. if p=nil then
  420. HandleError(204);
  421. { fix p to point to the heaprecord }
  422. pcurr:=pfreerecord(pointer(p)-sizeof(theaprecord));
  423. pcurrsize:=pcurr^.size and sizemask;
  424. inc(internal_memavail,pcurrsize);
  425. { size check }
  426. size:=(size+sizeof(theaprecord)+(blocksize-1)) and (not (blocksize-1));
  427. if size<>pcurrsize then
  428. HandleError(204);
  429. { insert the block in it's freelist }
  430. pcurr^.size:=pcurr^.size and (not usedmask);
  431. pcurr^.prev:=nil;
  432. s:=pcurrsize shr blockshr;
  433. if s>maxblock then
  434. s:=0;
  435. pcurr^.next:=freelists[s];
  436. if assigned(pcurr^.next) then
  437. pcurr^.next^.prev:=pcurr;
  438. freelists[s]:=pcurr;
  439. p:=nil;
  440. SysFreeMemSize:=pcurrsize;
  441. end;
  442. {*****************************************************************************
  443. SysMemSize
  444. *****************************************************************************}
  445. function SysMemSize(p:pointer):longint;
  446. begin
  447. SysMemSize:=(pheaprecord(pointer(p)-sizeof(theaprecord))^.size and sizemask)-sizeof(theaprecord);
  448. end;
  449. {*****************************************************************************
  450. SysAllocMem
  451. *****************************************************************************}
  452. function SysAllocMem(size : longint):pointer;
  453. begin
  454. sysallocmem:=MemoryManager.GetMem(size);
  455. if sysallocmem<>nil then
  456. FillChar(sysallocmem^,size,0);
  457. end;
  458. {*****************************************************************************
  459. SysReAllocMem
  460. *****************************************************************************}
  461. function SysReAllocMem(var p:pointer;size : longint):pointer;
  462. var
  463. orgsize,
  464. currsize,
  465. foundsize,
  466. sizeleft,
  467. s : longint;
  468. wasbeforeheapend : boolean;
  469. p2 : pointer;
  470. hp,
  471. pnew,
  472. pcurr : pfreerecord;
  473. begin
  474. { Allocate a new block? }
  475. if p=nil then
  476. begin
  477. p:=MemoryManager.GetMem(size);
  478. SysReallocmem:=P;
  479. exit;
  480. end;
  481. { fix needed size }
  482. orgsize:=size;
  483. size:=(size+sizeof(theaprecord)+(blocksize-1)) and (not (blocksize-1));
  484. { fix p to point to the heaprecord }
  485. pcurr:=pfreerecord(pointer(p)-sizeof(theaprecord));
  486. currsize:=pcurr^.size and sizemask;
  487. wasbeforeheapend:=(pcurr^.size and beforeheapendmask)<>0;
  488. { is the allocated block still correct? }
  489. if currsize=size then
  490. begin
  491. SysReAllocMem:=p;
  492. exit;
  493. end;
  494. { do we need to allocate more memory ? }
  495. if size>currsize then
  496. begin
  497. { the size is bigger than the previous size, we need to allocated more mem.
  498. We first check if the blocks after the current block are free. If not we
  499. simply call getmem/freemem to get the new block }
  500. foundsize:=0;
  501. hp:=pcurr;
  502. repeat
  503. inc(foundsize,hp^.size and sizemask);
  504. { block used or before a heapptr ? }
  505. if (hp^.size and beforeheapendmask)<>0 then
  506. begin
  507. wasbeforeheapend:=true;
  508. break;
  509. end;
  510. { get next block }
  511. hp:=pfreerecord(pointer(hp)+(hp^.size and sizemask));
  512. { when we're at heapptr then we can stop }
  513. if (hp=heapptr) then
  514. begin
  515. inc(foundsize,heapend-heapptr);
  516. break;
  517. end;
  518. if (hp^.size and usedmask)<>0 then
  519. break;
  520. until (foundsize>=size);
  521. { found enough free blocks? }
  522. if foundsize>=size then
  523. begin
  524. { we walk the list again and remove all blocks }
  525. foundsize:=pcurr^.size and sizemask;
  526. hp:=pcurr;
  527. repeat
  528. { get next block }
  529. hp:=pfreerecord(pointer(hp)+(hp^.size and sizemask));
  530. { when we're at heapptr then we can increase it, if there is enough
  531. room is already checked }
  532. if (hp=heapptr) then
  533. begin
  534. inc(heapptr,size-foundsize);
  535. foundsize:=size;
  536. break;
  537. end;
  538. s:=hp^.size and sizemask;
  539. inc(foundsize,s);
  540. { remove block from freelist }
  541. s:=s shr blockshr;
  542. if s>maxblock then
  543. s:=0;
  544. if assigned(hp^.next) then
  545. hp^.next^.prev:=hp^.prev;
  546. if assigned(hp^.prev) then
  547. hp^.prev^.next:=hp^.next
  548. else
  549. freelists[s]:=hp^.next;
  550. until (foundsize>=size);
  551. if wasbeforeheapend then
  552. pcurr^.size:=foundsize or usedmask or beforeheapendmask
  553. else
  554. pcurr^.size:=foundsize or usedmask;
  555. end
  556. else
  557. begin
  558. { we need to call getmem/move/freemem }
  559. p2:=MemoryManager.GetMem(orgsize);
  560. if p2<>nil then
  561. Move(p^,p2^,orgsize);
  562. MemoryManager.Freemem(p);
  563. p:=p2;
  564. SysReAllocMem:=p;
  565. exit;
  566. end;
  567. currsize:=pcurr^.size and sizemask;
  568. end;
  569. { is the size smaller then we can adjust the block to that size and insert
  570. the other part into the freelist }
  571. if size<currsize then
  572. begin
  573. { create the left over freelist block, if at least 16 bytes are free }
  574. sizeleft:=currsize-size;
  575. if sizeleft>sizeof(tfreerecord) then
  576. begin
  577. pnew:=pfreerecord(pointer(pcurr)+size);
  578. pnew^.size:=sizeleft or (pcurr^.size and beforeheapendmask);
  579. { insert the block in the freelist }
  580. pnew^.prev:=nil;
  581. s:=sizeleft shr blockshr;
  582. if s>maxblock then
  583. s:=0;
  584. pnew^.next:=freelists[s];
  585. if assigned(freelists[s]) then
  586. freelists[s]^.prev:=pnew;
  587. freelists[s]:=pnew;
  588. { fix the size of the current block and leave }
  589. pcurr^.size:=size or usedmask;
  590. end
  591. else
  592. begin
  593. { fix the size of the current block and leave }
  594. pcurr^.size:=size or usedmask or (pcurr^.size and beforeheapendmask);
  595. end;
  596. end;
  597. SysReAllocMem:=p;
  598. end;
  599. {*****************************************************************************
  600. Mark/Release
  601. *****************************************************************************}
  602. procedure release(var p : pointer);
  603. begin
  604. end;
  605. procedure mark(var p : pointer);
  606. begin
  607. end;
  608. {*****************************************************************************
  609. Grow Heap
  610. *****************************************************************************}
  611. function growheap(size :longint) : integer;
  612. var
  613. sizeleft,
  614. NewPos : longint;
  615. pcurr : pfreerecord;
  616. begin
  617. {$ifdef DUMPGROW}
  618. writeln('grow ',size);
  619. DumpBlocks;
  620. {$endif}
  621. { Allocate by 64K size }
  622. size:=(size+$ffff) and $ffff0000;
  623. { first try 256K (default) }
  624. if size<=GrowHeapSize1 then
  625. begin
  626. NewPos:=Sbrk(GrowHeapSize1);
  627. if NewPos>0 then
  628. size:=GrowHeapSize1;
  629. end
  630. else
  631. { second try 1024K (default) }
  632. if size<=GrowHeapSize2 then
  633. begin
  634. NewPos:=Sbrk(GrowHeapSize2);
  635. if NewPos>0 then
  636. size:=GrowHeapSize2;
  637. end
  638. { else alloate the needed bytes }
  639. else
  640. NewPos:=SBrk(size);
  641. { try again }
  642. if NewPos=-1 then
  643. begin
  644. NewPos:=Sbrk(size);
  645. if NewPos=-1 then
  646. begin
  647. GrowHeap:=0;
  648. Exit;
  649. end;
  650. end;
  651. { increase heapend or add to freelist }
  652. if heapend=pointer(newpos) then
  653. begin
  654. heapend:=pointer(newpos+size);
  655. end
  656. else
  657. begin
  658. { create freelist entry for old heapptr-heapend }
  659. sizeleft:=heapend-heapptr;
  660. if sizeleft>sizeof(tfreerecord) then
  661. begin
  662. pcurr:=pfreerecord(heapptr);
  663. pcurr^.size:=sizeleft or beforeheapendmask;
  664. { insert the block in the freelist }
  665. pcurr^.next:=freelists[0];
  666. pcurr^.prev:=nil;
  667. if assigned(freelists[0]) then
  668. freelists[0]^.prev:=pcurr;
  669. freelists[0]:=pcurr;
  670. end;
  671. { now set the new heapptr,heapend to the new block }
  672. heapptr:=pointer(newpos);
  673. heapend:=pointer(newpos+size);
  674. end;
  675. { set the total new heap size }
  676. inc(internal_memavail,size);
  677. inc(internal_heapsize,size);
  678. { try again }
  679. GrowHeap:=2;
  680. end;
  681. {*****************************************************************************
  682. InitHeap
  683. *****************************************************************************}
  684. { This function will initialize the Heap manager and need to be called from
  685. the initialization of the system unit }
  686. procedure InitHeap;
  687. begin
  688. FillChar(FreeLists,sizeof(TFreeLists),0);
  689. internal_heapsize:=GetHeapSize;
  690. internal_memavail:=internal_heapsize;
  691. HeapOrg:=GetHeapStart;
  692. HeapPtr:=HeapOrg;
  693. HeapEnd:=HeapOrg+internal_memavail;
  694. HeapError:=@GrowHeap;
  695. end;
  696. {
  697. $Log$
  698. Revision 1.29 2000-01-07 16:41:34 daniel
  699. * copyright 2000
  700. Revision 1.28 2000/01/07 16:32:24 daniel
  701. * copyright 2000 added
  702. Revision 1.27 1999/12/16 19:11:49 peter
  703. * fixed sysmemsize which did the and sizemask wrong
  704. Revision 1.26 1999/12/13 21:04:46 peter
  705. * fixed getmem call with wrong size from reallocmem
  706. Revision 1.25 1999/12/01 22:57:31 peter
  707. * cmdline support
  708. Revision 1.24 1999/11/14 21:34:21 peter
  709. * fixed reallocmem with a block at the end of an allocated memoryblock,
  710. had to introduce a flag for such blocks.
  711. * flags are now stored in the first 4 bits instead of the highest bit,
  712. this could be done because the sizes of block are always >= 16
  713. Revision 1.23 1999/11/10 22:29:51 michael
  714. + Fixed sysreallocmem
  715. Revision 1.22 1999/11/01 13:56:50 peter
  716. * freemem,reallocmem now get var argument
  717. Revision 1.21 1999/10/30 17:39:05 peter
  718. * memorymanager expanded with allocmem/reallocmem
  719. Revision 1.20 1999/10/22 22:03:07 sg
  720. * FreeMem(p) is ignored if p is NIL, instead of throwing an
  721. runtime error 204. (Delphi ignores NIL FreeMem's, too)
  722. Revision 1.19 1999/10/01 07:55:54 peter
  723. * fixed memsize which forgot the sizemask
  724. Revision 1.18 1999/09/22 21:59:02 peter
  725. * best match for main freelist
  726. * removed root field, saves 4 bytes per block
  727. * fixed crash in dumpblocks
  728. Revision 1.17 1999/09/20 14:17:37 peter
  729. * fixed growheap freelist addition when heapend-heapptr<blocksize
  730. Revision 1.16 1999/09/17 17:14:12 peter
  731. + new heap manager supporting delphi freemem(pointer)
  732. }