heap.inc 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418
  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. { Try to find the best matching block in general freelist }
  14. { define BESTMATCH}
  15. { DEBUG: Dump info when the heap needs to grow }
  16. { define DUMPGROW}
  17. { DEBUG: Test the FreeList on correctness }
  18. {$ifdef SYSTEMDEBUG}
  19. {$define TestFreeLists}
  20. {$endif SYSTEMDEBUG}
  21. const
  22. {$ifdef CPU64}
  23. blocksize = 32; { at least size of freerecord }
  24. blockshr = 5; { shr value for blocksize=2^blockshr}
  25. maxblocksize = 512+blocksize; { 1024+8 needed for heaprecord }
  26. {$else}
  27. blocksize = 16; { at least size of freerecord }
  28. blockshr = 4; { shr value for blocksize=2^blockshr}
  29. maxblocksize = 512+blocksize; { 1024+8 needed for heaprecord }
  30. {$endif}
  31. maxblockindex = maxblocksize div blocksize; { highest index in array of lists of memchunks }
  32. maxreusebigger = 8; { max reuse bigger tries }
  33. usedflag = 1; { flag if the block is used or not }
  34. lastblockflag = 2; { flag if the block is the last in os chunk }
  35. firstblockflag = 4; { flag if the block is the first in os chunk }
  36. fixedsizeflag = 8; { flag if the block is of fixed size }
  37. sizemask = not(blocksize-1);
  38. fixedsizemask = sizemask and $ffff;
  39. {****************************************************************************}
  40. {$ifdef DUMPGROW}
  41. {$define DUMPBLOCKS}
  42. {$endif}
  43. { Forward defines }
  44. procedure SysHeapMutexInit;forward;
  45. procedure SysHeapMutexDone;forward;
  46. procedure SysHeapMutexLock;forward;
  47. procedure SysHeapMutexUnlock;forward;
  48. { Memory manager }
  49. const
  50. MemoryManager: TMemoryManager = (
  51. NeedLock: true;
  52. GetMem: @SysGetMem;
  53. FreeMem: @SysFreeMem;
  54. FreeMemSize: @SysFreeMemSize;
  55. AllocMem: @SysAllocMem;
  56. ReAllocMem: @SysReAllocMem;
  57. MemSize: @SysMemSize;
  58. GetHeapStatus: @SysGetHeapStatus;
  59. {$ifdef HASGETFPCHEAPSTATUS}
  60. GetFPCHeapStatus: @SysGetFPCHeapStatus;
  61. {$endif HASGETFPCHEAPSTATUS}
  62. );
  63. MemoryMutexManager: TMemoryMutexManager = (
  64. MutexInit: @SysHeapMutexInit;
  65. MutexDone: @SysHeapMutexDone;
  66. MutexLock: @SysHeapMutexLock;
  67. MutexUnlock: @SysHeapMutexUnlock;
  68. );
  69. type
  70. pmemchunk_fixed = ^tmemchunk_fixed;
  71. tmemchunk_fixed = record
  72. {$ifdef cpusparc}
  73. { Sparc needs to alloc aligned on 8 bytes, to allow doubles }
  74. _dummy : ptrint;
  75. {$endif cpusparc}
  76. size : ptrint;
  77. next_fixed,
  78. prev_fixed : pmemchunk_fixed;
  79. end;
  80. pmemchunk_var = ^tmemchunk_var;
  81. tmemchunk_var = record
  82. prevsize : ptrint;
  83. size : ptrint;
  84. next_var,
  85. prev_var : pmemchunk_var;
  86. end;
  87. { ``header'', ie. size of structure valid when chunk is in use }
  88. { should correspond to tmemchunk_var_hdr structure starting with the
  89. last field. Reason is that the overlap is starting from the end of the
  90. record. }
  91. tmemchunk_fixed_hdr = record
  92. {$ifdef cpusparc}
  93. { Sparc needs to alloc aligned on 8 bytes, to allow doubles }
  94. _dummy : ptrint;
  95. {$endif cpusparc}
  96. size : ptrint;
  97. end;
  98. tmemchunk_var_hdr = record
  99. prevsize : ptrint;
  100. size : ptrint;
  101. end;
  102. poschunk = ^toschunk;
  103. toschunk = record
  104. size : ptrint;
  105. next,
  106. prev : poschunk;
  107. used : ptrint;
  108. end;
  109. tfreelists = array[1..maxblockindex] of pmemchunk_fixed;
  110. pfreelists = ^tfreelists;
  111. var
  112. {$ifdef HASGETFPCHEAPSTATUS}
  113. internal_status : TFPCHeapStatus;
  114. {$else HASGETFPCHEAPSTATUS}
  115. internal_status : THeapStatus;
  116. {$endif HASGETFPCHEAPSTATUS}
  117. freelists_fixed : tfreelists;
  118. freelist_var : pmemchunk_var;
  119. freeoslist : poschunk;
  120. freeoslistcount : dword;
  121. {$ifdef TestFreeLists}
  122. { this can be turned on by debugger }
  123. const
  124. test_each : boolean = false;
  125. {$endif TestFreeLists}
  126. {*****************************************************************************
  127. Memory Manager
  128. *****************************************************************************}
  129. procedure SetMemoryMutexManager(var MutexMgr: TMemoryMutexManager);
  130. begin
  131. { Release old mutexmanager, the default manager does nothing so
  132. calling this without initializing is safe }
  133. MemoryMutexManager.MutexDone;
  134. { Copy new mutexmanager }
  135. MemoryMutexManager := MutexMgr;
  136. { Init new mutexmanager }
  137. MemoryMutexManager.MutexInit;
  138. end;
  139. procedure GetMemoryManager(var MemMgr:TMemoryManager);
  140. begin
  141. if IsMultiThread and MemoryManager.NeedLock then
  142. begin
  143. try
  144. MemoryMutexManager.MutexLock;
  145. MemMgr := MemoryManager;
  146. finally
  147. MemoryMutexManager.MutexUnlock;
  148. end;
  149. end
  150. else
  151. begin
  152. MemMgr := MemoryManager;
  153. end;
  154. end;
  155. procedure SetMemoryManager(const MemMgr:TMemoryManager);
  156. begin
  157. if IsMultiThread and MemoryManager.NeedLock then
  158. begin
  159. try
  160. MemoryMutexManager.MutexLock;
  161. MemoryManager := MemMgr;
  162. finally
  163. MemoryMutexManager.MutexUnlock;
  164. end;
  165. end
  166. else
  167. begin
  168. MemoryManager := MemMgr;
  169. end;
  170. end;
  171. function IsMemoryManagerSet:Boolean;
  172. begin
  173. if IsMultiThread and MemoryManager.NeedLock then
  174. begin
  175. try
  176. MemoryMutexManager.MutexLock;
  177. IsMemoryManagerSet := (MemoryManager.GetMem<>@SysGetMem) or
  178. (MemoryManager.FreeMem<>@SysFreeMem);
  179. finally
  180. MemoryMutexManager.MutexUnlock;
  181. end;
  182. end
  183. else
  184. begin
  185. IsMemoryManagerSet := (MemoryManager.GetMem<>@SysGetMem) or
  186. (MemoryManager.FreeMem<>@SysFreeMem);
  187. end;
  188. end;
  189. procedure GetMem(Var p:pointer;Size:ptrint);
  190. begin
  191. if IsMultiThread and MemoryManager.NeedLock then
  192. begin
  193. try
  194. MemoryMutexManager.MutexLock;
  195. p := MemoryManager.GetMem(Size);
  196. finally
  197. MemoryMutexManager.MutexUnlock;
  198. end;
  199. end
  200. else
  201. begin
  202. p := MemoryManager.GetMem(Size);
  203. end;
  204. end;
  205. procedure GetMemory(Var p:pointer;Size:ptrint);
  206. begin
  207. GetMem(p,size);
  208. end;
  209. procedure FreeMem(p:pointer;Size:ptrint);
  210. begin
  211. if IsMultiThread and MemoryManager.NeedLock then
  212. begin
  213. try
  214. MemoryMutexManager.MutexLock;
  215. MemoryManager.FreeMemSize(p,Size);
  216. finally
  217. MemoryMutexManager.MutexUnlock;
  218. end;
  219. end
  220. else
  221. begin
  222. MemoryManager.FreeMemSize(p,Size);
  223. end;
  224. end;
  225. procedure FreeMemory(p:pointer;Size:ptrint);
  226. begin
  227. FreeMem(p,size);
  228. end;
  229. {$ifdef HASGETFPCHEAPSTATUS}
  230. function GetHeapStatus:THeapStatus;
  231. begin
  232. if IsMultiThread and MemoryManager.NeedLock then
  233. begin
  234. try
  235. MemoryMutexManager.MutexLock;
  236. result:=MemoryManager.GetHeapStatus();
  237. finally
  238. MemoryMutexManager.MutexUnlock;
  239. end;
  240. end
  241. else
  242. begin
  243. result:=MemoryManager.GetHeapStatus();
  244. end;
  245. end;
  246. function GetFPCHeapStatus:TFPCHeapStatus;
  247. begin
  248. if IsMultiThread and MemoryManager.NeedLock then
  249. begin
  250. try
  251. MemoryMutexManager.MutexLock;
  252. result:=MemoryManager.GetFPCHeapStatus();
  253. finally
  254. MemoryMutexManager.MutexUnlock;
  255. end;
  256. end
  257. else
  258. begin
  259. Result:=MemoryManager.GetFPCHeapStatus();
  260. end;
  261. end;
  262. {$else HASGETFPCHEAPSTATUS}
  263. procedure GetHeapStatus(var status:THeapStatus);
  264. begin
  265. if IsMultiThread and MemoryManager.NeedLock then
  266. begin
  267. try
  268. MemoryMutexManager.MutexLock;
  269. MemoryManager.GetHeapStatus(status);
  270. finally
  271. MemoryMutexManager.MutexUnlock;
  272. end;
  273. end
  274. else
  275. begin
  276. MemoryManager.GetHeapStatus(status);
  277. end;
  278. end;
  279. {$endif HASGETFPCHEAPSTATUS}
  280. function MemSize(p:pointer):ptrint;
  281. begin
  282. if IsMultiThread and MemoryManager.NeedLock then
  283. begin
  284. try
  285. MemoryMutexManager.MutexLock;
  286. MemSize := MemoryManager.MemSize(p);
  287. finally
  288. MemoryMutexManager.MutexUnlock;
  289. end;
  290. end
  291. else
  292. begin
  293. MemSize := MemoryManager.MemSize(p);
  294. end;
  295. end;
  296. { Delphi style }
  297. function FreeMem(p:pointer):ptrint;
  298. begin
  299. if IsMultiThread and MemoryManager.NeedLock then
  300. begin
  301. try
  302. MemoryMutexManager.MutexLock;
  303. Freemem := MemoryManager.FreeMem(p);
  304. finally
  305. MemoryMutexManager.MutexUnlock;
  306. end;
  307. end
  308. else
  309. begin
  310. Freemem := MemoryManager.FreeMem(p);
  311. end;
  312. end;
  313. function FreeMemory(p:pointer):ptrint;
  314. begin
  315. FreeMemory := FreeMem(p);
  316. end;
  317. function GetMem(size:ptrint):pointer;
  318. begin
  319. if IsMultiThread and MemoryManager.NeedLock then
  320. begin
  321. try
  322. MemoryMutexManager.MutexLock;
  323. GetMem := MemoryManager.GetMem(Size);
  324. finally
  325. MemoryMutexManager.MutexUnlock;
  326. end;
  327. end
  328. else
  329. begin
  330. GetMem := MemoryManager.GetMem(Size);
  331. end;
  332. end;
  333. function GetMemory(size:ptrint):pointer;
  334. begin
  335. GetMemory := Getmem(size);
  336. end;
  337. function AllocMem(Size:ptrint):pointer;
  338. begin
  339. if IsMultiThread and MemoryManager.NeedLock then
  340. begin
  341. try
  342. MemoryMutexManager.MutexLock;
  343. AllocMem := MemoryManager.AllocMem(size);
  344. finally
  345. MemoryMutexManager.MutexUnlock;
  346. end;
  347. end
  348. else
  349. begin
  350. AllocMem := MemoryManager.AllocMem(size);
  351. end;
  352. end;
  353. function ReAllocMem(var p:pointer;Size:ptrint):pointer;
  354. begin
  355. if IsMultiThread and MemoryManager.NeedLock then
  356. begin
  357. try
  358. MemoryMutexManager.MutexLock;
  359. ReAllocMem := MemoryManager.ReAllocMem(p,size);
  360. finally
  361. MemoryMutexManager.MutexUnlock;
  362. end;
  363. end
  364. else
  365. begin
  366. ReAllocMem := MemoryManager.ReAllocMem(p,size);
  367. end;
  368. end;
  369. function ReAllocMemory(var p:pointer;Size:ptrint):pointer;
  370. begin
  371. ReAllocMemory := ReAllocMem(p,size);
  372. end;
  373. {$ifdef ValueGetmem}
  374. { Needed for calls from Assembler }
  375. function fpc_getmem(size:ptrint):pointer;compilerproc;[public,alias:'FPC_GETMEM'];
  376. begin
  377. if IsMultiThread and MemoryManager.NeedLock then
  378. begin
  379. try
  380. MemoryMutexManager.MutexLock;
  381. fpc_GetMem := MemoryManager.GetMem(size);
  382. finally
  383. MemoryMutexManager.MutexUnlock;
  384. end;
  385. end
  386. else
  387. begin
  388. fpc_GetMem := MemoryManager.GetMem(size);
  389. end;
  390. end;
  391. {$else ValueGetmem}
  392. { Needed for calls from Assembler }
  393. procedure AsmGetMem(var p:pointer;size:ptrint);[public,alias:'FPC_GETMEM'];
  394. begin
  395. p := MemoryManager.GetMem(size);
  396. end;
  397. {$endif ValueGetmem}
  398. {$ifdef ValueFreemem}
  399. procedure fpc_freemem(p:pointer);compilerproc;[public,alias:'FPC_FREEMEM'];
  400. begin
  401. if IsMultiThread and MemoryManager.NeedLock then
  402. begin
  403. try
  404. MemoryMutexManager.MutexLock;
  405. if p <> nil then
  406. MemoryManager.FreeMem(p);
  407. finally
  408. MemoryMutexManager.MutexUnlock;
  409. end;
  410. end
  411. else
  412. begin
  413. if p <> nil then
  414. MemoryManager.FreeMem(p);
  415. end;
  416. end;
  417. {$else ValueFreemem}
  418. procedure AsmFreeMem(var p:pointer);[public,alias:'FPC_FREEMEM'];
  419. begin
  420. if p <> nil then
  421. MemoryManager.FreeMem(p);
  422. end;
  423. {$endif ValueFreemem}
  424. { Bootstrapping }
  425. {$ifndef HASGETHEAPSTATUS}
  426. Function Memavail:ptrint;
  427. begin
  428. result:=0;
  429. end;
  430. Function Maxavail:ptrint;
  431. begin
  432. result:=0;
  433. end;
  434. Function Heapsize:ptrint;
  435. begin
  436. result:=0;
  437. end;
  438. {$endif HASGETHEAPSTATUS}
  439. {*****************************************************************************
  440. GetHeapStatus
  441. *****************************************************************************}
  442. {$ifdef HASGETFPCHEAPSTATUS}
  443. function SysGetFPCHeapStatus:TFPCHeapStatus;
  444. begin
  445. internal_status.CurrHeapFree:=internal_status.CurrHeapSize-internal_status.CurrHeapUsed;
  446. result:=internal_status;
  447. end;
  448. function SysGetHeapStatus :THeapStatus;
  449. begin
  450. internal_status.CurrHeapFree:=internal_status.CurrHeapSize-internal_status.CurrHeapUsed;
  451. result.TotalAllocated :=internal_status.CurrHeapUsed;
  452. result.TotalFree :=internal_status.CurrHeapFree;
  453. result.TotalAddrSpace :=0;
  454. result.TotalUncommitted :=0;
  455. result.TotalCommitted :=0;
  456. result.FreeSmall :=0;
  457. result.FreeBig :=0;
  458. result.Unused :=0;
  459. result.Overhead :=0;
  460. result.HeapErrorCode :=0;
  461. end;
  462. {$else}
  463. procedure SysGetHeapStatus(var status:THeapStatus);
  464. begin
  465. internal_status.CurrHeapFree:=internal_status.CurrHeapSize-internal_status.CurrHeapUsed;
  466. status:=internal_status;
  467. end;
  468. {$endif HASGETFPCHEAPSTATUS}
  469. {$ifdef DUMPBLOCKS} // TODO
  470. procedure DumpBlocks;
  471. var
  472. s,i,j : ptrint;
  473. hp : pfreerecord;
  474. begin
  475. for i := 1 to maxblock do
  476. begin
  477. hp := freelists[i];
  478. j := 0;
  479. while assigned(hp) do
  480. begin
  481. inc(j);
  482. hp := hp^.next;
  483. end;
  484. writeln('Block ',i*blocksize,': ',j);
  485. end;
  486. { freelist 0 }
  487. hp := freelists[0];
  488. j := 0;
  489. s := 0;
  490. while assigned(hp) do
  491. begin
  492. inc(j);
  493. if hp^.size>s then
  494. s := hp^.size;
  495. hp := hp^.next;
  496. end;
  497. writeln('Main: ',j,' maxsize: ',s);
  498. end;
  499. {$endif}
  500. {$ifdef TestFreeLists}
  501. procedure TestFreeLists;
  502. var
  503. i,j : ptrint;
  504. mc : pmemchunk_fixed;
  505. begin
  506. for i := 1 to maxblockindex do
  507. begin
  508. j := 0;
  509. mc := freelists_fixed[i];
  510. while assigned(mc) do
  511. begin
  512. inc(j);
  513. if ((mc^.size and fixedsizemask) <> i * blocksize) then
  514. RunError(204);
  515. mc := mc^.next_fixed;
  516. end;
  517. end;
  518. end;
  519. {$endif TestFreeLists}
  520. {*****************************************************************************
  521. List adding/removal
  522. *****************************************************************************}
  523. procedure append_to_list_fixed(blockindex: ptrint; pmc: pmemchunk_fixed);
  524. begin
  525. pmc^.prev_fixed := nil;
  526. pmc^.next_fixed := freelists_fixed[blockindex];
  527. if freelists_fixed[blockindex]<>nil then
  528. freelists_fixed[blockindex]^.prev_fixed := pmc;
  529. freelists_fixed[blockindex] := pmc;
  530. end;
  531. procedure append_to_list_var(pmc: pmemchunk_var);
  532. begin
  533. pmc^.prev_var := nil;
  534. pmc^.next_var := freelist_var;
  535. if freelist_var<>nil then
  536. freelist_var^.prev_var := pmc;
  537. freelist_var := pmc;
  538. end;
  539. procedure remove_from_list_fixed(blockindex: ptrint; pmc: pmemchunk_fixed);
  540. begin
  541. if assigned(pmc^.next_fixed) then
  542. pmc^.next_fixed^.prev_fixed := pmc^.prev_fixed;
  543. if assigned(pmc^.prev_fixed) then
  544. pmc^.prev_fixed^.next_fixed := pmc^.next_fixed
  545. else
  546. freelists_fixed[blockindex] := pmc^.next_fixed;
  547. end;
  548. procedure remove_from_list_var(pmc: pmemchunk_var);
  549. begin
  550. if assigned(pmc^.next_var) then
  551. pmc^.next_var^.prev_var := pmc^.prev_var;
  552. if assigned(pmc^.prev_var) then
  553. pmc^.prev_var^.next_var := pmc^.next_var
  554. else
  555. freelist_var := pmc^.next_var;
  556. end;
  557. procedure append_to_oslist(poc: poschunk);
  558. begin
  559. { decide whether to free block or add to list }
  560. {$ifdef HAS_SYSOSFREE}
  561. if freeoslistcount >= 3 then
  562. begin
  563. dec(internal_status.currheapsize, poc^.size);
  564. SysOSFree(poc, poc^.size);
  565. end
  566. else
  567. begin
  568. {$endif}
  569. poc^.prev := nil;
  570. poc^.next := freeoslist;
  571. if freeoslist <> nil then
  572. freeoslist^.prev := poc;
  573. freeoslist := poc;
  574. inc(freeoslistcount);
  575. {$ifdef HAS_SYSOSFREE}
  576. end;
  577. {$endif}
  578. end;
  579. procedure remove_from_oslist(poc: poschunk);
  580. begin
  581. if assigned(poc^.next) then
  582. poc^.next^.prev := poc^.prev;
  583. if assigned(poc^.prev) then
  584. poc^.prev^.next := poc^.next
  585. else
  586. freeoslist := poc^.next;
  587. dec(freeoslistcount);
  588. end;
  589. procedure append_to_oslist_var(pmc: pmemchunk_var);
  590. var
  591. poc: poschunk;
  592. begin
  593. // block eligable for freeing
  594. poc := pointer(pmc)-sizeof(toschunk);
  595. remove_from_list_var(pmc);
  596. append_to_oslist(poc);
  597. end;
  598. procedure append_to_oslist_fixed(blockindex, chunksize: ptrint; poc: poschunk);
  599. var
  600. pmc: pmemchunk_fixed;
  601. i, count: ptrint;
  602. begin
  603. count := (poc^.size - sizeof(toschunk)) div chunksize;
  604. pmc := pmemchunk_fixed(pointer(poc)+sizeof(toschunk));
  605. for i := 0 to count - 1 do
  606. begin
  607. remove_from_list_fixed(blockindex, pmc);
  608. pmc := pointer(pmc)+chunksize;
  609. end;
  610. append_to_oslist(poc);
  611. end;
  612. {*****************************************************************************
  613. Split block
  614. *****************************************************************************}
  615. procedure split_block(pcurr: pmemchunk_var; size: ptrint);
  616. var
  617. pcurr_tmp : pmemchunk_var;
  618. sizeleft: ptrint;
  619. begin
  620. sizeleft := (pcurr^.size and sizemask)-size;
  621. if sizeleft>=blocksize then
  622. begin
  623. pcurr_tmp := pmemchunk_var(pointer(pcurr)+size);
  624. { update prevsize of block to the right }
  625. if (pcurr^.size and lastblockflag) = 0 then
  626. pmemchunk_var(pointer(pcurr)+(pcurr^.size and sizemask))^.prevsize := sizeleft;
  627. { inherit the lastblockflag }
  628. pcurr_tmp^.size := sizeleft or (pcurr^.size and lastblockflag);
  629. pcurr_tmp^.prevsize := size;
  630. { the block we return is not the last one anymore (there's now a block after it) }
  631. { decrease size of block to new size }
  632. pcurr^.size := size or (pcurr^.size and (not sizemask and not lastblockflag));
  633. { insert the block in the freelist }
  634. append_to_list_var(pcurr_tmp);
  635. end;
  636. end;
  637. {*****************************************************************************
  638. Try concat freerecords
  639. *****************************************************************************}
  640. procedure concat_two_blocks(mc_left, mc_right: pmemchunk_var);
  641. var
  642. mc_tmp : pmemchunk_var;
  643. size_right : ptrint;
  644. begin
  645. // mc_right can't be a fixed size block
  646. if mc_right^.size and fixedsizeflag<>0 then
  647. HandleError(204);
  648. // left block free, concat with right-block
  649. size_right := mc_right^.size and sizemask;
  650. inc(mc_left^.size, size_right);
  651. // if right-block was last block, copy flag
  652. if (mc_right^.size and lastblockflag) <> 0 then
  653. begin
  654. mc_left^.size := mc_left^.size or lastblockflag;
  655. end
  656. else
  657. begin
  658. // there is a block to the right of the right-block, adjust it's prevsize
  659. mc_tmp := pmemchunk_var(pointer(mc_right)+size_right);
  660. mc_tmp^.prevsize := mc_left^.size and sizemask;
  661. end;
  662. // remove right-block from doubly linked list
  663. remove_from_list_var(mc_right);
  664. end;
  665. procedure try_concat_free_chunk_forward(mc: pmemchunk_var);
  666. var
  667. mc_tmp : pmemchunk_var;
  668. begin
  669. { try concat forward }
  670. if (mc^.size and lastblockflag) = 0 then
  671. begin
  672. mc_tmp := pmemchunk_var(pointer(mc)+(mc^.size and sizemask));
  673. if (mc_tmp^.size and usedflag) = 0 then
  674. begin
  675. // next block free: concat
  676. concat_two_blocks(mc, mc_tmp);
  677. end;
  678. end;
  679. end;
  680. function try_concat_free_chunk(mc: pmemchunk_var): pmemchunk_var;
  681. var
  682. mc_tmp : pmemchunk_var;
  683. begin
  684. try_concat_free_chunk_forward(mc);
  685. { try concat backward }
  686. if (mc^.size and firstblockflag) = 0 then
  687. begin
  688. mc_tmp := pmemchunk_var(pointer(mc)-mc^.prevsize);
  689. if (mc_tmp^.size and usedflag) = 0 then
  690. begin
  691. // prior block free: concat
  692. concat_two_blocks(mc_tmp, mc);
  693. mc := mc_tmp;
  694. end;
  695. end;
  696. result := mc;
  697. end;
  698. function check_concat_free_chunk_forward(mc: pmemchunk_var;reqsize:ptrint):boolean;
  699. var
  700. mc_tmp : pmemchunk_var;
  701. freesize : ptrint;
  702. begin
  703. check_concat_free_chunk_forward:=false;
  704. freesize:=0;
  705. mc_tmp:=mc;
  706. repeat
  707. inc(freesize,mc_tmp^.size and sizemask);
  708. if freesize>=reqsize then
  709. begin
  710. check_concat_free_chunk_forward:=true;
  711. exit;
  712. end;
  713. if (mc_tmp^.size and lastblockflag) <> 0 then
  714. break;
  715. mc_tmp := pmemchunk_var(pointer(mc_tmp)+(mc_tmp^.size and sizemask));
  716. if (mc_tmp^.size and usedflag) <> 0 then
  717. break;
  718. until false;
  719. end;
  720. {*****************************************************************************
  721. Grow Heap
  722. *****************************************************************************}
  723. function alloc_oschunk(blockindex, size: ptrint): pointer;
  724. var
  725. pmc : pmemchunk_fixed;
  726. pmcv : pmemchunk_var;
  727. minsize,
  728. maxsize,
  729. i, count : ptrint;
  730. chunksize : ptrint;
  731. begin
  732. { increase size by size needed for os block header }
  733. minsize := size + sizeof(toschunk);
  734. if blockindex<>0 then
  735. maxsize := (size * $ffff) + sizeof(toschunk)
  736. else
  737. maxsize := high(ptrint);
  738. { blocks available in freelist? }
  739. result := freeoslist;
  740. while result <> nil do
  741. begin
  742. if (poschunk(result)^.size >= minsize) and
  743. (poschunk(result)^.size <= maxsize) then
  744. begin
  745. size := poschunk(result)^.size;
  746. remove_from_oslist(poschunk(result));
  747. break;
  748. end;
  749. result := poschunk(result)^.next;
  750. end;
  751. if result = nil then
  752. begin
  753. {$ifdef DUMPGROW}
  754. writeln('growheap(',size,') allocating ',(size+sizeof(toschunk)+$ffff) and $ffff0000);
  755. DumpBlocks;
  756. {$endif}
  757. { allocate by 64K size }
  758. size := (size+sizeof(toschunk)+$ffff) and not $ffff;
  759. { allocate smaller blocks for fixed-size chunks }
  760. if blockindex<>0 then
  761. begin
  762. result := SysOSAlloc(GrowHeapSizeSmall);
  763. if result<>nil then
  764. size := GrowHeapSizeSmall;
  765. end
  766. { first try 256K (default) }
  767. else if size<=GrowHeapSize1 then
  768. begin
  769. result := SysOSAlloc(GrowHeapSize1);
  770. if result<>nil then
  771. size := GrowHeapSize1;
  772. end
  773. { second try 1024K (default) }
  774. else if size<=GrowHeapSize2 then
  775. begin
  776. result := SysOSAlloc(GrowHeapSize2);
  777. if result<>nil then
  778. size := GrowHeapSize2;
  779. end
  780. { else allocate the needed bytes }
  781. else
  782. result := SysOSAlloc(size);
  783. { try again }
  784. if result=nil then
  785. begin
  786. result := SysOSAlloc(size);
  787. if (result=nil) then
  788. begin
  789. if ReturnNilIfGrowHeapFails then
  790. exit
  791. else
  792. HandleError(203);
  793. end;
  794. end;
  795. { set the total new heap size }
  796. inc(internal_status.currheapsize,size);
  797. if internal_status.currheapsize>internal_status.maxheapsize then
  798. internal_status.maxheapsize:=internal_status.currheapsize;
  799. end;
  800. { initialize os-block }
  801. poschunk(result)^.used := 0;
  802. poschunk(result)^.size := size;
  803. inc(result, sizeof(toschunk));
  804. if blockindex<>0 then
  805. begin
  806. { chop os chunk in fixedsize parts,
  807. maximum of $ffff elements are allowed, otherwise
  808. there will be an overflow }
  809. chunksize := blockindex shl blockshr;
  810. count := (size-sizeof(toschunk)) div chunksize;
  811. if count>$ffff then
  812. HandleError(204);
  813. pmc := pmemchunk_fixed(result);
  814. pmc^.prev_fixed := nil;
  815. i := 0;
  816. repeat
  817. pmc^.size := fixedsizeflag or chunksize or (i shl 16);
  818. pmc^.next_fixed := pointer(pmc)+chunksize;
  819. inc(i);
  820. if i < count then
  821. begin
  822. pmc := pmemchunk_fixed(pointer(pmc)+chunksize);
  823. pmc^.prev_fixed := pointer(pmc)-chunksize;
  824. end
  825. else
  826. begin
  827. break;
  828. end;
  829. until false;
  830. append_to_list_fixed(blockindex, pmc);
  831. pmc^.prev_fixed := pointer(pmc)-chunksize;
  832. freelists_fixed[blockindex] := pmemchunk_fixed(result);
  833. end
  834. else
  835. begin
  836. pmcv := pmemchunk_var(result);
  837. append_to_list_var(pmcv);
  838. pmcv^.size := ((size-sizeof(toschunk)) and sizemask) or (firstblockflag or lastblockflag);
  839. pmcv^.prevsize := 0;
  840. end;
  841. {$ifdef TestFreeLists}
  842. TestFreeLists;
  843. {$endif TestFreeLists}
  844. end;
  845. {*****************************************************************************
  846. SysGetMem
  847. *****************************************************************************}
  848. function SysGetMem_Fixed(size: ptrint): pointer;
  849. var
  850. pcurr: pmemchunk_fixed;
  851. poc: poschunk;
  852. s: ptrint;
  853. begin
  854. result:=nil;
  855. { try to find a block in one of the freelists per size }
  856. s := size shr blockshr;
  857. pcurr := freelists_fixed[s];
  858. { no free blocks ? }
  859. if not assigned(pcurr) then
  860. begin
  861. pcurr := alloc_oschunk(s, size);
  862. if not assigned(pcurr) then
  863. exit;
  864. end;
  865. { get a pointer to the block we should return }
  866. result := pointer(pcurr)+sizeof(tmemchunk_fixed_hdr);
  867. { flag as in-use }
  868. pcurr^.size := pcurr^.size or usedflag;
  869. { update freelist }
  870. freelists_fixed[s] := pcurr^.next_fixed;
  871. if assigned(freelists_fixed[s]) then
  872. freelists_fixed[s]^.prev_fixed := nil;
  873. poc := poschunk(pointer(pcurr)-((pcurr^.size shr 16)*(pcurr^.size and fixedsizemask)+sizeof(toschunk)));
  874. inc(poc^.used);
  875. { statistics }
  876. inc(internal_status.currheapused,size);
  877. if internal_status.currheapused>internal_status.maxheapused then
  878. internal_status.maxheapused:=internal_status.currheapused;
  879. {$ifdef TestFreeLists}
  880. if test_each then
  881. TestFreeLists;
  882. {$endif TestFreeLists}
  883. end;
  884. function SysGetMem_Var(size: ptrint): pointer;
  885. var
  886. pcurr : pmemchunk_var;
  887. {$ifdef BESTMATCH}
  888. pbest : pmemchunk_var;
  889. {$endif}
  890. begin
  891. result:=nil;
  892. {$ifdef BESTMATCH}
  893. pbest := nil;
  894. {$endif}
  895. pcurr := freelist_var;
  896. while assigned(pcurr) do
  897. begin
  898. {$ifdef BESTMATCH}
  899. if pcurr^.size=size then
  900. begin
  901. break;
  902. end
  903. else
  904. begin
  905. if (pcurr^.size>size) then
  906. begin
  907. if (not assigned(pbest)) or
  908. (pcurr^.size<pbest^.size) then
  909. pbest := pcurr;
  910. end;
  911. end;
  912. {$else BESTMATCH}
  913. if pcurr^.size>=size then
  914. break;
  915. {$endif BESTMATCH}
  916. pcurr := pcurr^.next_var;
  917. end;
  918. {$ifdef BESTMATCH}
  919. if not assigned(pcurr) then
  920. pcurr := pbest;
  921. {$endif}
  922. if not assigned(pcurr) then
  923. begin
  924. // all os-chunks full, allocate a new one
  925. pcurr := alloc_oschunk(0, size);
  926. if not assigned(pcurr) then
  927. exit;
  928. end;
  929. { get pointer of the block we should return }
  930. result := pointer(pcurr)+sizeof(tmemchunk_var_hdr);
  931. { remove the current block from the freelist }
  932. remove_from_list_var(pcurr);
  933. { create the left over freelist block, if at least 16 bytes are free }
  934. split_block(pcurr, size);
  935. { flag block as used }
  936. pcurr^.size := pcurr^.size or usedflag;
  937. { statistics }
  938. inc(internal_status.currheapused,size);
  939. if internal_status.currheapused>internal_status.maxheapused then
  940. internal_status.maxheapused:=internal_status.currheapused;
  941. {$ifdef TestFreeLists}
  942. if test_each then
  943. TestFreeLists;
  944. {$endif TestFreeLists}
  945. end;
  946. function SysGetMem(size : ptrint):pointer;
  947. begin
  948. { Something to allocate ? }
  949. if size<=0 then
  950. begin
  951. { give an error for < 0 }
  952. if size<0 then
  953. HandleError(204);
  954. { we always need to allocate something, using heapend is not possible,
  955. because heappend can be changed by growheap (PFV) }
  956. size := 1;
  957. end;
  958. { calc to multiple of 16 after adding the needed bytes for memchunk header }
  959. if size <= (maxblocksize - sizeof(tmemchunk_fixed_hdr)) then
  960. begin
  961. size := (size+sizeof(tmemchunk_fixed_hdr)+(blocksize-1)) and fixedsizemask;
  962. sysgetmem := sysgetmem_fixed(size);
  963. end
  964. else
  965. begin
  966. size := (size+sizeof(tmemchunk_var_hdr)+(blocksize-1)) and sizemask;
  967. sysgetmem := sysgetmem_var(size);
  968. end;
  969. end;
  970. {*****************************************************************************
  971. SysFreeMem
  972. *****************************************************************************}
  973. function SysFreeMem_Fixed(pcurr: pmemchunk_fixed; size: ptrint): ptrint;
  974. var
  975. pcurrsize: ptrint;
  976. blockindex: ptrint;
  977. poc: poschunk;
  978. begin
  979. pcurrsize := pcurr^.size and fixedsizemask;
  980. if size<>pcurrsize then
  981. HandleError(204);
  982. dec(internal_status.currheapused,pcurrsize);
  983. { insert the block in it's freelist }
  984. pcurr^.size := pcurr^.size and (not usedflag);
  985. blockindex := pcurrsize shr blockshr;
  986. append_to_list_fixed(blockindex, pcurr);
  987. { decrease used blocks count }
  988. poc := poschunk(pointer(pcurr)-(pcurr^.size shr 16)*pcurrsize-sizeof(toschunk));
  989. if poc^.used = 0 then
  990. HandleError(204);
  991. dec(poc^.used);
  992. if poc^.used = 0 then
  993. begin
  994. // block eligable for freeing
  995. append_to_oslist_fixed(blockindex, pcurrsize, poc);
  996. end;
  997. SysFreeMem_Fixed := pcurrsize;
  998. {$ifdef TestFreeLists}
  999. if test_each then
  1000. TestFreeLists;
  1001. {$endif TestFreeLists}
  1002. end;
  1003. function SysFreeMem_Var(pcurr: pmemchunk_var; size: ptrint): ptrint;
  1004. var
  1005. pcurrsize: ptrint;
  1006. begin
  1007. pcurrsize := pcurr^.size and sizemask;
  1008. if size<>pcurrsize then
  1009. HandleError(204);
  1010. dec(internal_status.currheapused,pcurrsize);
  1011. { insert the block in it's freelist }
  1012. pcurr^.size := pcurr^.size and (not usedflag);
  1013. append_to_list_var(pcurr);
  1014. SysFreeMem_Var := pcurrsize;
  1015. pcurr := try_concat_free_chunk(pcurr);
  1016. if (pcurr^.size and (firstblockflag or lastblockflag)) = (firstblockflag or lastblockflag) then
  1017. begin
  1018. append_to_oslist_var(pcurr);
  1019. end;
  1020. {$ifdef TestFreeLists}
  1021. if test_each then
  1022. TestFreeLists;
  1023. {$endif TestFreeLists}
  1024. end;
  1025. function SysFreeMem(p: pointer): ptrint;
  1026. var
  1027. pcurrsize: ptrint;
  1028. begin
  1029. if p=nil then
  1030. exit;
  1031. pcurrsize := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr))^.size;
  1032. { check if this is a fixed- or var-sized chunk }
  1033. if (pcurrsize and fixedsizeflag) = 0 then
  1034. begin
  1035. result := sysfreemem_var(pmemchunk_var(p-sizeof(tmemchunk_var_hdr)), pcurrsize and sizemask);
  1036. end
  1037. else
  1038. begin
  1039. result := sysfreemem_fixed(pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr)), pcurrsize and fixedsizemask);
  1040. end;
  1041. end;
  1042. {*****************************************************************************
  1043. SysFreeMemSize
  1044. *****************************************************************************}
  1045. Function SysFreeMemSize(p: pointer; size: ptrint):ptrint;
  1046. var
  1047. pcurrsize: ptrint;
  1048. begin
  1049. SysFreeMemSize := 0;
  1050. if size<=0 then
  1051. begin
  1052. if size<0 then
  1053. HandleError(204);
  1054. exit;
  1055. end;
  1056. if p=nil then
  1057. HandleError(204);
  1058. pcurrsize := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr))^.size;
  1059. { check if this is a fixed- or var-sized chunk }
  1060. if (pcurrsize and fixedsizeflag) = 0 then
  1061. begin
  1062. size := (size+sizeof(tmemchunk_var_hdr)+(blocksize-1)) and sizemask;
  1063. result := sysfreemem_var(pmemchunk_var(p-sizeof(tmemchunk_var_hdr)), size);
  1064. end
  1065. else
  1066. begin
  1067. size := (size+sizeof(tmemchunk_fixed_hdr)+(blocksize-1)) and fixedsizemask;
  1068. result := sysfreemem_fixed(pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr)), size);
  1069. end;
  1070. end;
  1071. {*****************************************************************************
  1072. SysMemSize
  1073. *****************************************************************************}
  1074. function SysMemSize(p: pointer): ptrint;
  1075. begin
  1076. SysMemSize := pmemchunk_fixed(pointer(p)-sizeof(tmemchunk_fixed_hdr))^.size;
  1077. if (SysMemSize and fixedsizeflag) = 0 then
  1078. begin
  1079. SysMemSize := SysMemSize and sizemask;
  1080. dec(SysMemSize, sizeof(tmemchunk_var_hdr));
  1081. end
  1082. else
  1083. begin
  1084. SysMemSize := SysMemSize and fixedsizemask;
  1085. dec(SysMemSize, sizeof(tmemchunk_fixed_hdr));
  1086. end;
  1087. end;
  1088. {*****************************************************************************
  1089. SysAllocMem
  1090. *****************************************************************************}
  1091. function SysAllocMem(size: ptrint): pointer;
  1092. begin
  1093. sysallocmem := MemoryManager.GetMem(size);
  1094. if sysallocmem<>nil then
  1095. FillChar(sysallocmem^,MemoryManager.MemSize(sysallocmem),0);
  1096. end;
  1097. {*****************************************************************************
  1098. SysResizeMem
  1099. *****************************************************************************}
  1100. function SysTryResizeMem(var p: pointer; size: ptrint): boolean;
  1101. var
  1102. pcurrsize,
  1103. oldsize,
  1104. currsize : ptrint;
  1105. pcurr : pmemchunk_var;
  1106. begin
  1107. SysTryResizeMem := false;
  1108. { fix p to point to the heaprecord }
  1109. pcurrsize := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr))^.size;
  1110. if (pcurrsize and fixedsizeflag) = 0 then
  1111. begin
  1112. currsize := pcurrsize and sizemask;
  1113. size := (size+sizeof(tmemchunk_var_hdr)+(blocksize-1)) and sizemask;
  1114. end
  1115. else
  1116. begin
  1117. currsize := pcurrsize and fixedsizemask;
  1118. size := (size+sizeof(tmemchunk_fixed_hdr)+(blocksize-1)) and fixedsizemask;
  1119. end;
  1120. { is the allocated block still correct? }
  1121. if (currsize>=size) and (size>(currsize-blocksize)) then
  1122. begin
  1123. SysTryResizeMem := true;
  1124. {$ifdef TestFreeLists}
  1125. if test_each then
  1126. TestFreeLists;
  1127. {$endif TestFreeLists}
  1128. exit;
  1129. end;
  1130. { don't do resizes on fixed-size blocks }
  1131. if (pcurrsize and fixedsizeflag) <> 0 then
  1132. exit;
  1133. { get pointer to block }
  1134. pcurr := pmemchunk_var(pointer(p)-sizeof(tmemchunk_var_hdr));
  1135. oldsize := currsize;
  1136. { do we need to allocate more memory ? }
  1137. if size>currsize then
  1138. begin
  1139. { the size is bigger than the previous size, we need to allocated more mem.
  1140. We first check if the blocks after the current block are free. If not we
  1141. simply call getmem/freemem to get the new block }
  1142. if check_concat_free_chunk_forward(pcurr,size) then
  1143. begin
  1144. try_concat_free_chunk_forward(pcurr);
  1145. currsize := (pcurr^.size and sizemask);
  1146. end;
  1147. end;
  1148. { not enough space? }
  1149. if size>currsize then
  1150. exit;
  1151. { is the size smaller then we can adjust the block to that size and insert
  1152. the other part into the freelist }
  1153. if currsize>size then
  1154. split_block(pcurr, size);
  1155. inc(internal_status.currheapused,size-oldsize);
  1156. SysTryResizeMem := true;
  1157. {$ifdef TestFreeLists}
  1158. if test_each then
  1159. TestFreeLists;
  1160. {$endif TestFreeLists}
  1161. end;
  1162. {*****************************************************************************
  1163. SysResizeMem
  1164. *****************************************************************************}
  1165. function SysReAllocMem(var p: pointer; size: ptrint):pointer;
  1166. var
  1167. minsize : ptrint;
  1168. p2 : pointer;
  1169. begin
  1170. { Free block? }
  1171. if size=0 then
  1172. begin
  1173. if p<>nil then
  1174. begin
  1175. MemoryManager.FreeMem(p);
  1176. p := nil;
  1177. end;
  1178. end
  1179. else
  1180. { Allocate a new block? }
  1181. if p=nil then
  1182. begin
  1183. p := MemoryManager.GetMem(size);
  1184. end
  1185. else
  1186. { Resize block }
  1187. if not SysTryResizeMem(p,size) then
  1188. begin
  1189. minsize := MemoryManager.MemSize(p);
  1190. if size < minsize then
  1191. minsize := size;
  1192. p2 := MemoryManager.GetMem(size);
  1193. if p2<>nil then
  1194. Move(p^,p2^,minsize);
  1195. MemoryManager.FreeMem(p);
  1196. p := p2;
  1197. end;
  1198. SysReAllocMem := p;
  1199. end;
  1200. {*****************************************************************************
  1201. MemoryMutexManager default hooks
  1202. *****************************************************************************}
  1203. procedure SysHeapMutexInit;
  1204. begin
  1205. { nothing todo }
  1206. end;
  1207. procedure SysHeapMutexDone;
  1208. begin
  1209. { nothing todo }
  1210. end;
  1211. procedure SysHeapMutexLock;
  1212. begin
  1213. { give an runtime error. the program is running multithreaded without
  1214. any heap protection. this will result in unpredictable errors so
  1215. stopping here with an error is more safe (PFV) }
  1216. runerror(244);
  1217. end;
  1218. procedure SysHeapMutexUnLock;
  1219. begin
  1220. { see SysHeapMutexLock for comment }
  1221. runerror(244);
  1222. end;
  1223. {*****************************************************************************
  1224. InitHeap
  1225. *****************************************************************************}
  1226. { This function will initialize the Heap manager and need to be called from
  1227. the initialization of the system unit }
  1228. procedure InitHeap;
  1229. begin
  1230. FillChar(freelists_fixed,sizeof(tfreelists),0);
  1231. freelist_var := nil;
  1232. freeoslist := nil;
  1233. freeoslistcount := 0;
  1234. fillchar(internal_status,sizeof(internal_status),0);
  1235. end;
  1236. {
  1237. $Log$
  1238. Revision 1.51 2005-04-04 15:40:30 peter
  1239. * check if there is enough room before concatting blocks in
  1240. systryresizemem()
  1241. Revision 1.50 2005/03/25 22:53:39 jonas
  1242. * fixed several warnings and notes about unused variables (mainly) or
  1243. uninitialised use of variables/function results (a few)
  1244. Revision 1.49 2005/03/21 16:31:33 peter
  1245. * fix crash under win32 with previous reallocmem fix
  1246. Revision 1.48 2005/03/20 18:57:29 peter
  1247. * fixed tryresizemem
  1248. Revision 1.47 2005/03/04 16:49:34 peter
  1249. * fix getheapstatus bootstrapping
  1250. Revision 1.46 2005/03/02 14:25:19 marco
  1251. * small typo fix on last commit
  1252. Revision 1.45 2005/03/02 10:46:10 marco
  1253. * getfpcheapstatus now also on memmgr
  1254. Revision 1.44 2005/02/28 15:38:38 marco
  1255. * getFPCheapstatus (no, FPC HEAP, not FP CHEAP!)
  1256. Revision 1.43 2005/02/14 17:13:22 peter
  1257. * truncate log
  1258. Revision 1.42 2005/01/30 11:56:29 peter
  1259. * allow Freemem(nil)
  1260. }