mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
Common/MemArena: Add LazyMemoryRegion to represent a zero-initialized memory region whose pages are only allocated on first access.
This commit is contained in:
parent
5e5887a378
commit
5bd7756064
@ -122,4 +122,42 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This class represents a single fixed-size memory region where the individual memory pages are
|
||||||
|
// only actually allocated on first access. The memory will be zero on first access.
|
||||||
|
class LazyMemoryRegion final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LazyMemoryRegion();
|
||||||
|
~LazyMemoryRegion();
|
||||||
|
LazyMemoryRegion(const LazyMemoryRegion&) = delete;
|
||||||
|
LazyMemoryRegion(LazyMemoryRegion&&) = delete;
|
||||||
|
LazyMemoryRegion& operator=(const LazyMemoryRegion&) = delete;
|
||||||
|
LazyMemoryRegion& operator=(LazyMemoryRegion&&) = delete;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Reserve a memory region.
|
||||||
|
///
|
||||||
|
/// @param size The size of the region.
|
||||||
|
///
|
||||||
|
/// @return The address the region was mapped at. Returns nullptr on failure.
|
||||||
|
///
|
||||||
|
void* Create(size_t size);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Reset the memory region back to zero, throwing away any mapped pages.
|
||||||
|
/// This can only be called after a successful call to Create().
|
||||||
|
///
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Release the memory previously reserved with Create(). After this call the pointer that was
|
||||||
|
/// returned by Create() will become invalid.
|
||||||
|
///
|
||||||
|
void Release();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* m_memory = nullptr;
|
||||||
|
size_t m_size = 0;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
#include "Common/CommonFuncs.h"
|
#include "Common/CommonFuncs.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
@ -142,4 +143,46 @@ void MemArena::UnmapFromMemoryRegion(void* view, size_t size)
|
|||||||
if (retval == MAP_FAILED)
|
if (retval == MAP_FAILED)
|
||||||
NOTICE_LOG_FMT(MEMMAP, "mmap failed");
|
NOTICE_LOG_FMT(MEMMAP, "mmap failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LazyMemoryRegion::LazyMemoryRegion() = default;
|
||||||
|
|
||||||
|
LazyMemoryRegion::~LazyMemoryRegion()
|
||||||
|
{
|
||||||
|
Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void* LazyMemoryRegion::Create(size_t size)
|
||||||
|
{
|
||||||
|
ASSERT(!m_memory);
|
||||||
|
|
||||||
|
void* memory = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
|
if (!memory)
|
||||||
|
{
|
||||||
|
NOTICE_LOG_FMT(MEMMAP, "Memory allocation of {} bytes failed.", size);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_memory = memory;
|
||||||
|
m_size = size;
|
||||||
|
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LazyMemoryRegion::Clear()
|
||||||
|
{
|
||||||
|
ASSERT(m_memory);
|
||||||
|
|
||||||
|
mmap(m_memory, m_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LazyMemoryRegion::Release()
|
||||||
|
{
|
||||||
|
if (m_memory)
|
||||||
|
{
|
||||||
|
munmap(m_memory, m_size);
|
||||||
|
m_memory = nullptr;
|
||||||
|
m_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
#include "Common/CommonFuncs.h"
|
#include "Common/CommonFuncs.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
@ -108,4 +109,46 @@ void MemArena::UnmapFromMemoryRegion(void* view, size_t size)
|
|||||||
if (retval == MAP_FAILED)
|
if (retval == MAP_FAILED)
|
||||||
NOTICE_LOG_FMT(MEMMAP, "mmap failed");
|
NOTICE_LOG_FMT(MEMMAP, "mmap failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LazyMemoryRegion::LazyMemoryRegion() = default;
|
||||||
|
|
||||||
|
LazyMemoryRegion::~LazyMemoryRegion()
|
||||||
|
{
|
||||||
|
Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void* LazyMemoryRegion::Create(size_t size)
|
||||||
|
{
|
||||||
|
ASSERT(!m_memory);
|
||||||
|
|
||||||
|
void* memory = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
|
if (!memory)
|
||||||
|
{
|
||||||
|
NOTICE_LOG_FMT(MEMMAP, "Memory allocation of {} bytes failed.", size);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_memory = memory;
|
||||||
|
m_size = size;
|
||||||
|
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LazyMemoryRegion::Clear()
|
||||||
|
{
|
||||||
|
ASSERT(m_memory);
|
||||||
|
|
||||||
|
mmap(m_memory, m_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LazyMemoryRegion::Release()
|
||||||
|
{
|
||||||
|
if (m_memory)
|
||||||
|
{
|
||||||
|
munmap(m_memory, m_size);
|
||||||
|
m_memory = nullptr;
|
||||||
|
m_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
@ -433,4 +433,47 @@ void MemArena::UnmapFromMemoryRegion(void* view, size_t size)
|
|||||||
|
|
||||||
UnmapViewOfFile(view);
|
UnmapViewOfFile(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LazyMemoryRegion::LazyMemoryRegion() = default;
|
||||||
|
|
||||||
|
LazyMemoryRegion::~LazyMemoryRegion()
|
||||||
|
{
|
||||||
|
Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void* LazyMemoryRegion::Create(size_t size)
|
||||||
|
{
|
||||||
|
ASSERT(!m_memory);
|
||||||
|
|
||||||
|
void* memory = VirtualAlloc(nullptr, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
if (!memory)
|
||||||
|
{
|
||||||
|
NOTICE_LOG_FMT(MEMMAP, "Memory allocation of {} bytes failed.", size);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_memory = memory;
|
||||||
|
m_size = size;
|
||||||
|
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LazyMemoryRegion::Clear()
|
||||||
|
{
|
||||||
|
ASSERT(m_memory);
|
||||||
|
|
||||||
|
VirtualFree(m_memory, m_size, MEM_DECOMMIT);
|
||||||
|
VirtualAlloc(m_memory, m_size, MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LazyMemoryRegion::Release()
|
||||||
|
{
|
||||||
|
if (m_memory)
|
||||||
|
{
|
||||||
|
VirtualFree(m_memory, 0, MEM_RELEASE);
|
||||||
|
m_memory = nullptr;
|
||||||
|
m_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
Loading…
Reference in New Issue
Block a user