diff --git a/src/common/heap_tracker.cpp b/src/common/heap_tracker.cpp index 4475ab5f0e..4c71bd06da 100644 --- a/src/common/heap_tracker.cpp +++ b/src/common/heap_tracker.cpp @@ -4,36 +4,17 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include "common/heap_tracker.h" #include "common/logging.h" +#include "common/memory_detect.h" #include "common/assert.h" namespace Common { -namespace { - -s64 GetMaxPermissibleResidentMapCount() { - // Default value. - s64 value = 65530; - - // Try to read how many mappings we can make. - std::ifstream s("/proc/sys/vm/max_map_count"); - s >> value; - - // Print, for debug. - LOG_INFO(HW_Memory, "Current maximum map count: {}", value); - - // Allow 20000 maps for other code and to account for split inaccuracy. - return std::max(value - 20000, 0); -} - -} // namespace - HeapTracker::HeapTracker(Common::HostMemory& buffer) : m_buffer(buffer), m_has_hardware_buffer_backing(!buffer.BackingHardwareBuffers().empty()), - m_max_resident_map_count(GetMaxPermissibleResidentMapCount()) {} + m_max_resident_map_count(static_cast(GetPermissibleMapCount())) {} HeapTracker::~HeapTracker() = default; void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length, diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 6b0065f16c..553b15b9ec 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -65,7 +65,9 @@ #include "common/settings.h" #ifdef __ANDROID__ +#include #include +#include #include namespace { @@ -88,6 +90,24 @@ PFN_AHardwareBuffer_getNativeHandle ResolveGetNativeHandle() { dlsym(lib, "AHardwareBuffer_getNativeHandle")); } +struct DmaBufSync { + u64 flags; +}; + +constexpr u64 DmaBufSyncRead = 1ULL << 0; +constexpr u64 DmaBufSyncWrite = 1ULL << 1; +constexpr u64 DmaBufSyncStart = 0ULL << 2; +constexpr u64 DmaBufSyncEnd = 1ULL << 2; + +void SyncDmaBufCpuAccess(int fd, u64 phase) { + DmaBufSync sync{.flags = phase | DmaBufSyncRead | DmaBufSyncWrite}; + while (ioctl(fd, _IOW('b', 0, DmaBufSync), &sync) != 0) { + if (errno != EINTR) { + return; + } + } +} + } // namespace #endif @@ -646,7 +666,7 @@ public: } const int probe_fd = handle->data[0]; bool ok = true; - const auto try_map = [&](int prot, off_t offset, const char* what) { + const auto try_map = [&](int prot, off_t offset) { if (!ok) { return; } @@ -657,10 +677,10 @@ public: } munmap(ptr, PageAlignment); }; - try_map(PROT_READ | PROT_WRITE, 0, "shared mappings"); - try_map(PROT_READ | PROT_WRITE, static_cast(PageAlignment), "mappings at an offset"); + try_map(PROT_READ | PROT_WRITE, 0); + try_map(PROT_READ | PROT_WRITE, static_cast(PageAlignment)); #ifdef ARCHITECTURE_arm64 - try_map(PROT_READ | PROT_EXEC, 0, "executable mappings"); + try_map(PROT_READ | PROT_EXEC, 0); #endif AHardwareBuffer_release(buffer); return ok; @@ -672,19 +692,14 @@ public: if (total_physical <= BaselineFootprint) { return 0; } - const u64 max_map_count = Common::GetMaxMapCount(); - constexpr u64 ReservedMaps = 24576; - if (max_map_count == 0 || max_map_count <= ReservedMaps) { + const u64 permissible_maps = Common::GetPermissibleMapCount(); + if (permissible_maps == 0) { return 0; } u64 budget = (total_physical - BaselineFootprint) / 2; - constexpr u64 MapSlotsPerWindow = 4096; - const u64 affordable_windows = (max_map_count - ReservedMaps) / MapSlotsPerWindow; + constexpr u64 MapSlotsPerWindow = 64; + const u64 affordable_windows = permissible_maps / MapSlotsPerWindow; budget = (std::min)(budget, affordable_windows * window_size); - const u64 available = Common::GetAvailablePhysicalMemory(); - if (available != 0) { - budget = (std::min)(budget, available / 2); - } budget = (std::min)(budget, static_cast(backing_size)); budget = Common::AlignDown(budget, window_size); constexpr u64 MinimumBudget = 256ULL << 20; @@ -790,6 +805,9 @@ public: ahb_base = region_base; ahb_bytes = region_size; committed_backing_size.store(region_size, std::memory_order_relaxed); + for (const int window_fd : ahb_fds) { + SyncDmaBufCpuAccess(window_fd, DmaBufSyncStart); + } return true; } @@ -960,6 +978,9 @@ private: } #ifdef __ANDROID__ + for (const int window_fd : ahb_fds) { + SyncDmaBufCpuAccess(window_fd, DmaBufSyncEnd); + } for (AHardwareBuffer* buffer : ahb_windows) { AHardwareBuffer_release(buffer); } diff --git a/src/common/memory_detect.cpp b/src/common/memory_detect.cpp index 457168a6ca..e21e058486 100644 --- a/src/common/memory_detect.cpp +++ b/src/common/memory_detect.cpp @@ -22,7 +22,6 @@ #include #include -#include #include "common/memory_detect.h" @@ -76,55 +75,26 @@ const MemoryInfo& GetMemInfo() { return mem_info; } -u64 GetAvailablePhysicalMemory() { -#ifdef _WIN32 - MEMORYSTATUSEX memorystatus; - memorystatus.dwLength = sizeof(memorystatus); - if (GlobalMemoryStatusEx(&memorystatus)) { - return memorystatus.ullAvailPhys; - } - return 0; -#elif defined(__linux__) - if (std::FILE* const file = std::fopen("/proc/meminfo", "re")) { - char line[256]; - u64 available = 0; - while (std::fgets(line, sizeof(line), file) != nullptr) { - if (std::strncmp(line, "MemAvailable:", 13) == 0) { - available = std::strtoull(line + 13, nullptr, 10) * 1024ULL; - break; - } - } - std::fclose(file); - if (available != 0) { - return available; - } - } - struct sysinfo info; - if (sysinfo(&info) == 0) { - const u64 unit = info.mem_unit != 0 ? info.mem_unit : 1ULL; - return (static_cast(info.freeram) + static_cast(info.bufferram)) * unit; - } - return 0; -#else - return 0; -#endif -} - -u64 GetMaxMapCount() { +u64 GetPermissibleMapCount() { + constexpr u64 DefaultMapCount = 65530; + constexpr u64 ReservedMaps = 20000; + u64 count = DefaultMapCount; #ifdef __linux__ if (std::FILE* const file = std::fopen("/proc/sys/vm/max_map_count", "re")) { char line[32]; - u64 count = 0; if (std::fgets(line, sizeof(line), file) != nullptr) { - count = std::strtoull(line, nullptr, 10); + const u64 parsed = std::strtoull(line, nullptr, 10); + if (parsed != 0) { + count = parsed; + } } std::fclose(file); - return count; } - return 0; -#else - return 0; #endif + if (count <= ReservedMaps) { + return 0; + } + return count - ReservedMaps; } } // namespace Common diff --git a/src/common/memory_detect.h b/src/common/memory_detect.h index ce5d03788f..9a7ce7ab1c 100644 --- a/src/common/memory_detect.h +++ b/src/common/memory_detect.h @@ -21,8 +21,6 @@ struct MemoryInfo { */ [[nodiscard]] const MemoryInfo& GetMemInfo(); -[[nodiscard]] u64 GetAvailablePhysicalMemory(); - -[[nodiscard]] u64 GetMaxMapCount(); +[[nodiscard]] u64 GetPermissibleMapCount(); } // namespace Common