Merge pull request #10550 from kkoniuszy/linux-map-buildup-fix

host_memory: merge adjacent placeholder mappings on Linux
This commit is contained in:
bunnei 2023-06-03 23:22:24 -07:00 committed by GitHub
commit c5782150f0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -14,6 +14,7 @@
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #endif
#include <boost/icl/interval_set.hpp>
#include <fcntl.h> #include <fcntl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <unistd.h> #include <unistd.h>
@ -415,6 +416,7 @@ public:
madvise(virtual_base, virtual_size, MADV_HUGEPAGE); madvise(virtual_base, virtual_size, MADV_HUGEPAGE);
#endif #endif
placeholders.add({0, virtual_size});
good = true; good = true;
} }
@ -423,6 +425,10 @@ public:
} }
void Map(size_t virtual_offset, size_t host_offset, size_t length) { 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, void* ret = mmap(virtual_base + virtual_offset, length, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FIXED, fd, host_offset); MAP_SHARED | MAP_FIXED, fd, host_offset);
@ -433,6 +439,19 @@ public:
// The method name is wrong. We're still talking about the virtual range. // 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. // 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, void* ret = mmap(virtual_base + virtual_offset, length, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno)); ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno));
@ -476,6 +495,9 @@ private:
} }
int fd{-1}; // memfd file descriptor, -1 is the error value of memfd_create 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 #else // ^^^ Linux ^^^ vvv Generic vvv