1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*++
6
7
8
9Module Name:
10
11 include/pal/virtual.h
12
13Abstract:
14 Header file for virtual memory management.
15
16
17
18--*/
19
20#ifndef _PAL_VIRTUAL_H_
21#define _PAL_VIRTUAL_H_
22
23#ifdef __cplusplus
24extern "C"
25{
26#endif // __cplusplus
27
28typedef struct _CMI {
29
30 struct _CMI * pNext; /* Link to the next entry. */
31 struct _CMI * pPrevious; /* Link to the previous entry. */
32
33 UINT_PTR startBoundary; /* Starting location of the region. */
34 SIZE_T memSize; /* Size of the entire region.. */
35
36 DWORD accessProtection; /* Initial allocation access protection. */
37 DWORD allocationType; /* Initial allocation type. */
38
39 BYTE * pAllocState; /* Individual allocation type tracking for each */
40 /* page in the region. */
41
42 BYTE * pProtectionState; /* Individual allocation type tracking for each */
43 /* page in the region. */
44
45} CMI, * PCMI;
46
47enum VIRTUAL_CONSTANTS
48{
49 /* Allocation type. */
50 VIRTUAL_COMMIT_ALL_BITS = 0xFF,
51 VIRTUAL_RESERVE_ALL_BITS = 0x0,
52
53 /* Protection Type. */
54 VIRTUAL_READONLY,
55 VIRTUAL_READWRITE,
56 VIRTUAL_EXECUTE_READWRITE,
57 VIRTUAL_NOACCESS,
58 VIRTUAL_EXECUTE,
59 VIRTUAL_EXECUTE_READ,
60
61 VIRTUAL_64KB = 0x10000
62};
63
64size_t GetVirtualPageSize();
65
66/*++
67Function :
68 VIRTUALInitialize
69
70 Initialize the critical sections.
71
72Return value:
73 TRUE if initialization succeeded
74 FALSE otherwise.
75--*/
76BOOL VIRTUALInitialize(bool initializeExecutableMemoryAllocator);
77
78/*++
79Function :
80 VIRTUALCleanup
81
82 Deletes the critical sections.
83
84--*/
85void VIRTUALCleanup( void );
86
87#ifdef __cplusplus
88}
89
90/*++
91Class:
92 ExecutableMemoryAllocator
93
94 This class implements a virtual memory allocator for JIT'ed code.
95 The purpose of this allocator is to opportunistically reserve a chunk of virtual memory
96 that is located near the coreclr library (within 2GB range) that can be later used by
97 JIT. Having executable memory close to the coreclr library allows JIT to generate more
98 efficient code (by avoiding usage of jump stubs) and thus it can significantly improve
99 performance of the application.
100
101 This allocator is integrated with the VirtualAlloc/Reserve code. If VirtualAlloc has been
102 called with the MEM_RESERVE_EXECUTABLE flag then it will first try to obtain the requested size
103 of virtual memory from ExecutableMemoryAllocator. If ExecutableMemoryAllocator runs out of
104 the reserved memory (or fails to allocate it during initialization) then VirtualAlloc/Reserve code
105 will simply fall back to reserving memory using OS APIs.
106
107 Notes:
108 - the memory allocated by this class is NOT committed by default. It is responsibility
109 of the caller to commit the virtual memory before accessing it.
110 - in addition, this class does not provide ability to free the reserved memory. The caller
111 has full control of the memory it got from this allocator (i.e. the caller becomes
112 the owner of the allocated memory), so it is caller's responsibility to free the memory
113 if it is no longer needed.
114--*/
115class ExecutableMemoryAllocator
116{
117public:
118 /*++
119 Function:
120 Initialize
121
122 This function initializes the allocator. It should be called early during process startup
123 (when process address space is pretty much empty) in order to have a chance to reserve
124 sufficient amount of memory that is close to the coreclr library.
125 --*/
126 void Initialize();
127
128 /*++
129 Function:
130 AllocateMemory
131
132 This function attempts to allocate the requested amount of memory from its reserved virtual
133 address space. The function will return null if the allocation request cannot
134 be satisfied by the memory that is currently available in the allocator.
135 --*/
136 void* AllocateMemory(SIZE_T allocationSize);
137
138 /*++
139 Function:
140 AllocateMemory
141
142 This function attempts to allocate the requested amount of memory from its reserved virtual
143 address space, if memory is available within the specified range. The function will return
144 null if the allocation request cannot satisfied by the memory that is currently available in
145 the allocator.
146 --*/
147 void *AllocateMemoryWithinRange(const void *beginAddress, const void *endAddress, SIZE_T allocationSize);
148
149private:
150 /*++
151 Function:
152 TryReserveInitialMemory
153
154 This function is called during initialization. It opportunistically tries to reserve
155 a large chunk of virtual memory that can be later used to store JIT'ed code.
156 --*/
157 void TryReserveInitialMemory();
158
159 /*++
160 Function:
161 GenerateRandomStartOffset
162
163 This function returns a random offset (in multiples of the virtual page size)
164 at which the allocator should start allocating memory from its reserved memory range.
165 --*/
166 int32_t GenerateRandomStartOffset();
167
168private:
169 // There does not seem to be an easy way find the size of a library on Unix.
170 // So this constant represents an approximation of the libcoreclr size (on debug build)
171 // that can be used to calculate an approximate location of the memory that
172 // is in 2GB range from the coreclr library. In addition, having precise size of libcoreclr
173 // is not necessary for the calculations.
174 static const int32_t CoreClrLibrarySize = 100 * 1024 * 1024;
175
176 // This constant represent the max size of the virtual memory that this allocator
177 // will try to reserve during initialization. We want all JIT-ed code and the
178 // entire libcoreclr to be located in a 2GB range.
179 static const int32_t MaxExecutableMemorySize = 0x7FFF0000;
180 static const int32_t MaxExecutableMemorySizeNearCoreClr = MaxExecutableMemorySize - CoreClrLibrarySize;
181
182 // Start address of the reserved virtual address space
183 void* m_startAddress;
184
185 // Next available address in the reserved address space
186 void* m_nextFreeAddress;
187
188 // Total size of the virtual memory that the allocator has been able to
189 // reserve during its initialization.
190 int32_t m_totalSizeOfReservedMemory;
191
192 // Remaining size of the reserved virtual memory that can be used to satisfy allocation requests.
193 int32_t m_remainingReservedMemory;
194};
195
196#endif // __cplusplus
197
198/*++
199Function :
200 ReserveMemoryFromExecutableAllocator
201
202 This function is used to reserve a region of virual memory (not commited)
203 that is located close to the coreclr library. The memory comes from the virtual
204 address range that is managed by ExecutableMemoryAllocator.
205--*/
206void* ReserveMemoryFromExecutableAllocator(CorUnix::CPalThread* pthrCurrent, SIZE_T allocationSize);
207
208#endif /* _PAL_VIRTUAL_H_ */
209
210
211
212
213
214
215
216