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.
15 Implementation of heap memory management functions.
23 #include "pal/palinternal.h"
24 #include "pal/dbgmsg.h"
25 #include "pal/handlemgr.hpp"
26 #include "pal/corunix.hpp"
28 using namespace CorUnix;
30 SET_DEFAULT_DEBUG_CHANNEL(MEM);
32 // In safemath.h, Template SafeInt uses macro _ASSERTE, which need to use variable
33 // defdbgchan defined by SET_DEFAULT_DEBUG_CHANNEL. Therefore, the include statement
34 // should be placed after the SET_DEFAULT_DEBUG_CHANNEL(MEM)
38 #define DUMMY_HEAP 0x01020304
51 IN CONST VOID *Source,
54 PERF_ENTRY(RtlMoveMemory);
55 ENTRY("RtlMoveMemory(Destination:%p, Source:%p, Length:%d)\n",
56 Destination, Source, Length);
58 memmove(Destination, Source, Length);
60 LOGEXIT("RtlMoveMemory returning\n");
61 PERF_EXIT(RtlMoveMemory);
77 PERF_ENTRY(RtlZeroMemory);
78 ENTRY("RtlZeroMemory(Destination:%p, Length:%x)\n", Destination, Length);
80 memset(Destination, 0, Length);
82 LOGEXIT("RtlZeroMemory returning.\n");
83 PERF_EXIT(RtlZeroMemory);
96 IN SIZE_T dwInitialSize,
97 IN SIZE_T dwMaximumSize)
99 HANDLE ret = INVALID_HANDLE_VALUE;
100 PERF_ENTRY(HeapCreate);
101 ENTRY("HeapCreate(flOptions=%#x, dwInitialSize=%u, dwMaximumSize=%u)\n",
102 flOptions, dwInitialSize, dwMaximumSize);
104 if ((flOptions & 0x40005) != 0)
106 ERROR("Invalid flOptions\n");
107 SetLastError(ERROR_INVALID_PARAMETER);
109 else if (flOptions != 0)
111 ERROR("No support for flOptions\n");
112 SetLastError(ERROR_INVALID_PARAMETER);
114 else if (dwMaximumSize)
116 ERROR("Zone implementation does not support a max size\n");
117 SetLastError(ERROR_INVALID_PARAMETER);
121 ret = (HANDLE)malloc_create_zone(dwInitialSize, 0 /* flags */);
125 ret = (HANDLE)DUMMY_HEAP;
128 LOGEXIT("HeapCreate returning HANDLE %p\n", ret);
129 PERF_EXIT(HeapCreate);
147 PERF_ENTRY(GetProcessHeap);
148 ENTRY("GetProcessHeap()\n");
151 #if HEAP_HANDLES_ARE_REAL_HANDLES
154 malloc_zone_t *pZone = malloc_default_zone();
156 #endif // HEAP_HANDLES_ARE_REAL_HANDLES
158 ret = (HANDLE) DUMMY_HEAP;
161 LOGEXIT("GetProcessHeap returning HANDLE %p\n", ret);
162 PERF_EXIT(GetProcessHeap);
171 Implemented as wrapper over malloc
180 IN SIZE_T numberOfBytes)
184 PERF_ENTRY(HeapAlloc);
185 ENTRY("HeapAlloc (hHeap=%p, dwFlags=%#x, numberOfBytes=%u)\n",
186 hHeap, dwFlags, numberOfBytes);
191 if (hHeap != (HANDLE) DUMMY_HEAP)
192 #endif // __APPLE__ else
194 ERROR("Invalid heap handle\n");
195 SetLastError(ERROR_INVALID_PARAMETER);
196 LOGEXIT("HeapAlloc returning NULL\n");
197 PERF_EXIT(HeapAlloc);
201 if ((dwFlags != 0) && (dwFlags != HEAP_ZERO_MEMORY))
203 ASSERT("Invalid parameter dwFlags=%#x\n", dwFlags);
204 SetLastError(ERROR_INVALID_PARAMETER);
205 LOGEXIT("HeapAlloc returning NULL\n");
206 PERF_EXIT(HeapAlloc);
211 // This is patterned off of InternalMalloc in malloc.cpp.
213 pMem = (BYTE *)malloc_zone_malloc((malloc_zone_t *)hHeap, numberOfBytes);
216 pMem = (BYTE *) PAL_malloc(numberOfBytes);
217 #endif // __APPLE__ else
221 ERROR("Not enough memory\n");
222 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
223 LOGEXIT("HeapAlloc returning NULL\n");
224 PERF_EXIT(HeapAlloc);
228 /* If the HEAP_ZERO_MEMORY flag is set initialize to zero */
229 if (dwFlags == HEAP_ZERO_MEMORY)
231 memset(pMem, 0, numberOfBytes);
234 LOGEXIT("HeapAlloc returning LPVOID %p\n", pMem);
235 PERF_EXIT(HeapAlloc);
245 Implemented as wrapper over free
256 BOOL bRetVal = FALSE;
258 PERF_ENTRY(HeapFree);
259 ENTRY("HeapFree (hHeap=%p, dwFlags = %#x, lpMem=%p)\n",
260 hHeap, dwFlags, lpMem);
265 if (hHeap != (HANDLE) DUMMY_HEAP)
266 #endif // __APPLE__ else
268 ERROR("Invalid heap handle\n");
269 SetLastError(ERROR_INVALID_PARAMETER);
275 ASSERT("Invalid parameter dwFlags=%#x\n", dwFlags);
276 SetLastError(ERROR_INVALID_PARAMETER);
288 // This is patterned off of InternalFree in malloc.cpp.
290 malloc_zone_free((malloc_zone_t *)hHeap, lpMem);
294 #endif // __APPLE__ else
297 LOGEXIT( "HeapFree returning BOOL %d\n", bRetVal );
308 Implemented as wrapper over realloc
318 IN SIZE_T numberOfBytes)
322 PERF_ENTRY(HeapReAlloc);
323 ENTRY("HeapReAlloc (hHeap=%p, dwFlags=%#x, lpmem=%p, numberOfBytes=%u)\n",
324 hHeap, dwFlags, lpmem, numberOfBytes);
329 if (hHeap != (HANDLE)DUMMY_HEAP)
330 #endif // __APPLE__ else
332 ASSERT("Invalid heap handle\n");
333 SetLastError(ERROR_INVALID_HANDLE);
339 ASSERT("Invalid parameter dwFlags=%#x\n", dwFlags);
340 SetLastError(ERROR_INVALID_PARAMETER);
346 WARN("NULL memory pointer to realloc. Do not do anything.\n");
347 /* set LastError back to zero. this appears to be an undocumented
348 behavior in Windows, in doesn't cost much to match it */
353 if(numberOfBytes == 0)
355 // PAL's realloc behaves like free for a requested size of zero bytes. Force a nonzero size to get a valid pointer.
360 // This is patterned off of InternalRealloc in malloc.cpp.
362 pMem = (BYTE *) malloc_zone_realloc((malloc_zone_t *)hHeap, lpmem, numberOfBytes);
365 pMem = (BYTE *) PAL_realloc(lpmem, numberOfBytes);
366 #endif // __APPLE__ else
370 ERROR("Not enough memory\n");
371 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
376 LOGEXIT("HeapReAlloc returns LPVOID %p\n", pMem);
377 PERF_EXIT(HeapReAlloc);
384 IN OPTIONAL HANDLE HeapHandle,
385 IN HEAP_INFORMATION_CLASS HeapInformationClass,
386 IN PVOID HeapInformation,
387 IN SIZE_T HeapInformationLength)