Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

474 lines
17 KiB

  1. /*
  2. * heap.h - structures and equates for the Windows 32-bit heap
  3. *
  4. * Origin: Chicago
  5. *
  6. * Change history:
  7. *
  8. * Date Who Description
  9. * --------- --------- -------------------------------------------------
  10. * 1991 BrianSm Created
  11. */
  12. #ifdef DEBUG
  13. #define HPDEBUG 1
  14. #endif
  15. #ifndef WIN32
  16. #define WIN32
  17. #endif
  18. #define HPNOTTRUSTED 1 /* enable parameter checking */
  19. /***LT busyblock_s - busy heap block header structure
  20. *
  21. * This structure is stored at the head of every busy (not free) heap
  22. * block.
  23. *
  24. * The bh_size field is in bytes and includes the size of the
  25. * heap header and any slop at the end of the block that might have
  26. * been included because of the heap granularity, or to keep us
  27. * from leaving a block too small to hold a free heap header.
  28. *
  29. * bh_size is also used as a forward link to the next heap block.
  30. *
  31. * The low two bits of the bh_size field are used to hold flags
  32. * (BP_FREE must be clear and HP_PREVFREE is optionally set).
  33. */
  34. #ifndef HPDEBUG
  35. struct busyheap_s {
  36. unsigned long bh_size; /* block size + flags in low 2 bits */
  37. };
  38. #else
  39. struct busyheap_s {
  40. unsigned long bh_size; /* block size + flags in low 2 bits */
  41. unsigned long bh_eip; /* EIP of allocator */
  42. unsigned short bh_tid; /* thread id of allocator */
  43. unsigned short bh_signature; /* signature (should be BH_SIGNATURE)*/
  44. unsigned long bh_sum; /* checksum of this structure */
  45. };
  46. #endif
  47. /*XLATOFF*/
  48. #define BH_SIGNATURE 0x4842 /* busy heap block signature (BH) */
  49. /*XLATON*/
  50. #define BH_CDWSUM 3 /* count of dwords to sum in struct */
  51. /***LT freeblock_s - free heap block header structure
  52. *
  53. * This structure is stored at the head of every free block on the
  54. * heap. In the last dword of every free heap block is a pointer
  55. * the this structure.
  56. *
  57. * The fh_size field is in bytes and includes the size of the
  58. * heap header and any slop at the end of the block that might have
  59. * been included because of the heap granularity, or to keep us
  60. * from leaving a block too small to hold a free heap header.
  61. *
  62. * fh_size is also used as a forward link to the next heap block.
  63. *
  64. * The low two bits of the fh_size field are used to hold flags
  65. * (HP_FREE must be set and HP_PREVFREE must be clear).
  66. */
  67. #ifndef HPDEBUG
  68. struct freeheap_s {
  69. unsigned long fh_size; /* block size + flags in low 2 bits */
  70. struct freeheap_s *fh_flink; /* forward link to next free block */
  71. struct freeheap_s *fh_blink; /* back link to previous free block */
  72. };
  73. #else
  74. struct freeheap_s {
  75. unsigned long fh_size; /* block size + flags in low 2 bits */
  76. struct freeheap_s *fh_flink; /* forward link to next free block */
  77. unsigned short fh_pad; /* unused */
  78. unsigned short fh_signature;/* signature (should be FH_SIGNATURE)*/
  79. struct freeheap_s *fh_blink; /* back link to previous free block */
  80. unsigned long fh_sum; /* checksum of this structure */
  81. };
  82. #endif
  83. /*XLATOFF*/
  84. #define FH_SIGNATURE 0x4846 /* free heap block signature (FH) */
  85. /*XLATON*/
  86. #define FH_CDWSUM 4 /* count of dwords to sum in struct */
  87. /*
  88. * Equates common to all heap blocks.
  89. *
  90. * HP_FREE and HP_PREVFREE (HP_FLAGS) are stored in the low two
  91. * bits of the fh_ and bh_size field.
  92. * The signature is stored in the high three bits of the size.
  93. */
  94. #define HP_FREE 0x00000001 /* block is free */
  95. #define HP_PREVFREE 0x00000002 /* previous block is free */
  96. #define HP_FLAGS 0x00000003 /* mask for all the flags */
  97. #define HP_SIZE 0x0ffffffc /* mask for clearing flags */
  98. #define HP_SIGBITS 0xf0000000 /* bits used for signature */
  99. #define HP_SIGNATURE 0xa0000000 /* valid value of signature */
  100. /*
  101. * Misc heap equates
  102. */
  103. #define hpGRANULARITY 4 /* granularity for heap allocations */
  104. #define hpGRANMASK (hpGRANULARITY - 1) /* for rounding */
  105. /*XLATOFF*/
  106. #define hpMINSIZE (sizeof(struct freeheap_s)+sizeof(struct freeheap_s *))
  107. /* min block size */
  108. #define hpMAXALLOC (HP_SIZE - 100) /* biggest allocatable heap block */
  109. /* overhead for a new heap segment (header plus end sentinel) */
  110. #define hpSEGOVERHEAD (sizeof(struct busyheap_s) + sizeof(struct heapseg_s))
  111. /* default reserved size of new segments added to growable heaps */
  112. #define hpCBRESERVE (4*1024*1024)
  113. /*XLATON*/
  114. /*
  115. * Exported flags for heap calls
  116. */
  117. #ifdef WIN32
  118. #define HP_ZEROINIT 0x40 /* zero initialize block on HP(Re)Alloc */
  119. #define HP_MOVEABLE 0x02 /* block can be moved (HP(Re)Alloc) */
  120. #define HP_NOCOPY 0x20 /* don't copy data on HPReAlloc */
  121. #define HP_NOSERIALIZE 0x01 /* don't serialize heap access */
  122. #define HP_EXCEPT 0x04 /* generate exceptions on error */
  123. #ifdef HPMEASURE
  124. #define HP_MEASURE 0x80 /* enable heap measurement */
  125. #endif
  126. #else
  127. #define HP_ZEROINIT 0x01 /* zero initialize block on HP(Re)Alloc */
  128. #define HP_NOSERIALIZE 0x08 /* don't serialize heap access (HPInit) */
  129. #define HP_NOCOPY 0x04 /* don't copy data on HPReAlloc */
  130. #define HP_MOVEABLE 0x10 /* allow moving on HPReAlloc */
  131. #define HP_LOCKED 0x80 /* put heap in locked memory (HPInit) */
  132. #endif
  133. #define HP_FIXED 0x00 /* block is at a fixed address (HPAlloc) */
  134. #define HP_GROWABLE 0x40 /* heap can grow beyond cbreserve (HPInit) */
  135. /*
  136. * Note that flags above 0x80 will not be stored into the heap header in
  137. * HPInit calls because the flags field in the header is only a byte
  138. */
  139. #define HP_INITSEGMENT 0x100 /* just initialize a heap segment (HPInit) */
  140. #define HP_DECOMMIT 0x200 /* decommit pages in free block (hpFreeSub) */
  141. #define HP_GROWUP 0x400 /* waste last page of heap (HPInit) */
  142. /*XLATOFF*/
  143. /***LP hpSize - pull size field from heap header
  144. *
  145. * This routine depends on the size field being the first
  146. * dword in the header.
  147. *
  148. * ENTRY: ph - pointer to heap header
  149. * EXIT: count of bytes in block (counting header).
  150. */
  151. #define hpSize(ph) (*((unsigned long *)(ph)) & HP_SIZE)
  152. /***LP hpSetSize - set the size parameter in a heap header
  153. *
  154. * This routine depends on the size field being the first
  155. * dword in the header.
  156. *
  157. * ENTRY: ph - pointer to busy heap header
  158. * cb - count of bytes (should be rounded using hpRoundUp)
  159. * EXIT: size is set in heap header
  160. */
  161. #define hpSetSize(ph, cb) (((struct busyheap_s *)(ph))->bh_size = \
  162. ((((struct busyheap_s *)(ph))->bh_size & ~HP_SIZE) | (cb)))
  163. /* the compiler used to do a better version with this macro than the above,
  164. * but not any more
  165. #define hpSetSize2(ph, cb) *(unsigned long *)(ph) &= ~HP_SIZE; \
  166. *(unsigned long *)(ph) |= (cb);
  167. */
  168. /***LP hpSetBusySize - set the entire bh_size dword for a busy block
  169. *
  170. * This macro will set the bh_size field of the given heap header
  171. * to the given size as well as setting the HP_SIGNATURE and clearing
  172. * any HP_FREE or HP_PREVFREE bits.
  173. *
  174. * ENTRY: ph - pointer to busy heap header
  175. * cb - count of bytes (should be rounded using hpRoundUp)
  176. * EXIT: bh_size field is initialized
  177. */
  178. #define hpSetBusySize(ph, cb) ((ph)->bh_size = ((cb) | HP_SIGNATURE))
  179. /***LP hpSetFreeSize - set the entire fh_size dword for a free block
  180. *
  181. * This macro will set the fh_size field of the given heap header
  182. * to the given size as well as setting the HP_SIGNATURE and HP_FREE
  183. * and clearing HP_PREVFREE.
  184. *
  185. * ENTRY: ph - pointer to free heap header
  186. * cb - count of bytes (should be rounded using hpRoundUp)
  187. * EXIT: bh_size field is initialized
  188. */
  189. #define hpSetFreeSize(ph, cb) ((ph)->fh_size = ((cb) | HP_SIGNATURE | HP_FREE))
  190. /***LP hpIsBusySignatureValid - check a busy heap block's signature
  191. *
  192. * This macro checks the tiny signature (HP_SIGNATURE) in the bh_size
  193. * field to see if it is set properly and makes sure that the HP_FREE
  194. * bit is clear.
  195. *
  196. * ENTRY: ph - pointer to a busy heap header
  197. * EXIT: TRUE if signature is ok, else FALSE
  198. */
  199. #define hpIsBusySignatureValid(ph) \
  200. (((ph)->bh_size & (HP_SIGBITS | HP_FREE)) == HP_SIGNATURE)
  201. /***LP hpIsFreeSignatureValid - check a free heap block's signature
  202. *
  203. * This macro checks the tiny signature (HP_SIGNATURE) in the fh_size
  204. * field to see if it is set properly and makes sure that the HP_FREE
  205. * bit is also set and HP_PREVFREE is clear.
  206. *
  207. * ENTRY: ph - pointer to a free heap header
  208. * EXIT: TRUE if signature is ok, else FALSE
  209. */
  210. #define hpIsFreeSignatureValid(ph) \
  211. (((ph)->fh_size & (HP_SIGBITS | HP_FREE | HP_PREVFREE)) == \
  212. (HP_SIGNATURE | HP_FREE))
  213. /***LP hpRoundUp - round up byte count to appropriate heap block size
  214. *
  215. * Heap blocks have a minimum size of hpMINSIZE and hpGRANULARITY
  216. * granularity. This macro also adds on size for the heap header.
  217. *
  218. * ENTRY: cb - count of bytes
  219. * EXIT: count rounded up to hpGANULARITY boundary
  220. */
  221. #define hpRoundUp(cb) \
  222. max(hpMINSIZE, \
  223. (((cb) + sizeof(struct busyheap_s) + hpGRANMASK) & ~hpGRANMASK))
  224. /*XLATON*/
  225. /***LK freelist_s - heap free list head
  226. */
  227. struct freelist_s {
  228. unsigned long fl_cbmax; /* max size block in this free list */
  229. struct freeheap_s fl_header; /* pseudo heap header as list head */
  230. };
  231. #define hpFREELISTHEADS 4 /* number of free list heads in heapinfo_s */
  232. /***LK heapinfo_s - per-heap information (stored at start of heap)
  233. *
  234. */
  235. struct heapinfo_s {
  236. /* These first three fields must match the fields of heapseg_s */
  237. unsigned long hi_cbreserve; /* bytes reserved for heap */
  238. struct heapseg_s *hi_psegnext; /* pointer to next heap segment*/
  239. struct freelist_s hi_freelist[hpFREELISTHEADS]; /* free list heads */
  240. #ifdef WIN32
  241. struct heapinfo_s *hi_procnext; /* linked list of process heaps */
  242. CRST *hi_pcritsec; /* pointer to serialization obj*/
  243. CRST hi_critsec; /* serialize access to heap */
  244. #ifdef HPDEBUG
  245. unsigned char hi_matchring0[(76-sizeof(CRST))]; /* pad so .mh command works */
  246. #endif
  247. #else
  248. struct _MTX *hi_pcritsec; /* pointer to serialization obj*/
  249. struct _MTX hi_critsec; /* serialize access to heap */
  250. #endif
  251. #ifdef HPDEBUG
  252. unsigned long hi_thread; /* thread pointer of thread
  253. * inside heap code */
  254. unsigned long hi_eip; /* EIP of heap's creator */
  255. unsigned long hi_sum; /* checksum of this structure*/
  256. unsigned short hi_tid; /* thread ID of heap's creator*/
  257. unsigned short hi_pad1; /* unused */
  258. #endif
  259. unsigned char hi_flags; /* HP_SERIALIZE, HP_LOCKED */
  260. unsigned char hi_pad2; /* unused */
  261. unsigned short hi_signature; /* should be HI_SIGNATURE */
  262. };
  263. /*
  264. * Heap Measurement functions
  265. */
  266. #define HPMEASURE_FREE 0x8000000L
  267. #define SAMPLE_CACHE_SIZE 1024
  268. struct measure_s {
  269. char szFile[260];
  270. unsigned iCur;
  271. unsigned uSamples[SAMPLE_CACHE_SIZE];
  272. };
  273. /*XLATOFF*/
  274. #define HI_SIGNATURE 0x4948 /* heapinfo_s signature (HI) */
  275. /*XLATON*/
  276. #define HI_CDWSUM 1 /* count of dwords to sum */
  277. typedef struct heapinfo_s *HHEAP;
  278. /***LK heapseg_s - per-heap segment structure
  279. *
  280. * Growable heaps can have multiple discontiguous sections of memory
  281. * allocated to them. Each is headed by one of these structures. The
  282. * first segment is special, in that it has a full heapinfo_s structure,
  283. * but the first fields of heapinfo_s match heapseg_s, so it can be
  284. * treated as just another segment when convenient.
  285. */
  286. struct heapseg_s {
  287. unsigned long hs_cbreserve; /* bytes reserved for this segment */
  288. struct heapseg_s *hs_psegnext; /* pointer to next heap segment*/
  289. };
  290. /* XLATOFF */
  291. /* smallest possible heap */
  292. #define hpMINHEAPSIZE (sizeof(struct heapinfo_s) + hpMINSIZE + \
  293. sizeof(struct busyheap_s))
  294. /***LP hpRemove - remove item from free list
  295. *
  296. * ENTRY: pfh - pointer to free heap block to remove from list
  297. * EXIT: none
  298. */
  299. #define hpRemoveNoSum(pfh) \
  300. (pfh)->fh_flink->fh_blink = (pfh)->fh_blink; \
  301. (pfh)->fh_blink->fh_flink = (pfh)->fh_flink;
  302. #ifdef HPDEBUG
  303. #define hpRemove(pfh) hpRemoveNoSum(pfh); \
  304. (pfh)->fh_flink->fh_sum = \
  305. hpSum((pfh)->fh_flink, FH_CDWSUM); \
  306. (pfh)->fh_blink->fh_sum = \
  307. hpSum((pfh)->fh_blink, FH_CDWSUM);
  308. #else
  309. #define hpRemove(pfh) hpRemoveNoSum(pfh)
  310. #endif
  311. /***LP hpInsert - insert item onto the free list
  312. *
  313. * ENTRY: pfh - free heap block to insert onto the list
  314. * pfhprev - insert pfh after this item
  315. * EXIT: none
  316. */
  317. #define hpInsertNoSum(pfh, pfhprev) \
  318. (pfh)->fh_flink = (pfhprev)->fh_flink; \
  319. (pfh)->fh_flink->fh_blink = (pfh); \
  320. (pfh)->fh_blink = (pfhprev); \
  321. (pfhprev)->fh_flink = (pfh)
  322. #ifdef HPDEBUG
  323. #define hpInsert(pfh, pfhprev) hpInsertNoSum(pfh, pfhprev); \
  324. (pfh)->fh_flink->fh_sum = \
  325. hpSum((pfh)->fh_flink, FH_CDWSUM); \
  326. (pfhprev)->fh_sum = \
  327. hpSum((pfhprev), FH_CDWSUM)
  328. #else
  329. #define hpInsert(pfh, pfhprev) hpInsertNoSum(pfh, pfhprev)
  330. #endif
  331. #ifdef WIN32
  332. #define INTERNAL
  333. #endif
  334. /*
  335. * critical section macros to be used by all internal heap functions
  336. */
  337. #ifndef WIN32
  338. #define hpEnterCriticalSection(hheap) mmEnterMutex(hheap->hi_pcritsec)
  339. #define hpLeaveCriticalSection(hheap) mmLeaveMutex(hheap->hi_pcritsec)
  340. #define hpInitializeCriticalSection(hheap) \
  341. hheap->hi_pcritsec = &(hheap->hi_critsec); \
  342. mmInitMutex(hheap->hi_pcritsec)
  343. #else
  344. #define hpEnterCriticalSection(hheap) EnterCrst(hheap->hi_pcritsec)
  345. #define hpLeaveCriticalSection(hheap) LeaveCrst(hheap->hi_pcritsec)
  346. #define hpInitializeCriticalSection(hheap) \
  347. if (hheapKernel) { \
  348. hheap->hi_critsec.typObj = 0; /* 0 init crit sect obj type */ \
  349. InitializeCriticalSection( (LPCRITICAL_SECTION)(&(hheap->hi_critsec)) ); \
  350. hheap->hi_pcritsec = ((CRST_EXPORT *)(&(hheap->hi_critsec)))->crstInternal; \
  351. } else { \
  352. hheap->hi_pcritsec = &(hheap->hi_critsec); \
  353. InitCrst(hheap->hi_pcritsec); \
  354. }
  355. #endif
  356. /*
  357. * Exported heap functions
  358. */
  359. extern HHEAP INTERNAL HPInit(void *hheap, void *pmem, unsigned long cbreserve,
  360. unsigned long flags);
  361. extern void * INTERNAL HPAlloc(HHEAP hheap, unsigned long cb,
  362. unsigned long flags);
  363. extern void * INTERNAL HPReAlloc(HHEAP hheap, void *pblock, unsigned long cb,
  364. unsigned long flags);
  365. #ifndef WIN32
  366. extern unsigned INTERNAL HPFree(HHEAP hheap, void *lpMem);
  367. extern unsigned INTERNAL HPSize(HHEAP hheap, void *lpMem);
  368. extern HHEAP INTERNAL HPClone(struct heapinfo_s *hheap, struct heapinfo_s *pmem);
  369. #endif
  370. /*
  371. * Local heap functions
  372. */
  373. extern void INTERNAL hpFreeSub(HHEAP hheap, void *pblock, unsigned cb,
  374. unsigned flags);
  375. extern unsigned INTERNAL hpCommit(unsigned page, int npages, unsigned flags);
  376. extern unsigned INTERNAL hpCarve(HHEAP hheap, struct freeheap_s *pfh,
  377. unsigned cb, unsigned flags);
  378. #ifdef WIN32
  379. extern unsigned INTERNAL hpTakeSem(HHEAP hheap, void *pbh, unsigned flags);
  380. extern void INTERNAL hpClearSem(HHEAP hheap, unsigned flags);
  381. #else
  382. extern unsigned INTERNAL hpTakeSem2(HHEAP hheap, void *pbh);
  383. extern void INTERNAL hpClearSem2(HHEAP hheap);
  384. #endif
  385. /*
  386. * Debug functions
  387. */
  388. #ifdef HPDEBUG
  389. extern unsigned INTERNAL hpWalk(HHEAP hheap);
  390. extern char INTERNAL hpfWalk;
  391. extern char INTERNAL hpfTrashStop;
  392. extern char INTERNAL hpfParanoid;
  393. extern char mmfErrorStop;
  394. extern unsigned long INTERNAL hpGetAllocator(void);
  395. extern unsigned long INTERNAL hpSum(PVOID p, unsigned long cdw);
  396. #else
  397. #define hpWalk(hheap) 1
  398. #endif
  399. #ifdef WIN32
  400. #ifdef HPDEBUG
  401. #define DebugStop() { _asm int 3 }
  402. #define mmError(rc, string) vDebugOut(mmfErrorStop ? DEB_ERR : DEB_WARN, string);SetError(rc)
  403. #define mmWarn(rc, string) vDebugOut(DEB_WARN, string);SetError(rc)
  404. #define mmAssert(exp, psz) if (!(exp)) vDebugOut(DEB_ERR, psz)
  405. #else
  406. #define mmError(rc, string) SetError(rc)
  407. #define mmWarn(rc, string) SetError(rc)
  408. #define mmAssert(exp, psz)
  409. #endif
  410. #endif