Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/common/memmap.h
4223 views
1
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#pragma once
5
6
#include "types.h"
7
8
#include <map>
9
#include <string>
10
11
#if defined(_WIN32)
12
13
// eww :/ but better than including windows.h
14
enum class PageProtect : u32
15
{
16
NoAccess = 0x01, // PAGE_NOACCESS
17
ReadOnly = 0x02, // PAGE_READONLY
18
ReadWrite = 0x04, // PAGE_READWRITE
19
ReadExecute = 0x20, // PAGE_EXECUTE_READ
20
ReadWriteExecute = 0x40, // PAGE_EXECUTE_READWRITE
21
};
22
23
#elif defined(__APPLE__)
24
25
#include <mach/mach_vm.h>
26
27
enum class PageProtect : u32
28
{
29
NoAccess = VM_PROT_NONE,
30
ReadOnly = VM_PROT_READ,
31
ReadWrite = VM_PROT_READ | VM_PROT_WRITE,
32
ReadExecute = VM_PROT_READ | VM_PROT_EXECUTE,
33
ReadWriteExecute = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE,
34
};
35
36
#else
37
38
#include <sys/mman.h>
39
40
enum class PageProtect : u32
41
{
42
NoAccess = PROT_NONE,
43
ReadOnly = PROT_READ,
44
ReadWrite = PROT_READ | PROT_WRITE,
45
ReadExecute = PROT_READ | PROT_EXEC,
46
ReadWriteExecute = PROT_READ | PROT_WRITE | PROT_EXEC,
47
};
48
49
#endif
50
51
class Error;
52
53
namespace MemMap {
54
/// Returns the size of pages for the current host.
55
u32 GetRuntimePageSize();
56
57
std::string GetFileMappingName(const char* prefix);
58
void* CreateSharedMemory(const char* name, size_t size, Error* error);
59
void DeleteSharedMemory(const char* name);
60
void DestroySharedMemory(void* ptr);
61
void* MapSharedMemory(void* handle, size_t offset, void* baseaddr, size_t size, PageProtect mode);
62
void UnmapSharedMemory(void* baseaddr, size_t size);
63
bool MemProtect(void* baseaddr, size_t size, PageProtect mode);
64
65
/// Returns the base address for the current process.
66
const void* GetBaseAddress();
67
68
/// Allocates RWX memory in branch range from the base address.
69
void* AllocateJITMemory(size_t size);
70
71
/// Releases RWX memory.
72
void ReleaseJITMemory(void* ptr, size_t size);
73
74
/// Flushes the instruction cache on the host for the specified range.
75
/// Only needed outside of X86, X86 has coherent D/I cache.
76
#if !defined(CPU_ARCH_ARM32) && !defined(CPU_ARCH_ARM64) && !defined(CPU_ARCH_RISCV64)
77
// clang-format off
78
ALWAYS_INLINE static void FlushInstructionCache(void* address, size_t size) { }
79
// clang-format on
80
#else
81
void FlushInstructionCache(void* address, size_t size);
82
#endif
83
84
/// JIT write protect for Apple Silicon. Needs to be called prior to writing to any RWX pages.
85
#if !defined(__APPLE__) || !defined(__aarch64__)
86
// clang-format off
87
ALWAYS_INLINE static void BeginCodeWrite() { }
88
ALWAYS_INLINE static void EndCodeWrite() { }
89
// clang-format on
90
#else
91
void BeginCodeWrite();
92
void EndCodeWrite();
93
#endif
94
} // namespace MemMap
95
96
class SharedMemoryMappingArea
97
{
98
public:
99
SharedMemoryMappingArea();
100
~SharedMemoryMappingArea();
101
102
ALWAYS_INLINE size_t GetSize() const { return m_size; }
103
ALWAYS_INLINE size_t GetNumPages() const { return m_num_pages; }
104
105
ALWAYS_INLINE u8* BasePointer() const { return m_base_ptr; }
106
ALWAYS_INLINE u8* OffsetPointer(size_t offset) const { return m_base_ptr + offset; }
107
ALWAYS_INLINE u8* PagePointer(size_t page) const { return m_base_ptr + (page << HOST_PAGE_SHIFT); }
108
109
bool Create(size_t size);
110
void Destroy();
111
112
u8* Map(void* file_handle, size_t file_offset, void* map_base, size_t map_size, PageProtect mode);
113
bool Unmap(void* map_base, size_t map_size);
114
115
private:
116
u8* m_base_ptr = nullptr;
117
size_t m_size = 0;
118
size_t m_num_pages = 0;
119
size_t m_num_mappings = 0;
120
121
#ifdef _WIN32
122
using PlaceholderMap = std::map<size_t, size_t>;
123
124
PlaceholderMap::iterator FindPlaceholder(size_t page);
125
126
PlaceholderMap m_placeholder_ranges;
127
#endif
128
};
129
130