heap.inc 36 KB

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