diff options
Diffstat (limited to 'src/pal/src/map/virtual.cpp')
-rw-r--r-- | src/pal/src/map/virtual.cpp | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/src/pal/src/map/virtual.cpp b/src/pal/src/map/virtual.cpp index 4a55de9891..7e00843b7a 100644 --- a/src/pal/src/map/virtual.cpp +++ b/src/pal/src/map/virtual.cpp @@ -92,6 +92,7 @@ namespace VirtualMemoryLogging Commit = 0x30, Decommit = 0x40, Release = 0x50, + Reset = 0x60, }; // Indicates that the attempted operation has failed @@ -810,6 +811,58 @@ static BOOL VIRTUALStoreAllocationInfo( /****** * + * VIRTUALResetMemory() - Helper function that resets the memory + * + * + */ +static LPVOID VIRTUALResetMemory( + IN CPalThread *pthrCurrent, /* Currently executing thread */ + IN LPVOID lpAddress, /* Region to reserve or commit */ + IN SIZE_T dwSize) /* Size of Region */ +{ + LPVOID pRetVal = NULL; + UINT_PTR StartBoundary; + SIZE_T MemSize; + + TRACE( "Resetting the memory now..\n"); + + StartBoundary = (UINT_PTR)lpAddress & ~VIRTUAL_PAGE_MASK; + // Add the sizes, and round down to the nearest page boundary. + MemSize = ( ((UINT_PTR)lpAddress + dwSize + VIRTUAL_PAGE_MASK) & ~VIRTUAL_PAGE_MASK ) - + StartBoundary; + + int st; +#if HAVE_MADV_FREE + // Try to use MADV_FREE if supported. It tells the kernel that the application doesn't + // need the pages in the range. Freeing the pages can be delayed until a memory pressure + // occurs. + st = madvise((LPVOID)StartBoundary, MemSize, MADV_FREE); + if (st != 0) +#endif + { + // In case the MADV_FREE is not supported, use MADV_DONTNEED + st = madvise((LPVOID)StartBoundary, MemSize, MADV_DONTNEED); + } + + if (st == 0) + { + pRetVal = lpAddress; + } + + LogVaOperation( + VirtualMemoryLogging::VirtualOperation::Reset, + lpAddress, + dwSize, + 0, + 0, + pRetVal, + pRetVal != NULL); + + return pRetVal; +} + +/****** + * * VIRTUALReserveMemory() - Helper function that actually reserves the memory. * * NOTE: I call SetLastError in here, because many different error states @@ -837,8 +890,6 @@ static LPVOID VIRTUALReserveMemory( MemSize = ( ((UINT_PTR)lpAddress + dwSize + VIRTUAL_PAGE_MASK) & ~VIRTUAL_PAGE_MASK ) - StartBoundary; - InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); - // If this is a request for special executable (JIT'ed) memory then, first of all, // try to get memory from the executable memory allocator to satisfy the request. if (((flAllocationType & MEM_RESERVE_EXECUTABLE) != 0) && (lpAddress == NULL)) @@ -881,7 +932,6 @@ static LPVOID VIRTUALReserveMemory( pRetVal, pRetVal != NULL); - InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); return pRetVal; } @@ -1211,7 +1261,7 @@ VirtualAlloc( } /* Test for un-supported flags. */ - if ( ( flAllocationType & ~( MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN | MEM_RESERVE_EXECUTABLE ) ) != 0 ) + if ( ( flAllocationType & ~( MEM_COMMIT | MEM_RESERVE | MEM_RESET | MEM_TOP_DOWN | MEM_RESERVE_EXECUTABLE ) ) != 0 ) { ASSERT( "flAllocationType can be one, or any combination of MEM_COMMIT, \ MEM_RESERVE, MEM_TOP_DOWN, or MEM_RESERVE_EXECUTABLE.\n" ); @@ -1240,6 +1290,26 @@ VirtualAlloc( NULL, TRUE); + if ( flAllocationType & MEM_RESET ) + { + if ( flAllocationType != MEM_RESET ) + { + ASSERT( "MEM_RESET cannot be used with any other allocation flags in flAllocationType.\n" ); + pthrCurrent->SetLastError( ERROR_INVALID_PARAMETER ); + goto done; + } + + InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + pRetVal = VIRTUALResetMemory( pthrCurrent, lpAddress, dwSize ); + InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + + if ( !pRetVal ) + { + /* Error messages are already displayed, just leave. */ + goto done; + } + } + if ( flAllocationType & MEM_RESERVE ) { InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); @@ -1280,7 +1350,6 @@ done: return pRetVal; } - /*++ Function: VirtualFree |