Merge pull request #12150 from AdmiralCurtiss/fast-block-cache-fix
JitCache: Fix potentially dangling pointer to fast block map.
This commit is contained in:
commit
6beaee078b
|
@ -122,4 +122,42 @@ private:
|
|||
#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
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
@ -142,4 +143,46 @@ void MemArena::UnmapFromMemoryRegion(void* view, size_t size)
|
|||
if (retval == MAP_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
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
@ -108,4 +109,46 @@ void MemArena::UnmapFromMemoryRegion(void* view, size_t size)
|
|||
if (retval == MAP_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
|
||||
|
|
|
@ -433,4 +433,47 @@ void MemArena::UnmapFromMemoryRegion(void* view, size_t size)
|
|||
|
||||
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
|
||||
|
|
|
@ -42,7 +42,11 @@ void JitBaseBlockCache::Init()
|
|||
{
|
||||
Common::JitRegister::Init(Config::Get(Config::MAIN_PERF_MAP_DIR));
|
||||
|
||||
m_block_map_arena.GrabSHMSegment(FAST_BLOCK_MAP_SIZE, "dolphin-emu-jitblock");
|
||||
m_fast_block_map = reinterpret_cast<JitBlock**>(m_block_map_arena.Create(FAST_BLOCK_MAP_SIZE));
|
||||
if (m_fast_block_map)
|
||||
m_fast_block_map_ptr = m_fast_block_map;
|
||||
else
|
||||
m_fast_block_map_ptr = m_fast_block_map_fallback.data();
|
||||
|
||||
Clear();
|
||||
}
|
||||
|
@ -51,12 +55,7 @@ void JitBaseBlockCache::Shutdown()
|
|||
{
|
||||
Common::JitRegister::Shutdown();
|
||||
|
||||
if (m_fast_block_map)
|
||||
{
|
||||
m_block_map_arena.ReleaseView(m_fast_block_map, FAST_BLOCK_MAP_SIZE);
|
||||
}
|
||||
|
||||
m_block_map_arena.ReleaseSHMSegment();
|
||||
m_block_map_arena.Release();
|
||||
}
|
||||
|
||||
// This clears the JIT cache. It's called from JitCache.cpp when the JIT cache
|
||||
|
@ -80,23 +79,7 @@ void JitBaseBlockCache::Clear()
|
|||
valid_block.ClearAll();
|
||||
|
||||
if (m_fast_block_map)
|
||||
{
|
||||
m_block_map_arena.ReleaseView(m_fast_block_map, FAST_BLOCK_MAP_SIZE);
|
||||
m_block_map_arena.ReleaseSHMSegment();
|
||||
m_block_map_arena.GrabSHMSegment(FAST_BLOCK_MAP_SIZE, "dolphin-emu-jitblock");
|
||||
}
|
||||
|
||||
m_fast_block_map =
|
||||
reinterpret_cast<JitBlock**>(m_block_map_arena.CreateView(0, FAST_BLOCK_MAP_SIZE));
|
||||
|
||||
if (m_fast_block_map)
|
||||
{
|
||||
m_fast_block_map_ptr = m_fast_block_map;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fast_block_map_ptr = m_fast_block_map_fallback.data();
|
||||
}
|
||||
m_block_map_arena.Clear();
|
||||
}
|
||||
|
||||
void JitBaseBlockCache::Reset()
|
||||
|
|
|
@ -212,7 +212,7 @@ private:
|
|||
// This is used as a fast cache of block_map used in the assembly dispatcher.
|
||||
// It is implemented via a shm segment using m_block_map_arena.
|
||||
JitBlock** m_fast_block_map = 0;
|
||||
Common::MemArena m_block_map_arena;
|
||||
Common::LazyMemoryRegion m_block_map_arena;
|
||||
|
||||
// An alternative for the above fast_block_map but without a shm segment
|
||||
// in case the shm memory region couldn't be allocated.
|
||||
|
|
Loading…
Reference in New Issue