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.

277 lines
6.3 KiB

  1. /*++
  2. Copyright (C) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. NEWNEW.CPP
  5. Abstract:
  6. CReuseMemoryManager
  7. History:
  8. --*/
  9. #include "precomp.h"
  10. #include <wbemcomn.h>
  11. #include <sync.h>
  12. #include "newnew.h"
  13. const int constMinAllocationSize = 4096;
  14. const int constMaxAllocationSize = 1024 * 1024;
  15. const double constNextAllocationFactor = 2.0;
  16. void CTempMemoryManager::CAllocation::Init(size_t dwAllocationSize)
  17. {
  18. m_dwAllocationSize = dwAllocationSize;
  19. m_dwUsed = 0;
  20. m_dwFirstFree = GetHeaderSize();
  21. }
  22. void* CTempMemoryManager::CAllocation::Alloc(size_t nBlockSize)
  23. {
  24. if(m_dwFirstFree + nBlockSize <= m_dwAllocationSize)
  25. {
  26. m_dwUsed += nBlockSize;
  27. void* p = ((byte*)this) + m_dwFirstFree;
  28. m_dwFirstFree += nBlockSize;
  29. return p;
  30. }
  31. else
  32. return NULL;
  33. }
  34. bool CTempMemoryManager::CAllocation::Contains(void* p)
  35. {
  36. return (p > this && p <= GetEnd());
  37. }
  38. void CTempMemoryManager::CAllocation::Destroy()
  39. {
  40. VirtualFree(this, 0, MEM_RELEASE);
  41. }
  42. bool CTempMemoryManager::CAllocation::Free(size_t nBlockSize)
  43. {
  44. m_dwUsed -= nBlockSize;
  45. if(m_dwUsed== 0)
  46. {
  47. m_dwFirstFree = GetHeaderSize();
  48. return true;
  49. }
  50. else
  51. return false;
  52. }
  53. void* CTempMemoryManager::Allocate(size_t nBlockSize)
  54. {
  55. //
  56. // Add the space for the length of the block
  57. //
  58. nBlockSize += DEF_ALIGNED(sizeof(DWORD));
  59. nBlockSize = RoundUp(nBlockSize);
  60. CInCritSec ics(&m_cs);
  61. //
  62. // Check if the last allocation has room
  63. //
  64. int nAllocations = m_pAllocations->GetSize();
  65. CAllocation* pLast = NULL;
  66. if(nAllocations)
  67. {
  68. pLast = (*m_pAllocations)[nAllocations-1];
  69. void* p = pLast->Alloc(nBlockSize);
  70. if(p)
  71. {
  72. *(DWORD*)p = nBlockSize;
  73. m_dwTotalUsed += nBlockSize;
  74. m_dwNumAllocations++;
  75. return ((BYTE*)p) + DEF_ALIGNED(sizeof(DWORD));
  76. }
  77. else if(pLast->GetUsedSize() == 0)
  78. {
  79. //
  80. // The last allocation record is actually empty --- we don't want
  81. // to leave it there, as it will just dangle
  82. //
  83. m_dwTotalAllocated -= pLast->GetAllocationSize();
  84. pLast->Destroy();
  85. (*m_pAllocations).RemoveAt(nAllocations-1);
  86. }
  87. }
  88. //
  89. // No room: need a new allocation. The size shall be double the previous
  90. // size, or 1M if too large
  91. //
  92. size_t dwAllocationSize = 0;
  93. if(nAllocations == 0)
  94. {
  95. //
  96. // First time: constant size
  97. //
  98. dwAllocationSize = constMinAllocationSize;
  99. }
  100. else
  101. {
  102. //
  103. // Not first time: allocation constant factor of the total, but not
  104. // larger that a constant.
  105. //
  106. dwAllocationSize = m_dwTotalUsed * constNextAllocationFactor;
  107. if(dwAllocationSize > constMaxAllocationSize)
  108. dwAllocationSize = constMaxAllocationSize;
  109. if(dwAllocationSize < constMinAllocationSize)
  110. dwAllocationSize = constMinAllocationSize;
  111. }
  112. if(dwAllocationSize < CAllocation::GetMinAllocationSize(nBlockSize))
  113. {
  114. dwAllocationSize = CAllocation::GetMinAllocationSize(nBlockSize);
  115. }
  116. //
  117. // VirtualAlloc it and read back the actual size of the allocation
  118. //
  119. CAllocation* pAlloc = (CAllocation*)
  120. VirtualAlloc(NULL, dwAllocationSize, MEM_COMMIT, PAGE_READWRITE);
  121. if(pAlloc == NULL)
  122. return NULL;
  123. MEMORY_BASIC_INFORMATION info;
  124. VirtualQuery(pAlloc, &info, sizeof(MEMORY_BASIC_INFORMATION));
  125. //
  126. // Initialize it, and add it to the list of allocations
  127. //
  128. pAlloc->Init(info.RegionSize);
  129. m_pAllocations->Add(pAlloc);
  130. m_dwTotalAllocated += dwAllocationSize;
  131. m_dwNumAllocations++;
  132. m_dwNumMisses++;
  133. //
  134. // Allocation memory from it
  135. //
  136. void* p = pAlloc->Alloc(nBlockSize);
  137. if(p)
  138. {
  139. *(DWORD*)p = nBlockSize;
  140. m_dwTotalUsed += nBlockSize;
  141. return ((BYTE*)p) + DEF_ALIGNED(sizeof(DWORD));
  142. }
  143. else
  144. return NULL;
  145. }
  146. void CTempMemoryManager::Free(void* p, size_t nBlockSize)
  147. {
  148. if (p == NULL)
  149. return;
  150. CInCritSec ics(&m_cs);
  151. //
  152. // Figure out the size of the allocation
  153. //
  154. nBlockSize = *(DWORD*)((BYTE*)p - DEF_ALIGNED(sizeof(DWORD)));
  155. //
  156. // Search for it in the allocations
  157. //
  158. for(int i = 0; i < m_pAllocations->GetSize(); i++)
  159. {
  160. CAllocation* pAlloc = (*m_pAllocations)[i];
  161. if(pAlloc->Contains(p))
  162. {
  163. //
  164. // Found it. Remove and deallocate block if last. Except that we
  165. // do not want to deallocate the last minimal block --- otherwise
  166. // small allocations will just keep VirtualAllocing all the time
  167. //
  168. m_dwTotalUsed -= nBlockSize;
  169. bool bLastInAlloc = pAlloc->Free(nBlockSize);
  170. if(!bLastInAlloc)
  171. return;
  172. bool bDestroy = false;
  173. if(m_pAllocations->GetSize() != i+1)
  174. {
  175. //
  176. // This is not the last record. Destroy it
  177. //
  178. bDestroy = true;
  179. }
  180. else
  181. {
  182. //
  183. // This is the last record. Do more tests
  184. //
  185. if(m_pAllocations->GetSize() > 1)
  186. bDestroy = true;
  187. else if((*m_pAllocations)[0]->GetAllocationSize() !=
  188. constMinAllocationSize)
  189. bDestroy = true;
  190. }
  191. if(bDestroy)
  192. {
  193. m_dwTotalAllocated -= pAlloc->GetAllocationSize();
  194. pAlloc->Destroy();
  195. (*m_pAllocations).RemoveAt(i);
  196. }
  197. return;
  198. }
  199. }
  200. //
  201. // Bad news: freeing something we don't own!
  202. //
  203. return;
  204. }
  205. void CTempMemoryManager::Clear()
  206. {
  207. for(int i = 0; i < m_pAllocations->GetSize(); i++)
  208. {
  209. CAllocation* pAlloc = (*m_pAllocations)[i];
  210. pAlloc->Destroy();
  211. }
  212. m_pAllocations->RemoveAll();
  213. }
  214. CTempMemoryManager::CTempMemoryManager() :
  215. m_dwTotalUsed(0), m_dwTotalAllocated(0), m_dwNumAllocations(0),
  216. m_dwNumMisses(0), m_pAllocations(NULL)
  217. {
  218. m_pAllocations = new CPointerArray<CAllocation>;
  219. }
  220. CTempMemoryManager::~CTempMemoryManager()
  221. {
  222. Clear();
  223. delete m_pAllocations;
  224. }