Last active
March 19, 2022 20:56
-
-
Save NickStrupat/cf94ffd899a4c9ecfa184a57a3caeb6c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#if defined(_WIN32) | |
# include <Windows.h> | |
#elif defined(__APPLE__) || defined(LINUX) | |
# include <sys/mman.h> | |
#endif | |
#include <optional> | |
#include "result.hpp" | |
#include "block.hpp" | |
namespace cova::memory::virtual_ | |
{ | |
result<block<>, uint32_t> allocate(size_t size); | |
result<block<>, uint32_t> allocate(void * first, size_t size); | |
result<void, uint32_t> deallocate(block<> const & allocated); | |
void * reserve(size_t size); | |
void * reserve(void * location, size_t size); | |
void * commit(void * reserved, size_t size); | |
bool decommit(void * committed); | |
bool release(void * reserved); | |
#if defined(_WIN32) | |
inline result<block<>, uint32_t> allocate(size_t const size) | |
{ | |
auto const p = VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); | |
if (p == nullptr) | |
return uint32_t(GetLastError()); | |
return block<>(p, size); | |
} | |
inline result<block<>, uint32_t> allocate(void * const first, size_t const size) | |
{ | |
auto const p = VirtualAlloc(first, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); | |
if (p == nullptr) | |
return uint32_t(GetLastError()); | |
if (p != first) | |
return uint32_t(-1); | |
return block<>(p, size); | |
} | |
inline result<void, uint32_t> deallocate(block<> const & allocated) | |
{ | |
if (!VirtualFree(allocated.address, 0, MEM_RELEASE)) | |
return uint32_t(GetLastError()); | |
return result<void, uint32_t>(); | |
} | |
inline void * reserve(size_t const size) | |
{ | |
return VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_NOACCESS); // don't use MEM_TOP_DOWN (https://randomascii.wordpress.com/2011/08/05/making-virtualalloc-arbitrarily-slower/) | |
} | |
inline void * commit(void * const reserved, size_t const size) | |
{ | |
return VirtualAlloc(reserved, size, MEM_COMMIT, PAGE_READWRITE); | |
} | |
inline bool decommit(void * const committed) | |
{ | |
return static_cast<bool>(VirtualFree(committed, 0, MEM_DECOMMIT)); | |
} | |
inline bool release(void * const reserved) | |
{ | |
return static_cast<bool>(VirtualFree(reserved, 0, MEM_RELEASE)); | |
} | |
#elif defined(__APPLE__) | |
// https://stackoverflow.com/questions/30057381/c-porting-virtualfree-in-os-x | |
inline void * reserve(size_t const size) | |
{ | |
void * ptr = mmap(NULL, size, PROT_NONE, (MAP_PRIVATE | MAP_ANON), -1, 0); | |
msync(ptr, size, (MS_SYNC | MS_INVALIDATE)); | |
} | |
inline void * commit(void * const reserved, size_t const size) | |
{ | |
void * ptr = mmap(addr, size, (PROT_READ | PROT_WRITE), (MAP_FIXED | MAP_SHARED | MAP_ANON), -1, 0); | |
msync(addr, size, (MS_SYNC | MS_INVALIDATE)); | |
} | |
inline bool decommit(void * const committed) | |
{ | |
mmap(addr, size, PROT_NONE, (MAP_FIXED | MAP_PRIVATE | MAP_ANON), -1, 0); | |
msync(addr, size, MS_SYNC | MS_INVALIDATE); | |
} | |
inline bool release(void * const reserved) | |
{ | |
msync(addr, size, MS_SYNC); | |
munmap(addr, size); | |
} | |
#elif defined(LINUX) | |
inline void * reserve(size_t const size) | |
{ | |
void * ptr = mmap(NULL, size, PROT_NONE, (MAP_PRIVATE | MAP_ANONYMOUS), -1, 0); | |
} | |
inline void * commit(void * const reserved, size_t const size) | |
{ | |
void * ptr = mmap(addr, size, (PROT_READ | PROT_WRITE), (MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS), -1, 0); | |
} | |
inline bool decommit(void * const committed) | |
{ | |
mmap(addr, size, PROT_NONE, (MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS), -1, 0); | |
} | |
inline bool release(void * const reserved) | |
{ | |
munmap(addr, size); | |
} | |
#endif | |
/* | |
//https://stackoverflow.com/questions/30057381/c-porting-virtualfree-in-os-x | |
//to reserve virtual address space | |
//equivalent of VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS) | |
void* ptr = mmap(NULL, size, PROT_NONE, (MAP_PRIVATE | MAP_ANON), -1, 0); | |
msync(ptr, size, (MS_SYNC | MS_INVALIDATE)); | |
//to free ALL virtual address space | |
//equivalent of VirtualFree(addr, 0, MEM_RELEASE) | |
//where "size" is the size of the entire virtual address space and "addr" the starting address | |
msync(addr, size, MS_SYNC); | |
munmap(addr, size); | |
//to allocate physical memory | |
//equivalent of VirtualAlloc(addr, size, MEM_COMMIT, PAGE_READWRITE) | |
void* ptr = mmap(addr, size, (PROT_READ | PROT_WRITE), (MAP_FIXED | MAP_SHARED | MAP_ANON), -1, 0); | |
msync(addr, size, (MS_SYNC | MS_INVALIDATE)); | |
void DecommitMemory(void* addr, size_t size) | |
{ | |
// instead of unmapping the address, we're just gonna trick | |
// the TLB to mark this as a new mapped area which, due to | |
// demand paging, will not be committed until used. | |
mmap(addr, size, PROT_NONE, MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0); | |
msync(addr, size, MS_SYNC|MS_INVALIDATE); | |
} | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment