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.

280 lines
6.4 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. oscheap.c
  5. Abstract:
  6. This module contains "local" heap management code for OS Chooser.
  7. Author:
  8. Geoff Pease (gpease) May 28 1998
  9. Revision History:
  10. --*/
  11. #ifdef i386
  12. #include "bldrx86.h"
  13. #endif
  14. #if defined(_IA64_)
  15. #include "bldria64.h"
  16. #endif
  17. #include "netfs.h"
  18. #include "oscheap.h"
  19. #define FREE_POOL_TAG 0x0
  20. #define ALLOC_POOL_TAG 0x1
  21. typedef struct _LOCAL_MEMORY_DESCRIPTOR {
  22. //
  23. // We create a union to make sure that this struct is always at least the size of a
  24. // pointer, and thus will be pointer aligned.
  25. //
  26. union {
  27. struct {
  28. ULONG Tag;
  29. ULONG Size;
  30. };
  31. struct {
  32. void *Align;
  33. };
  34. };
  35. } LOCAL_MEMORY_DESCRIPTOR, *PLOCAL_MEMORY_DESCRIPTOR;
  36. //
  37. // Variable for holding our memory together.
  38. //
  39. #define OSCHEAPSIZE 0x2000 // 8k
  40. CHAR OscHeap[ OSCHEAPSIZE ];
  41. //
  42. // Functions
  43. //
  44. void
  45. OscHeapInitialize(
  46. VOID
  47. )
  48. /*++
  49. Routine Description:
  50. This routine initializes the internal memory management system.
  51. Arguments:
  52. None.
  53. Return Value:
  54. None.
  55. --*/
  56. {
  57. PLOCAL_MEMORY_DESCRIPTOR LocalDescriptor;
  58. LocalDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)OscHeap;
  59. LocalDescriptor->Tag = FREE_POOL_TAG;
  60. LocalDescriptor->Size = OSCHEAPSIZE - sizeof(LOCAL_MEMORY_DESCRIPTOR);
  61. memset((PVOID)(LocalDescriptor + 1), 0, LocalDescriptor->Size);
  62. }
  63. PCHAR
  64. OscHeapAlloc(
  65. IN UINT iSize
  66. )
  67. /*++
  68. Routine Description:
  69. This routine allocates memory from our internal structures.
  70. Arguments:
  71. iSize - Number of bytes the client wants.
  72. Return Value:
  73. A pointer to the allocated block if successful, else NULL
  74. --*/
  75. {
  76. PLOCAL_MEMORY_DESCRIPTOR LocalDescriptor;
  77. PLOCAL_MEMORY_DESCRIPTOR NextDescriptor;
  78. LONG ThisBlockSize;
  79. ULONG BytesToAllocate;
  80. //
  81. // Always allocate in increments of a pointer, minmally.
  82. //
  83. if (iSize & (sizeof(void *) - 1)) {
  84. iSize += sizeof(void *) - (iSize & (sizeof(void *) - 1));
  85. }
  86. LocalDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)OscHeap;
  87. ThisBlockSize = OSCHEAPSIZE - sizeof(LOCAL_MEMORY_DESCRIPTOR);
  88. while (ThisBlockSize > 0) {
  89. if ((LocalDescriptor->Tag == FREE_POOL_TAG) &&
  90. (LocalDescriptor->Size >= iSize)) {
  91. goto FoundBlock;
  92. }
  93. ThisBlockSize -= (LocalDescriptor->Size + sizeof(LOCAL_MEMORY_DESCRIPTOR));
  94. LocalDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)(((PUCHAR)LocalDescriptor) +
  95. LocalDescriptor->Size +
  96. sizeof(LOCAL_MEMORY_DESCRIPTOR)
  97. );
  98. }
  99. //
  100. // There is no memory block big enough to hold the request.
  101. //
  102. return NULL;
  103. FoundBlock:
  104. //
  105. // Jump to here when a memory descriptor of the right size has been found. It is expected that
  106. // LocalDescriptor points to the correct block.
  107. //
  108. if (LocalDescriptor->Size > iSize + sizeof(LOCAL_MEMORY_DESCRIPTOR)) {
  109. //
  110. // Make a descriptor of the left over parts of this block.
  111. //
  112. NextDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)(((PUCHAR)LocalDescriptor) +
  113. sizeof(LOCAL_MEMORY_DESCRIPTOR) +
  114. iSize
  115. );
  116. NextDescriptor->Tag = FREE_POOL_TAG;
  117. NextDescriptor->Size = (ULONG)(LocalDescriptor->Size - iSize - sizeof(LOCAL_MEMORY_DESCRIPTOR));
  118. LocalDescriptor->Size = (ULONG)iSize;
  119. }
  120. LocalDescriptor->Tag = ALLOC_POOL_TAG;
  121. memset((LocalDescriptor+1), 0, iSize);
  122. return (PCHAR)(LocalDescriptor + 1);
  123. }
  124. PCHAR
  125. OscHeapFree(
  126. IN PCHAR Pointer
  127. )
  128. /*++
  129. Routine Description:
  130. This routine frees a block previously allocated from the internal memory management system.
  131. Arguments:
  132. Pointer - A pointer to free.
  133. Return Value:
  134. NULL.
  135. --*/
  136. {
  137. LONG ThisBlockSize;
  138. PLOCAL_MEMORY_DESCRIPTOR LocalDescriptor;
  139. PLOCAL_MEMORY_DESCRIPTOR PrevDescriptor;
  140. PLOCAL_MEMORY_DESCRIPTOR ThisDescriptor;
  141. LocalDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)(((PUCHAR)Pointer) - sizeof(LOCAL_MEMORY_DESCRIPTOR));
  142. //
  143. // Find the memory block in the heap
  144. //
  145. PrevDescriptor = NULL;
  146. ThisDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)OscHeap;
  147. ThisBlockSize = OSCHEAPSIZE - sizeof(LOCAL_MEMORY_DESCRIPTOR);
  148. while (ThisBlockSize > 0) {
  149. if (ThisDescriptor == LocalDescriptor) {
  150. goto FoundBlock;
  151. }
  152. ThisBlockSize -= (ThisDescriptor->Size + sizeof(LOCAL_MEMORY_DESCRIPTOR));
  153. PrevDescriptor = ThisDescriptor;
  154. ThisDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)(((PUCHAR)ThisDescriptor) +
  155. ThisDescriptor->Size +
  156. sizeof(LOCAL_MEMORY_DESCRIPTOR)
  157. );
  158. }
  159. return NULL;
  160. FoundBlock:
  161. //
  162. // Jump to here when the proper memory descriptor has been found.
  163. //
  164. if (LocalDescriptor->Tag == FREE_POOL_TAG) {
  165. //
  166. // Ouch! We tried to free something twice, skip it before bad things happen.
  167. //
  168. return NULL;
  169. }
  170. LocalDescriptor->Tag = FREE_POOL_TAG;
  171. //
  172. // If possible, merge this memory block with the next one.
  173. //
  174. if ((ULONG)ThisBlockSize > (LocalDescriptor->Size + sizeof(LOCAL_MEMORY_DESCRIPTOR))) {
  175. ThisDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)(((PUCHAR)LocalDescriptor) +
  176. LocalDescriptor->Size +
  177. sizeof(LOCAL_MEMORY_DESCRIPTOR)
  178. );
  179. if (ThisDescriptor->Tag == FREE_POOL_TAG) {
  180. LocalDescriptor->Size += ThisDescriptor->Size + sizeof(LOCAL_MEMORY_DESCRIPTOR);
  181. ThisDescriptor->Tag = 0;
  182. ThisDescriptor->Size = 0;
  183. }
  184. }
  185. //
  186. // Now see if we can merge this block with a previous block.
  187. //
  188. if ((PrevDescriptor != NULL) && (PrevDescriptor->Tag == FREE_POOL_TAG)) {
  189. PrevDescriptor->Size += LocalDescriptor->Size + sizeof(LOCAL_MEMORY_DESCRIPTOR);
  190. LocalDescriptor->Tag = 0;
  191. LocalDescriptor->Size = 0;
  192. }
  193. return NULL;
  194. }