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.

461 lines
10 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1990 - 1999
  3. Module Name:
  4. memory.cxx
  5. Abstract:
  6. This file contains the new and delete routines for memory management in
  7. the Bits runtime. Rather than using the memory management provided by the
  8. C++ system we'll use the system allocator.
  9. Revision History:
  10. mikemon ??-??-?? Beginning of time (at least for this file).
  11. mikemon 12-31-90 Upgraded the comments.
  12. mariogo 04-24-96 Rewrite to unify platforms, behavior and performance.
  13. --*/
  14. #include <qmgrlib.h>
  15. #if !defined(BITS_V12_ON_NT4)
  16. #include <memory.tmh>
  17. #endif
  18. HANDLE hBitsHeap = 0;
  19. unsigned int DebugFlags = 0;
  20. #define NO_HEAP_SLOWDOWN
  21. ///////////////////////////////////////////////////////////////////////////
  22. //
  23. // Default allocators
  24. //
  25. ///////////////////////////////////////////////////////////////////////////
  26. #if !defined(DBG)
  27. void * _cdecl operator new(size_t nSize)
  28. {
  29. void *pNewMemory = HeapAlloc( hBitsHeap, 0, nSize );
  30. if ( !pNewMemory )
  31. {
  32. LogError( "Unable to allocate memory block of size, %X\n", nSize );
  33. throw ComError( E_OUTOFMEMORY );
  34. }
  35. return pNewMemory;
  36. }
  37. void _cdecl operator delete(void *pMemory)
  38. {
  39. if (!pMemory)
  40. return;
  41. if (!HeapFree( hBitsHeap, 0, pMemory ))
  42. {
  43. LogError( "Error occured freeing memory at %p, error %!winerr!\n",
  44. pMemory, GetLastError() );
  45. }
  46. }
  47. int fHeapInitialized = 0;
  48. int InitializeBitsAllocator(void)
  49. {
  50. #if 1
  51. if (0 == fHeapInitialized)
  52. {
  53. if (0 == hBitsHeap)
  54. {
  55. hBitsHeap = RtlCreateHeap( HEAP_GROWABLE
  56. | HEAP_FREE_CHECKING_ENABLED
  57. | HEAP_CLASS_1,
  58. 0,
  59. 16 * 1024 - 512,
  60. 0,
  61. 0,
  62. 0
  63. );
  64. }
  65. if (hBitsHeap)
  66. {
  67. fHeapInitialized = 1;
  68. }
  69. if (0 == fHeapInitialized )
  70. {
  71. return(ERROR_NOT_ENOUGH_MEMORY);
  72. }
  73. }
  74. return(0);
  75. #else
  76. hBitsHeap = RtlProcessHeap();
  77. return(0);
  78. #endif
  79. }
  80. int
  81. BitspCheckHeap (
  82. void
  83. )
  84. // Allow some checked compenents to be linked into a free memory.cxx.
  85. {
  86. return 0;
  87. }
  88. #else // ******************** DEBUG ********************
  89. #ifdef NO_HEAP_SLOWDOWN
  90. int fMemoryCheck = 0;
  91. #else
  92. int fMemoryCheck = 1;
  93. #endif
  94. int fHeapInitialized = 0;
  95. CRITICAL_SECTION BitsHeapLock;
  96. typedef NTSYSAPI
  97. USHORT
  98. (NTAPI RTLCAPTURESTACKBACKTRACE)(
  99. IN ULONG FramesToSkip,
  100. IN ULONG FramesToCapture,
  101. OUT PVOID *BackTrace,
  102. OUT PULONG BackTraceHash OPTIONAL
  103. );
  104. typedef RTLCAPTURESTACKBACKTRACE * PRTLCAPTURESTACKBACKTRACE;
  105. PRTLCAPTURESTACKBACKTRACE g_RtlCaptureStackBackTrace;
  106. int InitializeBitsAllocator(void)
  107. /*++
  108. Routine Description:
  109. Called during Bits initialization. This function must can by one
  110. thread at a time. Sets the heap handle for debugging.
  111. Maybe called more then once if this (or a later step) of Bits
  112. initialization fails.
  113. --*/
  114. {
  115. if (0 == fHeapInitialized)
  116. {
  117. if (0 == hBitsHeap)
  118. {
  119. hBitsHeap = RtlCreateHeap( HEAP_GROWABLE
  120. | HEAP_TAIL_CHECKING_ENABLED
  121. | HEAP_FREE_CHECKING_ENABLED
  122. | HEAP_CLASS_1,
  123. 0,
  124. 16 * 1024 - 512,
  125. 0,
  126. 0,
  127. 0
  128. );
  129. }
  130. if (hBitsHeap)
  131. {
  132. if (0 == RtlInitializeCriticalSection(&BitsHeapLock))
  133. {
  134. fHeapInitialized = 1;
  135. }
  136. }
  137. if (0 == fHeapInitialized )
  138. {
  139. return(ERROR_NOT_ENOUGH_MEMORY);
  140. }
  141. HMODULE hModule = GetModuleHandle( L"kernel32" );
  142. if (hModule)
  143. {
  144. g_RtlCaptureStackBackTrace = (PRTLCAPTURESTACKBACKTRACE) GetProcAddress( hModule, "RtlCaptureStackBacktrace" );
  145. // ignore error, because it's just a debugging aid and is not available in Win2000
  146. }
  147. }
  148. return(0);
  149. }
  150. #define Bits_GUARD 0xA1
  151. typedef struct _Bits_MEMORY_BLOCK
  152. {
  153. // First,forward and backward links to other Bits heap allocations.
  154. // These are first allow easy debugging with the dl command
  155. struct _Bits_MEMORY_BLOCK *next;
  156. struct _Bits_MEMORY_BLOCK *previous;
  157. // Specifies the size of the block of memory in bytes.
  158. unsigned long size;
  159. // Thread id of allocator
  160. unsigned long tid;
  161. void * AllocStackTrace[4];
  162. // (Pad to make header 0 mod 8) 0 when allocated, 0xF0F0F0F0 when freed.
  163. unsigned long free;
  164. // Reserve an extra 4 bytes as the front guard of each block.
  165. unsigned char frontguard[4];
  166. // Data will appear here. Note that the header must be 0 mod 8.
  167. // Reserve an extra 4 bytes as the rear guard of each block.
  168. unsigned char rearguard[4];
  169. } Bits_MEMORY_BLOCK;
  170. //
  171. // Compile-time test to ensure that Bits_MEMORY_BLOCK.rearguard is aligned on
  172. // natural boundary.
  173. //
  174. #if defined(_WIN64)
  175. C_ASSERT( (FIELD_OFFSET( Bits_MEMORY_BLOCK, rearguard ) % 16) == 0 );
  176. #else
  177. C_ASSERT( (FIELD_OFFSET( Bits_MEMORY_BLOCK, rearguard ) % 8) == 0 );
  178. #endif
  179. Bits_MEMORY_BLOCK * AllocatedBlocks = 0;
  180. unsigned long BlockCount = 0;
  181. int
  182. CheckMemoryBlock (
  183. Bits_MEMORY_BLOCK * block
  184. )
  185. {
  186. if ( block->frontguard[0] != Bits_GUARD
  187. || block->frontguard[1] != Bits_GUARD
  188. || block->frontguard[2] != Bits_GUARD
  189. || block->frontguard[3] != Bits_GUARD )
  190. {
  191. LogError("BAD BLOCK (front) @ %p\n", block);
  192. ASSERT(0);
  193. return(1);
  194. }
  195. if ( block->rearguard[block->size] != Bits_GUARD
  196. || block->rearguard[block->size+1] != Bits_GUARD
  197. || block->rearguard[block->size+2] != Bits_GUARD
  198. || block->rearguard[block->size+3] != Bits_GUARD )
  199. {
  200. LogError("BAD BLOCK (rear) @ %p (%p)\n",block, &block->rearguard[block->size]);
  201. ASSERT(0);
  202. return(1);
  203. }
  204. ASSERT(block->free == 0);
  205. if ( block->next != 0)
  206. {
  207. ASSERT(block->next->previous == block);
  208. }
  209. if ( block->previous != 0)
  210. {
  211. ASSERT(block->previous->next == block);
  212. }
  213. return(0);
  214. }
  215. int
  216. BitsValidateHeapList(
  217. void
  218. )
  219. // Called with BitsHeapLock held.
  220. {
  221. Bits_MEMORY_BLOCK * block;
  222. unsigned Blocks = 0;
  223. // Under stress this check causes performance to drop too much.
  224. // Compile with -DNO_HEAP_SLOWDOWN or ed the flag in memory
  225. // to speed things up.
  226. if (fMemoryCheck == 0)
  227. {
  228. return(0);
  229. }
  230. block = AllocatedBlocks;
  231. while (block != 0)
  232. {
  233. if (CheckMemoryBlock(block))
  234. {
  235. return(1);
  236. }
  237. block = block->next;
  238. Blocks++;
  239. }
  240. ASSERT(Blocks == BlockCount);
  241. return(0);
  242. }
  243. int
  244. BitspCheckHeap (
  245. void
  246. )
  247. // Returns 0 if the heap appears to be okay.
  248. {
  249. if (fMemoryCheck == 0)
  250. {
  251. return(0);
  252. }
  253. EnterCriticalSection(&BitsHeapLock);
  254. int ret = BitsValidateHeapList();
  255. LeaveCriticalSection(&BitsHeapLock);
  256. return(ret);
  257. }
  258. void * __cdecl
  259. operator new(
  260. size_t size
  261. )
  262. {
  263. Bits_MEMORY_BLOCK * block;
  264. EnterCriticalSection(&BitsHeapLock);
  265. ASSERT( ("You allocated a negative amount",
  266. size < (size + sizeof(Bits_MEMORY_BLOCK))) );
  267. BitsValidateHeapList();
  268. block = (Bits_MEMORY_BLOCK *) HeapAlloc( hBitsHeap, 0, size + sizeof(Bits_MEMORY_BLOCK));
  269. if ( block == 0 )
  270. {
  271. LeaveCriticalSection(&BitsHeapLock);
  272. LogError( "Unable to allocate memory block of size %X\n", size );
  273. throw ComError( E_OUTOFMEMORY );
  274. }
  275. block->size = size;
  276. block->tid = GetCurrentThreadId();
  277. block->free = 0;
  278. if (AllocatedBlocks != 0)
  279. AllocatedBlocks->previous = block;
  280. block->next = AllocatedBlocks;
  281. block->previous = 0;
  282. AllocatedBlocks = block;
  283. BlockCount++;
  284. block->frontguard[0] = Bits_GUARD;
  285. block->frontguard[1] = Bits_GUARD;
  286. block->frontguard[2] = Bits_GUARD;
  287. block->frontguard[3] = Bits_GUARD;
  288. #if i386
  289. if (g_RtlCaptureStackBackTrace)
  290. {
  291. ULONG ignore;
  292. g_RtlCaptureStackBackTrace(
  293. 2,
  294. 4,
  295. (void **) &block->AllocStackTrace,
  296. &ignore);
  297. }
  298. #endif
  299. block->rearguard[size] = Bits_GUARD;
  300. block->rearguard[size+1] = Bits_GUARD;
  301. block->rearguard[size+2] = Bits_GUARD;
  302. block->rearguard[size+3] = Bits_GUARD;
  303. LeaveCriticalSection(&BitsHeapLock);
  304. return(&(block->rearguard[0]));
  305. }
  306. void __cdecl
  307. operator delete (
  308. IN void * obj
  309. )
  310. {
  311. Bits_MEMORY_BLOCK * block;
  312. if (obj == 0)
  313. return;
  314. EnterCriticalSection(&BitsHeapLock);
  315. block = (Bits_MEMORY_BLOCK *) (((unsigned char *) obj)
  316. - FIELD_OFFSET(Bits_MEMORY_BLOCK, rearguard));
  317. // Validate block being freed.
  318. CheckMemoryBlock(block);
  319. if (block->next != 0)
  320. {
  321. CheckMemoryBlock(block->next);
  322. }
  323. if (block->previous != 0)
  324. {
  325. CheckMemoryBlock(block->previous);
  326. }
  327. // Remove the block from the list
  328. if (block == AllocatedBlocks)
  329. AllocatedBlocks = block->next;
  330. if (block->next != 0)
  331. block->next->previous = block->previous;
  332. if (block->previous != 0)
  333. block->previous->next = block->next;
  334. // Mark this block as free
  335. block->free = 0xF0F0F0F0;
  336. // Validate other Bits allocations.
  337. BlockCount-- ;
  338. BitsValidateHeapList();
  339. LeaveCriticalSection(&BitsHeapLock);
  340. if (!HeapFree( hBitsHeap, 0, block ))
  341. {
  342. LogError( "Error occured freeing memory at %p, error %!winerr!\n",
  343. block, GetLastError() );
  344. }
  345. }
  346. #endif // not debug