diff options
author | Daniel Neus <[email protected]> | 2016-03-07 20:46:09 +0100 |
---|---|---|
committer | Daniel Neus <[email protected]> | 2016-03-07 20:31:50 +0100 |
commit | 094e7bbcbf3ad930a01910e445bc3f2b6be2faf7 (patch) | |
tree | 33c0809f9497bbe11a402787ceeb7511f920f063 | |
parent | 58c89ae470c68bf300ea937740c233e2b5715535 (diff) |
add support for VirtualLock/VirtualUnlock on Windows
equivalent to mlock on Unix to prevent swapping out of memory
-rw-r--r-- | doc/license.txt | 2 | ||||
-rw-r--r-- | doc/news.rst | 2 | ||||
-rw-r--r-- | src/lib/utils/os_utils.cpp | 52 |
3 files changed, 54 insertions, 2 deletions
diff --git a/doc/license.txt b/doc/license.txt index 873e55e37..ba4381c1b 100644 --- a/doc/license.txt +++ b/doc/license.txt @@ -26,7 +26,7 @@ Copyright (C) 1999-2013,2014,2015,2016 Jack Lloyd 2015 Simon Warta (Kullo GmbH) 2015 Matej Kenda (TopIT d.o.o.) 2015 René Korthaus - 2015 Daniel Neus + 2015,2016 Daniel Neus 2015 Uri Blumenthal All rights reserved. diff --git a/doc/news.rst b/doc/news.rst index 72f5fa88b..d5698d23e 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -37,6 +37,8 @@ Version 1.11.29, Not Yet Released * Small optimizations to Keccak hash +* Support for locking allocator on Windows using VirtualLock/VirtualUnlock + Version 1.10.12, 2016-02-03 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp index 8fa099bc6..5deea902a 100644 --- a/src/lib/utils/os_utils.cpp +++ b/src/lib/utils/os_utils.cpp @@ -1,6 +1,7 @@ /* * OS and machine specific utility functions * (C) 2015,2016 Jack Lloyd +* (C) 2016 Daniel Neus * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -50,7 +51,7 @@ uint64_t get_processor_timestamp() #if defined(BOTAN_USE_GCC_INLINE_ASM) #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) - if(CPUID::has_rdtsc()) // not availble on all x86 CPUs + if(CPUID::has_rdtsc()) // not available on all x86 CPUs { uint32_t rtc_low = 0, rtc_high = 0; asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low)); @@ -140,6 +141,37 @@ size_t get_memory_locking_limit() return std::min<size_t>(limits.rlim_cur, mlock_requested * 1024); } +#elif defined BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK + SIZE_T working_min = 0, working_max = 0; + DWORD working_flags = 0; + if(!::GetProcessWorkingSetSizeEx(::GetCurrentProcess(), &working_min, &working_max, &working_flags)) + { + return 0; + } + + SYSTEM_INFO sSysInfo; + ::GetSystemInfo(&sSysInfo); + + // According to Microsoft MSDN: + // The maximum number of pages that a process can lock is equal to the number of pages in its minimum working set minus a small overhead + // In the book "Windows Internals Part 2": the maximum lockable pages are minimum working set size - 8 pages + // But the information in the book seems to be inaccurate/outdated + // I've tested this on Windows 8.1 x64, Windows 10 x64 and Windows 7 x86 + // On all three OS the value is 11 instead of 8 + size_t overhead = sSysInfo.dwPageSize * 11ULL; + if(working_min > overhead) + { + size_t lockable_bytes = working_min - overhead; + if(lockable_bytes < (BOTAN_MLOCK_ALLOCATOR_MAX_LOCKED_KB * 1024ULL)) + { + return lockable_bytes; + } + else + { + return BOTAN_MLOCK_ALLOCATOR_MAX_LOCKED_KB * 1024ULL; + } + } + return 0; #endif return 0; @@ -182,6 +214,20 @@ void* allocate_locked_pages(size_t length) ::memset(ptr, 0, length); return ptr; +#elif defined BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK + LPVOID ptr = ::VirtualAlloc(nullptr, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if(!ptr) + { + return nullptr; + } + + if(::VirtualLock(ptr, length) == 0) + { + ::VirtualFree(ptr, 0, MEM_RELEASE); + return nullptr; // failed to lock + } + + return ptr; #else return nullptr; /* not implemented */ #endif @@ -196,6 +242,10 @@ void free_locked_pages(void* ptr, size_t length) zero_mem(ptr, length); ::munlock(ptr, length); ::munmap(ptr, length); +#elif defined BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK + zero_mem(ptr, length); + ::VirtualUnlock(ptr, length); + ::VirtualFree(ptr, 0, MEM_RELEASE); #else // Invalid argument because no way this pointer was allocated by us throw Invalid_Argument("Invalid ptr to free_locked_pages"); |