Skip to content

Instantly share code, notes, and snippets.

@NickStrupat
Last active March 19, 2022 20:56
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NickStrupat/cf94ffd899a4c9ecfa184a57a3caeb6c to your computer and use it in GitHub Desktop.
Save NickStrupat/cf94ffd899a4c9ecfa184a57a3caeb6c to your computer and use it in GitHub Desktop.
#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