diff options
Diffstat (limited to 'src/common/host_memory.cpp')
-rw-r--r-- | src/common/host_memory.cpp | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 611c7d1a3..ba22595e0 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -11,9 +11,14 @@ #elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv +#ifdef ANDROID +#include <android/sharedmem.h> +#endif + #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif +#include <boost/icl/interval_set.hpp> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> @@ -322,7 +327,7 @@ private: } /// Return true when a given memory region is a "nieche" and the placeholders don't have to be - /// splitted. + /// split. bool IsNiechePlaceholder(size_t virtual_offset, size_t length) const { const auto it = placeholders.upper_bound({virtual_offset, virtual_offset + length}); if (it != placeholders.end() && it->lower() == virtual_offset + length) { @@ -366,17 +371,20 @@ public: } // Backing memory initialization -#if defined(__FreeBSD__) && __FreeBSD__ < 13 +#ifdef ANDROID + fd = ASharedMemory_create("HostMemory", backing_size); +#elif defined(__FreeBSD__) && __FreeBSD__ < 13 // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 fd = shm_open(SHM_ANON, O_RDWR, 0600); #else fd = memfd_create("HostMemory", 0); #endif - if (fd == -1) { + if (fd < 0) { LOG_CRITICAL(HW_Memory, "memfd_create failed: {}", strerror(errno)); throw std::bad_alloc{}; } +#ifndef ANDROID // Defined to extend the file with zeros int ret = ftruncate(fd, backing_size); if (ret != 0) { @@ -384,6 +392,7 @@ public: strerror(errno)); throw std::bad_alloc{}; } +#endif backing_base = static_cast<u8*>( mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); @@ -415,6 +424,7 @@ public: madvise(virtual_base, virtual_size, MADV_HUGEPAGE); #endif + placeholders.add({0, virtual_size}); good = true; } @@ -423,6 +433,10 @@ public: } void Map(size_t virtual_offset, size_t host_offset, size_t length) { + { + std::scoped_lock lock{placeholder_mutex}; + placeholders.subtract({virtual_offset, virtual_offset + length}); + } void* ret = mmap(virtual_base + virtual_offset, length, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, host_offset); @@ -433,6 +447,19 @@ public: // The method name is wrong. We're still talking about the virtual range. // We don't want to unmap, we want to reserve this memory. + { + std::scoped_lock lock{placeholder_mutex}; + auto it = placeholders.find({virtual_offset - 1, virtual_offset + length + 1}); + + if (it != placeholders.end()) { + size_t prev_upper = virtual_offset + length; + virtual_offset = std::min(virtual_offset, it->lower()); + length = std::max(it->upper(), prev_upper) - virtual_offset; + } + + placeholders.add({virtual_offset, virtual_offset + length}); + } + void* ret = mmap(virtual_base + virtual_offset, length, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno)); @@ -476,6 +503,9 @@ private: } int fd{-1}; // memfd file descriptor, -1 is the error value of memfd_create + + boost::icl::interval_set<size_t> placeholders; ///< Mapped placeholders + std::mutex placeholder_mutex; ///< Mutex for placeholders }; #else // ^^^ Linux ^^^ vvv Generic vvv @@ -484,7 +514,7 @@ class HostMemory::Impl { public: explicit Impl(size_t /*backing_size */, size_t /* virtual_size */) { // This is just a place holder. - // Please implement fastmem in a propper way on your platform. + // Please implement fastmem in a proper way on your platform. throw std::bad_alloc{}; } |