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.

265 lines
5.5 KiB

  1. /*++
  2. Copyright (c) 1995-1998 Microsoft Corporation
  3. Module Name:
  4. epalloc.c
  5. Abstract:
  6. This module allocates memory for the entry point structures
  7. Author:
  8. 21-Aug-1995 Ori Gershony (t-orig)
  9. Revision History:
  10. 24-Aug-1999 [askhalid] copied from 32-bit wx86 directory and make work for 64bit.
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include "wx86.h"
  17. #include "cpuassrt.h"
  18. #include "config.h"
  19. #include "entrypt.h"
  20. ASSERTNAME;
  21. PVOID allocBase; // Base of the allocation unit
  22. PVOID commitLimit; // Top of commited memory
  23. PVOID allocLimit; // Top of memory allocated to the user
  24. #if DBG
  25. #define EPTRASHVALUE 0x0b
  26. #endif
  27. INT
  28. initEPAlloc(
  29. VOID
  30. )
  31. /*++
  32. Routine Description:
  33. Initializes the entry point memory allocator
  34. Arguments:
  35. none
  36. Return Value:
  37. return-value - non-zero for success, 0 for failure
  38. --*/
  39. {
  40. NTSTATUS Status;
  41. ULONGLONG ReserveSize = CpuEntryPointReserve;
  42. Status = NtAllocateVirtualMemory(NtCurrentProcess(),
  43. &allocBase,
  44. 0,
  45. &ReserveSize,
  46. MEM_RESERVE,
  47. PAGE_READWRITE
  48. );
  49. if (!NT_SUCCESS(Status)) {
  50. return 0;
  51. }
  52. // No memory is commited yet, nor is any allocated to the user
  53. allocLimit = commitLimit = allocBase;
  54. return (INT)(LONGLONG)allocBase;
  55. }
  56. VOID
  57. termEPAlloc(
  58. VOID
  59. )
  60. /*++
  61. Routine Description:
  62. Frees the memory used the the allocator. This should only be
  63. called before the process is terminated.
  64. Arguments:
  65. none
  66. Return Value:
  67. return-value - none
  68. --*/
  69. {
  70. ULONGLONG ReserveSize = CpuEntryPointReserve;
  71. NtFreeVirtualMemory(NtCurrentProcess(),
  72. &allocBase,
  73. &ReserveSize,
  74. MEM_RELEASE
  75. );
  76. }
  77. BOOLEAN
  78. commitMemory(
  79. LONG CommitDiff
  80. )
  81. /*++
  82. Routine Description:
  83. This routine tries to commit memory for use by the allocator. If there
  84. is no more memory left, is fails and returns with zero. Else it returns
  85. 1 for success. This is an internal function for use by the allocator
  86. only.
  87. Arguments:
  88. none
  89. Return Value:
  90. return-value - TRUE for success, FALSE for failure
  91. --*/
  92. {
  93. LONG CommitSize;
  94. DWORD i;
  95. LONGLONG TempCommitDiff = CommitDiff;
  96. for (i=0; i<CpuMaxAllocRetries; ++i) {
  97. NTSTATUS Status;
  98. LARGE_INTEGER Timeout;
  99. //
  100. // Try to allocate more memory
  101. //
  102. if ((LONG)(ULONGLONG)commitLimit + CommitDiff -(LONG)(ULONGLONG)allocBase > (LONG)(ULONGLONG)CpuEntryPointReserve) {
  103. //
  104. // The commit would extend pase the reserve. Fail the
  105. // alloc, which will cause a cache/entrypoint flush.
  106. //
  107. return FALSE;
  108. }
  109. Status = NtAllocateVirtualMemory(NtCurrentProcess(),
  110. &commitLimit,
  111. 0,
  112. &TempCommitDiff,
  113. MEM_COMMIT,
  114. PAGE_READWRITE
  115. );
  116. if (NT_SUCCESS(Status)) {
  117. //
  118. // Allocation succeeded. Move commitLimit up and return success
  119. //
  120. #if DBG
  121. RtlFillMemory(commitLimit, TempCommitDiff, EPTRASHVALUE);
  122. #endif
  123. commitLimit = (PVOID) ((ULONG)(ULONGLONG)commitLimit + TempCommitDiff);
  124. return TRUE;
  125. }
  126. //
  127. // No pages available. Sleep a bit and hope another thread frees a
  128. // page.
  129. //
  130. Timeout.QuadPart = (LONGLONG)CpuWaitForMemoryTime * -10000i64;
  131. NtDelayExecution(FALSE, &Timeout);
  132. }
  133. //
  134. // No pages available. Return failure. Caller will attempt to free
  135. // some pages and retry the EPAlloc call.
  136. return FALSE;
  137. }
  138. PVOID
  139. EPAlloc(
  140. DWORD cb
  141. )
  142. /*++
  143. Routine Description:
  144. This routine allocated memory for use by the entry point module.
  145. Arguments:
  146. cb - count of bytes to allocate from the entrypoint memory.
  147. Return Value:
  148. return-value - The memory allocated if succeeded, NULL otherwise
  149. --*/
  150. {
  151. PVOID newAllocLimit, oldAllocLimit;
  152. LONG CommitDiff;
  153. CPUASSERTMSG(allocLimit == commitLimit || *(PBYTE)allocLimit == EPTRASHVALUE, "Entrypoint memory overrun");
  154. // Calculate new allocation limit
  155. oldAllocLimit = allocLimit;
  156. newAllocLimit = (PVOID) ((ULONG)(ULONGLONG)oldAllocLimit + cb);
  157. // See if we need to commit more memory
  158. CommitDiff = (LONG)(ULONGLONG)newAllocLimit - (LONG)(ULONGLONG)commitLimit;
  159. if (CommitDiff > 0){
  160. // Yes we do, so try to commit more memory
  161. if (!commitMemory(CommitDiff)){
  162. // Cannot commit more memory, so return failure
  163. return NULL;
  164. }
  165. }
  166. allocLimit = newAllocLimit;
  167. return oldAllocLimit;
  168. }
  169. VOID
  170. EPFree(
  171. VOID
  172. )
  173. /*++
  174. Routine Description:
  175. This routine frees all entry point memory allocated so far
  176. Arguments:
  177. none
  178. Return Value:
  179. none
  180. --*/
  181. {
  182. #if DBG
  183. //
  184. // Fill the committed space with a known value to make
  185. // debugging easier
  186. //
  187. RtlFillMemory(allocBase, (ULONG)(ULONGLONG)allocLimit-(ULONG)(ULONGLONG)allocBase, EPTRASHVALUE);
  188. #endif
  189. allocLimit = allocBase;
  190. }