diff --git a/runtime/memory_manager/gfx_partition.cpp b/runtime/memory_manager/gfx_partition.cpp index de5387e236..884078b9a7 100644 --- a/runtime/memory_manager/gfx_partition.cpp +++ b/runtime/memory_manager/gfx_partition.cpp @@ -8,7 +8,6 @@ #include "runtime/memory_manager/gfx_partition.h" #include "runtime/helpers/aligned_memory.h" -#include "runtime/os_interface/os_memory.h" namespace NEO { @@ -23,9 +22,12 @@ const std::array GfxPartition::heapNonSvmNames{{HeapIndex::HEAP_IN HeapIndex::HEAP_EXTERNAL, HeapIndex::HEAP_STANDARD, HeapIndex::HEAP_STANDARD64KB}}; + +GfxPartition::GfxPartition() : osMemory(OSMemory::create()) {} + GfxPartition::~GfxPartition() { if (reservedCpuAddressRange) { - OSMemory::releaseCpuAddressRange(reservedCpuAddressRange, reservedCpuAddressRangeSize); + osMemory->releaseCpuAddressRange(reservedCpuAddressRange, reservedCpuAddressRangeSize); } } @@ -113,7 +115,7 @@ void GfxPartition::init(uint64_t gpuAddressSpace, size_t cpuAddressRangeSizeToRe } else if (gpuAddressSpace == maxNBitValue<47>) { reservedCpuAddressRangeSize = cpuAddressRangeSizeToReserve; UNRECOVERABLE_IF(reservedCpuAddressRangeSize == 0); - reservedCpuAddressRange = OSMemory::reserveCpuAddressRange(reservedCpuAddressRangeSize); + reservedCpuAddressRange = osMemory->reserveCpuAddressRange(reservedCpuAddressRangeSize); UNRECOVERABLE_IF(reservedCpuAddressRange == nullptr); UNRECOVERABLE_IF(!isAligned(reservedCpuAddressRange)); gfxBase = reinterpret_cast(reservedCpuAddressRange); diff --git a/runtime/memory_manager/gfx_partition.h b/runtime/memory_manager/gfx_partition.h index 592120fbd9..dd7ebb1011 100644 --- a/runtime/memory_manager/gfx_partition.h +++ b/runtime/memory_manager/gfx_partition.h @@ -7,6 +7,7 @@ #pragma once #include "runtime/memory_manager/memory_constants.h" +#include "runtime/os_interface/os_memory.h" #include "runtime/utilities/heap_allocator.h" #include @@ -30,7 +31,7 @@ constexpr auto internalHeapIndex = is32bit ? HeapIndex::HEAP_INTERNAL : HeapInde class GfxPartition { public: - GfxPartition() {} + GfxPartition(); MOCKABLE_VIRTUAL ~GfxPartition(); void init(uint64_t gpuAddressSpace, size_t cpuAddressRangeSizeToReserve); @@ -92,6 +93,7 @@ class GfxPartition { void *reservedCpuAddressRange = nullptr; size_t reservedCpuAddressRangeSize = 0; + std::unique_ptr osMemory; }; } // namespace NEO diff --git a/runtime/os_interface/linux/CMakeLists.txt b/runtime/os_interface/linux/CMakeLists.txt index d5fd9ba970..91a8becb4b 100644 --- a/runtime/os_interface/linux/CMakeLists.txt +++ b/runtime/os_interface/linux/CMakeLists.txt @@ -45,6 +45,7 @@ set(RUNTIME_SRCS_OS_INTERFACE_LINUX ${CMAKE_CURRENT_SOURCE_DIR}/os_library.cpp ${CMAKE_CURRENT_SOURCE_DIR}/os_library.h ${CMAKE_CURRENT_SOURCE_DIR}/os_memory_linux.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/os_memory_linux.h ${CMAKE_CURRENT_SOURCE_DIR}/os_metrics_library.cpp ${CMAKE_CURRENT_SOURCE_DIR}/os_thread_linux.cpp ${CMAKE_CURRENT_SOURCE_DIR}/os_thread_linux.h diff --git a/runtime/os_interface/linux/os_memory_linux.cpp b/runtime/os_interface/linux/os_memory_linux.cpp index 51b534a36f..015a34b9c6 100644 --- a/runtime/os_interface/linux/os_memory_linux.cpp +++ b/runtime/os_interface/linux/os_memory_linux.cpp @@ -5,19 +5,28 @@ * */ -#include "runtime/os_interface/os_memory.h" - -#include -#include +#include "runtime/os_interface/linux/os_memory_linux.h" namespace NEO { -void *OSMemory::reserveCpuAddressRange(size_t sizeToReserve) { - return mmap(0, sizeToReserve, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_HUGETLB, -1, 0); +std::unique_ptr OSMemory::create() { + return std::make_unique(); } -void OSMemory::releaseCpuAddressRange(void *reservedCpuAddressRange, size_t reservedSize) { - munmap(reservedCpuAddressRange, reservedSize); +void *OSMemoryLinux::reserveCpuAddressRange(size_t sizeToReserve) { + return mmapWrapper(0, sizeToReserve, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_HUGETLB, -1, 0); +} + +void OSMemoryLinux::releaseCpuAddressRange(void *reservedCpuAddressRange, size_t reservedSize) { + munmapWrapper(reservedCpuAddressRange, reservedSize); +} + +void *OSMemoryLinux::mmapWrapper(void *addr, size_t size, int prot, int flags, int fd, off_t off) { + return mmap(addr, size, prot, flags, fd, off); +} + +int OSMemoryLinux::munmapWrapper(void *addr, size_t size) { + return munmap(addr, size); } } // namespace NEO diff --git a/runtime/os_interface/linux/os_memory_linux.h b/runtime/os_interface/linux/os_memory_linux.h new file mode 100644 index 0000000000..4f74221d35 --- /dev/null +++ b/runtime/os_interface/linux/os_memory_linux.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2019 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "runtime/os_interface/os_memory.h" + +#include +#include + +namespace NEO { + +class OSMemoryLinux : public OSMemory { + public: + OSMemoryLinux() = default; + void *reserveCpuAddressRange(size_t sizeToReserve) override; + void releaseCpuAddressRange(void *reservedCpuAddressRange, size_t reservedSize) override; + + protected: + MOCKABLE_VIRTUAL void *mmapWrapper(void *, size_t, int, int, int, off_t); + MOCKABLE_VIRTUAL int munmapWrapper(void *, size_t); +}; + +} // namespace NEO diff --git a/runtime/os_interface/os_memory.h b/runtime/os_interface/os_memory.h index 2a0d18115a..d3ac3ca012 100644 --- a/runtime/os_interface/os_memory.h +++ b/runtime/os_interface/os_memory.h @@ -7,13 +7,17 @@ #pragma once #include +#include namespace NEO { struct OSMemory { public: - static void *reserveCpuAddressRange(size_t sizeToReserve); - static void releaseCpuAddressRange(void *reservedCpuAddressRange, size_t reservedSize); + static std::unique_ptr create(); + + virtual ~OSMemory() = default; + virtual void *reserveCpuAddressRange(size_t sizeToReserve) = 0; + virtual void releaseCpuAddressRange(void *reservedCpuAddressRange, size_t reservedSize) = 0; }; } // namespace NEO diff --git a/runtime/os_interface/windows/CMakeLists.txt b/runtime/os_interface/windows/CMakeLists.txt index d7b1f02661..b17f48bc89 100644 --- a/runtime/os_interface/windows/CMakeLists.txt +++ b/runtime/os_interface/windows/CMakeLists.txt @@ -36,6 +36,7 @@ set(RUNTIME_SRCS_OS_INTERFACE_WINDOWS ${CMAKE_CURRENT_SOURCE_DIR}/os_library.cpp ${CMAKE_CURRENT_SOURCE_DIR}/os_library.h ${CMAKE_CURRENT_SOURCE_DIR}/os_memory_win.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/os_memory_win.h ${CMAKE_CURRENT_SOURCE_DIR}/os_metrics_library.cpp ${CMAKE_CURRENT_SOURCE_DIR}/os_socket.h ${CMAKE_CURRENT_SOURCE_DIR}/os_thread_win.cpp diff --git a/runtime/os_interface/windows/os_memory_win.cpp b/runtime/os_interface/windows/os_memory_win.cpp index b1609113eb..e6bc345698 100644 --- a/runtime/os_interface/windows/os_memory_win.cpp +++ b/runtime/os_interface/windows/os_memory_win.cpp @@ -5,18 +5,28 @@ * */ -#include "runtime/os_interface/os_memory.h" - -#include +#include "runtime/os_interface/windows/os_memory_win.h" namespace NEO { -void *OSMemory::reserveCpuAddressRange(size_t sizeToReserve) { - return VirtualAlloc(0, sizeToReserve, MEM_RESERVE, PAGE_READWRITE); +std::unique_ptr OSMemory::create() { + return std::make_unique(); } -void OSMemory::releaseCpuAddressRange(void *reservedCpuAddressRange, size_t /* reservedSize */) { - VirtualFree(reservedCpuAddressRange, 0, MEM_RELEASE); +void *OSMemoryWindows::reserveCpuAddressRange(size_t sizeToReserve) { + return virtualAllocWrapper(0, sizeToReserve, MEM_RESERVE, PAGE_READWRITE); +} + +void OSMemoryWindows::releaseCpuAddressRange(void *reservedCpuAddressRange, size_t /* reservedSize */) { + virtualFreeWrapper(reservedCpuAddressRange, 0, MEM_RELEASE); +} + +LPVOID OSMemoryWindows::virtualAllocWrapper(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) { + return VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect); +} + +BOOL OSMemoryWindows::virtualFreeWrapper(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType) { + return VirtualFree(lpAddress, dwSize, dwFreeType); } } // namespace NEO diff --git a/runtime/os_interface/windows/os_memory_win.h b/runtime/os_interface/windows/os_memory_win.h new file mode 100644 index 0000000000..843d549915 --- /dev/null +++ b/runtime/os_interface/windows/os_memory_win.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2019 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "runtime/os_interface/os_memory.h" + +#include + +namespace NEO { + +class OSMemoryWindows : public OSMemory { + public: + OSMemoryWindows() = default; + void *reserveCpuAddressRange(size_t sizeToReserve) override; + void releaseCpuAddressRange(void *reservedCpuAddressRange, size_t reservedSize) override; + + protected: + MOCKABLE_VIRTUAL LPVOID virtualAllocWrapper(LPVOID, SIZE_T, DWORD, DWORD); + MOCKABLE_VIRTUAL BOOL virtualFreeWrapper(LPVOID, SIZE_T, DWORD); +}; + +}; // namespace NEO diff --git a/unit_tests/os_interface/linux/CMakeLists.txt b/unit_tests/os_interface/linux/CMakeLists.txt index 49c94afbcb..870cd29597 100644 --- a/unit_tests/os_interface/linux/CMakeLists.txt +++ b/unit_tests/os_interface/linux/CMakeLists.txt @@ -27,6 +27,7 @@ set(IGDRCL_SRCS_tests_os_interface_linux ${CMAKE_CURRENT_SOURCE_DIR}/drm_mock.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drm_mock.h ${CMAKE_CURRENT_SOURCE_DIR}/drm_neo_create.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/drm_os_memory_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drm_residency_handler_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drm_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hw_info_config_linux_tests.cpp diff --git a/unit_tests/os_interface/linux/drm_os_memory_tests.cpp b/unit_tests/os_interface/linux/drm_os_memory_tests.cpp new file mode 100644 index 0000000000..debb613d4e --- /dev/null +++ b/unit_tests/os_interface/linux/drm_os_memory_tests.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "runtime/os_interface/linux/os_memory_linux.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using ::testing::_; + +namespace NEO { + +class MockOSMemoryLinux : public OSMemoryLinux { + public: + static std::unique_ptr create() { + return std::make_unique(); + } + + MOCK_METHOD6(mmapWrapper, void *(void *, size_t, int, int, int, off_t)); + MOCK_METHOD2(munmapWrapper, int(void *, size_t)); +}; + +TEST(OSMemoryLinux, givenOSMemoryLinuxWhenReserveCpuAddressRangeIsCalledThenMinusOneIsPassedToMmapAsFdParam) { + auto mockOSMemoryLinux = MockOSMemoryLinux::create(); + + EXPECT_CALL(*mockOSMemoryLinux, mmapWrapper(_, _, _, _, -1, _)); + + size_t size = 0x1024; + auto reservedCpuAddr = mockOSMemoryLinux->reserveCpuAddressRange(size); + + EXPECT_CALL(*mockOSMemoryLinux, munmapWrapper(reservedCpuAddr, size)); + + mockOSMemoryLinux->releaseCpuAddressRange(reservedCpuAddr, size); +} + +}; // namespace NEO diff --git a/unit_tests/os_interface/os_memory_tests.cpp b/unit_tests/os_interface/os_memory_tests.cpp index 667ffce49a..aab8351247 100644 --- a/unit_tests/os_interface/os_memory_tests.cpp +++ b/unit_tests/os_interface/os_memory_tests.cpp @@ -12,8 +12,9 @@ using namespace NEO; TEST(OSMemory, reserveCpuAddressRange) { + auto osMemory = OSMemory::create(); size_t reservedCpuAddressRangeSize = 1024; - auto reservedCpuAddressRange = OSMemory::reserveCpuAddressRange(reservedCpuAddressRangeSize); + auto reservedCpuAddressRange = osMemory->reserveCpuAddressRange(reservedCpuAddressRangeSize); EXPECT_NE(reservedCpuAddressRange, nullptr); - OSMemory::releaseCpuAddressRange(reservedCpuAddressRange, reservedCpuAddressRangeSize); + osMemory->releaseCpuAddressRange(reservedCpuAddressRange, reservedCpuAddressRangeSize); }