Leaked source code of windows server 2003
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.

236 lines
7.0 KiB

  1. /***
  2. *chsyheap.cpp - RTC support
  3. *
  4. * Copyright (c) 1998-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *
  7. *Revision History:
  8. * 07-28-98 JWM Module incorporated into CRTs (from KFrei)
  9. * 05-11-99 KBF Error if RTC support define not enabled
  10. * 05-25-99 KBF Renamed - _RTC_SimpleHeap instead of CheesyHeap
  11. * 05-26-99 KBF Removed RTCl and RTCv, added _RTC_ADVMEM stuff
  12. *
  13. ****/
  14. #ifndef _RTC
  15. #error RunTime Check support not enabled!
  16. #endif
  17. #include "rtcpriv.h"
  18. #ifdef _RTC_ADVMEM
  19. // This is my 'Cheesy Heap' implementation...
  20. /* Here are the sizes that I need:
  21. BinaryNode 3 DWORDS - use heap4
  22. BinaryTree 1 DWORD - use heap2
  23. Container 2 DWORDS - use heap2
  24. BreakPoint 2 DWORDS - use heap2
  25. HashTable<HeapBlock> 2 DWORDS - use heap2
  26. HeapBlock 6 DWORDS - use heap8
  27. Container[] - short term...
  28. CallSite[] - permanent
  29. HeapBlock[] - permanent
  30. */
  31. _RTC_SimpleHeap *_RTC_heap2 = 0;
  32. _RTC_SimpleHeap *_RTC_heap4 = 0;
  33. _RTC_SimpleHeap *_RTC_heap8 = 0;
  34. void *
  35. _RTC_SimpleHeap::operator new(unsigned) throw()
  36. {
  37. void *res = VirtualAlloc(NULL, ALLOC_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  38. #ifdef _RTC_SHADOW
  39. if (shadow)
  40. _RTC_MSCommitRange((memptr)res, ALLOC_SIZE, IDX_STATE_ILLEGAL);
  41. #endif
  42. return res;
  43. }
  44. void
  45. _RTC_SimpleHeap::operator delete(void *addr) throw()
  46. {
  47. VirtualFree(addr, 0, MEM_RELEASE);
  48. #ifdef _RTC_SHADOW
  49. if (shadow)
  50. _RTC_MSDecommitRange((memptr)addr, ALLOC_SIZE);
  51. #endif
  52. }
  53. _RTC_SimpleHeap::_RTC_SimpleHeap(unsigned blockSize) throw()
  54. {
  55. // Flag it as the only item in the heap
  56. head.next = 0;
  57. head.inf.top.nxtFree = 0;
  58. // Align the block size
  59. head.inf.top.wordSize = 8;
  60. blockSize = (blockSize - 1) >> 3;
  61. while (blockSize) {
  62. blockSize >>= 1;
  63. head.inf.top.wordSize <<= 1;
  64. }
  65. // Build up the free-list
  66. head.free = (FreeList*)(((unsigned)&head) +
  67. ((head.inf.top.wordSize < sizeof(HeapNode)) ?
  68. sizeof(HeapNode) :
  69. head.inf.top.wordSize));
  70. FreeList *t = head.free;
  71. while (((unsigned)t) + head.inf.top.wordSize < ((unsigned)&head) + ALLOC_SIZE)
  72. {
  73. t->next = (FreeList*)(((unsigned)t) + head.inf.top.wordSize);
  74. t = t->next;
  75. }
  76. t->next = 0;
  77. }
  78. _RTC_SimpleHeap::~_RTC_SimpleHeap() throw()
  79. {
  80. // Free all sections that we have allocated
  81. HeapNode *n, *c = head.next;
  82. while(c) {
  83. n = c->next;
  84. _RTC_SimpleHeap::operator delete(c);
  85. c = n;
  86. }
  87. // the 'head' page will be handled by delete
  88. }
  89. void *
  90. _RTC_SimpleHeap::alloc() throw()
  91. {
  92. void *res;
  93. // If there's a free item, remove it from the list
  94. // And decrement the free count for it's parent page
  95. if (head.free)
  96. {
  97. // There's a free block on the first page
  98. res = head.free;
  99. head.free = head.free->next;
  100. // Since it's on the top page, there's no free-count to update,
  101. // And it ain't on no stinkin' free-list
  102. } else if (head.inf.top.nxtFree)
  103. {
  104. // There's a free block on some page
  105. HeapNode *n = head.inf.top.nxtFree;
  106. res = n->free;
  107. n->free = n->free->next;
  108. n->inf.nontop.freeCount--;
  109. if (!n->free)
  110. {
  111. // This page is now full, so it must be removed from the freelist
  112. for (n = head.next; n && !n->free; n = n->next) {}
  113. // Now the nxtFree pointer is either null (indicating a full heap)
  114. // or it's pointing to a page that has free nodes
  115. head.inf.top.nxtFree = n;
  116. }
  117. } else
  118. {
  119. // No pages have any free blocks
  120. // Get a new page, and add it to the list
  121. HeapNode *n = (HeapNode *)_RTC_SimpleHeap::operator new(0);
  122. // Count the number of free nodes
  123. n->inf.nontop.freeCount =
  124. (ALLOC_SIZE - sizeof(HeapNode)) / head.inf.top.wordSize - 1;
  125. res = (void *)(((unsigned)n) +
  126. ((head.inf.top.wordSize < sizeof(HeapNode)) ?
  127. sizeof(HeapNode) :
  128. head.inf.top.wordSize));
  129. // Build the free-list for this node
  130. FreeList *f;
  131. for (f = n->free = (FreeList*)(((unsigned)res) + head.inf.top.wordSize);
  132. ((unsigned)f) + head.inf.top.wordSize < ((unsigned)n) + ALLOC_SIZE;
  133. f = f->next)
  134. f->next = (FreeList*)(((unsigned)f) + head.inf.top.wordSize);
  135. f->next = 0;
  136. // Stick it in the page list
  137. n->next = head.next;
  138. n->inf.nontop.prev = &head;
  139. head.next = n;
  140. // Flag this as a page with free stuff on it...
  141. head.inf.top.nxtFree = n;
  142. }
  143. return res;
  144. }
  145. void
  146. _RTC_SimpleHeap::free(void *addr) throw()
  147. {
  148. // Get the heap node for this address
  149. HeapNode *n = (HeapNode *)(((unsigned)addr) & ~(ALLOC_SIZE - 1));
  150. // Stick this sucker back in the free list
  151. FreeList *f = (FreeList *)addr;
  152. f->next = n->free;
  153. n->free = f;
  154. if (n == &head)
  155. // If this is in the head node, just return...
  156. return;
  157. if (++n->inf.nontop.freeCount ==
  158. (ALLOC_SIZE - sizeof(HeapNode)) / head.inf.top.wordSize)
  159. {
  160. // This page is free
  161. if (head.inf.top.freePage)
  162. {
  163. // There's already another free page, go ahead and free this one
  164. // (there's always a previous node)
  165. n->inf.nontop.prev->next = n->next;
  166. if (n->next)
  167. n->next->inf.nontop.prev = n->inf.nontop.prev;
  168. _RTC_SimpleHeap::operator delete(n);
  169. if (head.inf.top.nxtFree == n)
  170. {
  171. // This was the free page
  172. // find a page with some free nodes on it...
  173. for (n = head.next; !n->free; n = n->next) {}
  174. // ASSERT(n)
  175. // If n is null, we're in some serious trouble...
  176. head.inf.top.nxtFree = n;
  177. }
  178. // If it wasn't the free page, we're just fine...
  179. } else
  180. {
  181. // flag the freePages to say we have a 100% free page
  182. head.inf.top.freePage = true;
  183. if (head.inf.top.nxtFree == n)
  184. {
  185. // If this is the free page,
  186. // try to find another page with some free nodes
  187. HeapNode *t;
  188. for (t = head.next; t && (!t->free || t == n) ; t = t->next) {}
  189. // if there was a different page with some nodes, pick it
  190. head.inf.top.nxtFree = t ? t : n;
  191. }
  192. }
  193. } else
  194. // This page isn't empty, so just set it as the next free
  195. head.inf.top.nxtFree = n;
  196. }
  197. #endif // _RTC_ADVMEM