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.

232 lines
8.0 KiB

  1. /***
  2. *expand.c - Win32 expand heap routine
  3. *
  4. * Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *Revision History:
  9. * 01-15-92 JCR Module created.
  10. * 02-04-92 GJF Replaced windows.h with oscalls.h.
  11. * 05-06-92 DJM ifndef out of POSIX build.
  12. * 09-23-92 SRW Change winheap code to call NT directly always
  13. * 10-15-92 SKS Removed the ill-named HEAP_GROWTH_ALLOWED flag
  14. * which was causing a bug: _expand was behaving like
  15. * realloc(), by moving the block when it could not be
  16. * grown in place. _expand() must NEVER move the block.
  17. * Also added a safety check to work around a bug in
  18. * HeapReAlloc, where it returns success even
  19. * when it fails to grow the block in place.
  20. * 10-28-92 SRW Change winheap code to call Heap????Ex calls
  21. * 11-05-92 SKS Change name of variable "CrtHeap" to "_crtheap"
  22. * 11-07-92 SRW _NTIDW340 replaced by linkopts\betacmp.c
  23. * 11-16-92 SRW Heap???Ex functions renamed to Heap???
  24. * 10-21-93 GJF Replace _CALLTYPE1 with _cdecl. Cleaned up format.
  25. * 04-06-95 GJF Added support for debug heap.
  26. * 04-29-95 GJF Copied over from winheap and made conditional on
  27. * WINHEAP.
  28. * 05-22-95 GJF Test against _HEAP_MAXREQ before calling API. Also,
  29. * removed workaround for long-ago NT problem.
  30. * 05-24-95 CFW Official ANSI C++ new handler added.
  31. * 05-23-95 GJF Really removed workaround this time...
  32. * 03-04-96 GJF Added support for small-block heap. Moved heaphook
  33. * invocation to the very start of the function.
  34. * 04-10-96 GJF Return type of __sbh_find_block and __sbh_resize_block
  35. * changed to __map_t *.
  36. * 05-30-96 GJF Minor changes for latest version of small-block heap.
  37. * 05-22-97 RDK New small-block heap scheme implemented.
  38. * 09-26-97 BWT Fix POSIX
  39. * 11-05-97 GJF Small POSIX fix from Roger Lanser.
  40. * 12-17-97 GJF Exception-safe locking.
  41. * 07-28-98 JWM RTC update.
  42. * 09-29-98 GJF Bypass all small-block heap code when __sbh_initialized
  43. * is 0.
  44. * 11-16-98 GJF Merged in VC++ 5.0 version of small-block heap.
  45. * 12-02-98 GJF One too many munlocks!
  46. * 12-18-98 GJF Changes for 64-bit size_t.
  47. * 05-01-99 PML Disable small-block heap for Win64.
  48. * 05-26-99 KBF Updated RTC hook func params
  49. * 06-21-99 GJF Removed old small-block heap from static libs.
  50. * 08-04-00 PML Don't round allocation sizes when using system
  51. * heap (VS7#131005).
  52. *
  53. *******************************************************************************/
  54. #ifdef WINHEAP
  55. #include <cruntime.h>
  56. #include <malloc.h>
  57. #include <winheap.h>
  58. #include <windows.h>
  59. #include <mtdll.h>
  60. #include <dbgint.h>
  61. #include <rtcsup.h>
  62. /***
  63. *void *_expand(void *pblck, size_t newsize) - expand/contract a block of memory
  64. * in the heap
  65. *
  66. *Purpose:
  67. * Resizes a block in the heap to newsize bytes. newsize may be either
  68. * greater (expansion) or less (contraction) than the original size of
  69. * the block. The block is NOT moved.
  70. *
  71. * NOTES:
  72. *
  73. * (1) In this implementation, if the block cannot be grown to the
  74. * desired size, the resulting block will NOT be grown to the max
  75. * possible size. (That is, either it works or it doesn't.)
  76. *
  77. * (2) Unlike other implementations, you can NOT pass a previously
  78. * freed block to this routine and expect it to work.
  79. *
  80. *Entry:
  81. * void *pblck - pointer to block in the heap previously allocated
  82. * by a call to malloc(), realloc() or _expand().
  83. *
  84. * size_t newsize - requested size for the resized block
  85. *
  86. *Exit:
  87. * Success: Pointer to the resized memory block (i.e., pblck)
  88. * Failure: NULL
  89. *
  90. *Uses:
  91. *
  92. *Exceptions:
  93. * If pblck does not point to a valid allocation block in the heap,
  94. * _expand() will behave unpredictably and probably corrupt the heap.
  95. *
  96. *******************************************************************************/
  97. void * __cdecl _expand_base (void * pBlock, size_t newsize)
  98. {
  99. #ifdef _POSIX_
  100. return (HeapReAlloc( _crtheap,
  101. HEAP_REALLOC_IN_PLACE_ONLY,
  102. pBlock,
  103. (DWORD)newsize ));
  104. #else
  105. void * pvReturn;
  106. #ifdef HEAPHOOK
  107. /* call heap hook if installed */
  108. if (_heaphook)
  109. {
  110. void * pvReturn;
  111. if ((*_heaphook)(_HEAP_EXPAND, newsize, pBlock, (void *)&pvReturn))
  112. return pvReturn;
  113. }
  114. #endif /* HEAPHOOK */
  115. /* validate size */
  116. if ( newsize > _HEAP_MAXREQ )
  117. return NULL;
  118. #ifndef _WIN64
  119. if ( __active_heap == __V6_HEAP )
  120. {
  121. PHEADER pHeader;
  122. #ifdef _MT
  123. _mlock( _HEAP_LOCK );
  124. __try {
  125. #endif
  126. // if allocation block lies within the small-block heap,
  127. // try to resize it there
  128. if ((pHeader = __sbh_find_block(pBlock)) != NULL)
  129. {
  130. pvReturn = NULL;
  131. if ( (newsize <= __sbh_threshold) &&
  132. __sbh_resize_block(pHeader, pBlock, (int)newsize) )
  133. pvReturn = pBlock;
  134. }
  135. #ifdef _MT
  136. }
  137. __finally {
  138. _munlock( _HEAP_LOCK );
  139. }
  140. #endif
  141. if ( pHeader == NULL )
  142. {
  143. // force nonzero size and round up to next paragraph
  144. if (newsize == 0)
  145. newsize = 1;
  146. newsize = (newsize + BYTES_PER_PARA - 1) & ~(BYTES_PER_PARA - 1);
  147. pvReturn = HeapReAlloc(_crtheap, HEAP_REALLOC_IN_PLACE_ONLY,
  148. pBlock, newsize);
  149. }
  150. }
  151. #ifdef CRTDLL
  152. else if ( __active_heap == __V5_HEAP )
  153. {
  154. __old_sbh_region_t *preg;
  155. __old_sbh_page_t * ppage;
  156. __old_page_map_t * pmap;
  157. // force nonzero size and round up to next paragraph
  158. if (newsize == 0)
  159. newsize = 1;
  160. newsize = (newsize + _OLD_PARASIZE - 1) & ~(_OLD_PARASIZE - 1);
  161. #ifdef _MT
  162. _mlock(_HEAP_LOCK);
  163. __try {
  164. #endif
  165. pmap = __old_sbh_find_block(pBlock, &preg, &ppage);
  166. // allocation block lies within the small-block heap, try to resize
  167. // it there.
  168. if ( pmap != NULL )
  169. {
  170. // *pBlock lies within the small-block heap, try to resize it
  171. // there
  172. pvReturn = NULL;
  173. if ( (newsize <= __old_sbh_threshold) &&
  174. __old_sbh_resize_block(preg, ppage, pmap,
  175. newsize >> _OLD_PARASHIFT) )
  176. pvReturn = pBlock;
  177. RTCCALLBACK(_RTC_Free_hook, (pBlock, 0));
  178. RTCCALLBACK(_RTC_Allocate_hook, (pvReturn, newsize, 0));
  179. return pvReturn;
  180. }
  181. #ifdef _MT
  182. }
  183. __finally {
  184. _munlock(_HEAP_LOCK);
  185. }
  186. #endif
  187. if ( pmap == NULL )
  188. pvReturn = HeapReAlloc(_crtheap, HEAP_REALLOC_IN_PLACE_ONLY,
  189. pBlock, newsize);
  190. }
  191. #endif /* CRTDLL */
  192. else // __active_heap == __SYSTEM_HEAP
  193. #endif /* ndef _WIN64 */
  194. {
  195. // force nonzero size
  196. if (newsize == 0)
  197. newsize = 1;
  198. pvReturn = HeapReAlloc(_crtheap, HEAP_REALLOC_IN_PLACE_ONLY,
  199. pBlock, newsize);
  200. }
  201. if (pvReturn)
  202. {
  203. RTCCALLBACK(_RTC_Free_hook, (pBlock, 0));
  204. RTCCALLBACK(_RTC_Allocate_hook, (pvReturn, newsize, 0));
  205. }
  206. return pvReturn;
  207. #endif /* _POSIX_ */
  208. }
  209. #endif /* WINHEAP */