aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoss Brunton <ross@codeplay.com>2025-09-09 12:43:50 +0100
committerRoss Brunton <ross@codeplay.com>2025-09-09 12:43:50 +0100
commit78270d0b496a408d2ffdeb15b81e9235cd98bdaf (patch)
tree0ac327bcef02f73af4591c7e3745c30f348e1821
parentd2a99ef7081ed92ae4ed334ede1d8bec193daa8d (diff)
downloadllvm-users/RossBrunton/newMemInfo3.zip
llvm-users/RossBrunton/newMemInfo3.tar.gz
llvm-users/RossBrunton/newMemInfo3.tar.bz2
[Offload] `olGetMemInfo`users/RossBrunton/newMemInfo3
This method queries an allocation allocated by `olMemAlloc`.
-rw-r--r--offload/liboffload/API/Memory.td55
-rw-r--r--offload/liboffload/src/OffloadImpl.cpp58
-rw-r--r--offload/unittests/OffloadAPI/CMakeLists.txt4
-rw-r--r--offload/unittests/OffloadAPI/memory/olGetMemInfo.cpp140
-rw-r--r--offload/unittests/OffloadAPI/memory/olGetMemInfoSize.cpp70
5 files changed, 326 insertions, 1 deletions
diff --git a/offload/liboffload/API/Memory.td b/offload/liboffload/API/Memory.td
index a24f05e..c04005e 100644
--- a/offload/liboffload/API/Memory.td
+++ b/offload/liboffload/API/Memory.td
@@ -21,6 +21,9 @@ def ol_alloc_type_t : Enum {
def olMemAlloc : Function {
let desc = "Creates a memory allocation on the specified device.";
+ let details = [
+ "Platforms will not allocate at a location equal to the host's `nullptr`"
+ ];
let params = [
Param<"ol_device_handle_t", "Device", "handle of the device to allocate on", PARAM_IN>,
Param<"ol_alloc_type_t", "Type", "type of the allocation", PARAM_IN>,
@@ -81,3 +84,55 @@ def olMemFill : Function {
Return<"OL_ERRC_INVALID_SIZE", ["`FillSize % PatternSize != 0`"]>
];
}
+
+def ol_mem_info_t : Enum {
+ let desc = "Supported memory info.";
+ let is_typed = 1;
+ let etors = [
+ TaggedEtor<"DEVICE", "ol_device_handle_t", "The handle of the device associated with the allocation.">,
+ TaggedEtor<"BASE", "void *", "Base address of this allocation.">,
+ TaggedEtor<"SIZE", "size_t", "Size of this allocation in bytes.">,
+ TaggedEtor<"TYPE", "ol_alloc_type_t", "Type of this allocation.">,
+ ];
+}
+
+def olGetMemInfo : Function {
+ let desc = "Queries the given property of a memory allocation allocated with olMemAlloc.";
+ let details = [
+ "`olGetMemInfoSize` can be used to query the storage size required for the given query.",
+ "The provided pointer can point to any location inside the allocation.",
+ ];
+ let params = [
+ Param<"ol_platform_handle_t", "Platform", "platform that allocated this memory", PARAM_IN>,
+ Param<"const void *", "Ptr", "pointer to the allocated memory", PARAM_IN>,
+ Param<"ol_mem_info_t", "PropName", "type of the info to retrieve", PARAM_IN>,
+ Param<"size_t", "PropSize", "the number of bytes pointed to by PropValue.", PARAM_IN>,
+ TypeTaggedParam<"void*", "PropValue", "array of bytes holding the info. "
+ "If Size is not equal to or greater to the real number of bytes needed to return the info "
+ "then the OL_ERRC_INVALID_SIZE error is returned and pPlatformInfo is not used.", PARAM_OUT,
+ TypeInfo<"PropName" , "PropSize">>
+ ];
+ let returns = [
+ Return<"OL_ERRC_INVALID_SIZE", [
+ "`PropSize == 0`",
+ "If `PropSize` is less than the real number of bytes needed to return the info."
+ ]>,
+ Return<"OL_ERRC_NOT_FOUND", ["memory was not allocated by this platform"]>
+ ];
+}
+
+def olGetMemInfoSize : Function {
+ let desc = "Returns the storage size of the given queue query.";
+ let details = [
+ "The provided pointer can point to any location inside the allocation.",
+ ];
+ let params = [
+ Param<"ol_platform_handle_t", "Platform", "platform that allocated this memory", PARAM_IN>,
+ Param<"const void *", "Ptr", "pointer to the allocated memory", PARAM_IN>,
+ Param<"ol_mem_info_t", "PropName", "type of the info to query", PARAM_IN>,
+ Param<"size_t*", "PropSizeRet", "pointer to the number of bytes required to store the query", PARAM_OUT>
+ ];
+ let returns = [
+ Return<"OL_ERRC_NOT_FOUND", ["memory was not allocated by this platform"]>
+ ];
+}
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 00d1b83..e55dd71 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -614,6 +614,21 @@ TargetAllocTy convertOlToPluginAllocTy(ol_alloc_type_t Type) {
}
}
+ol_alloc_type_t convertPluginToOlAllocTy(TargetAllocTy Type) {
+ switch (Type) {
+ case TARGET_ALLOC_DEVICE:
+ return OL_ALLOC_TYPE_DEVICE;
+ case TARGET_ALLOC_HOST:
+ return OL_ALLOC_TYPE_HOST;
+ case TARGET_ALLOC_SHARED:
+ return OL_ALLOC_TYPE_MANAGED;
+ default:
+ // Seems a reasonable default, although this default should never get hit
+ // with allocations made through liboffload
+ return OL_ALLOC_TYPE_MANAGED;
+ }
+}
+
Error olMemAlloc_impl(ol_device_handle_t Device, ol_alloc_type_t Type,
size_t Size, void **AllocationOut) {
auto Alloc =
@@ -656,6 +671,49 @@ Error olCreateQueue_impl(ol_device_handle_t Device, ol_queue_handle_t *Queue) {
return Error::success();
}
+Error olGetMemInfoImplDetail(ol_platform_handle_t Platform, const void *Ptr,
+ ol_mem_info_t PropName, size_t PropSize,
+ void *PropValue, size_t *PropSizeRet) {
+ InfoWriter Info(PropSize, PropValue, PropSizeRet);
+
+ Expected<MemoryInfoTy> MemInfo = Platform->Plugin->getMemoryInfo(Ptr);
+ if (auto Err = MemInfo.takeError())
+ return Err;
+
+ switch (PropName) {
+ case OL_MEM_INFO_DEVICE: {
+ auto Pos = std::find_if(
+ Platform->Devices.begin(), Platform->Devices.end(),
+ [&](auto &OlDevice) { return OlDevice->Device == MemInfo->Device; });
+ return Info.write<ol_device_handle_t>(Pos->get());
+ }
+ case OL_MEM_INFO_BASE:
+ return Info.write<void *>(MemInfo->Base);
+ case OL_MEM_INFO_SIZE:
+ return Info.write<size_t>(MemInfo->Size);
+ case OL_MEM_INFO_TYPE:
+ return Info.write<ol_alloc_type_t>(convertPluginToOlAllocTy(MemInfo->Type));
+ default:
+ return createOffloadError(ErrorCode::INVALID_ENUMERATION,
+ "olGetMemInfo enum '%i' is invalid", PropName);
+ }
+
+ return Error::success();
+}
+
+Error olGetMemInfo_impl(ol_platform_handle_t Platform, const void *Ptr,
+ ol_mem_info_t PropName, size_t PropSize,
+ void *PropValue) {
+ return olGetMemInfoImplDetail(Platform, Ptr, PropName, PropSize, PropValue,
+ nullptr);
+}
+
+Error olGetMemInfoSize_impl(ol_platform_handle_t Platform, const void *Ptr,
+ ol_mem_info_t PropName, size_t *PropSizeRet) {
+ return olGetMemInfoImplDetail(Platform, Ptr, PropName, 0, nullptr,
+ PropSizeRet);
+}
+
Error olDestroyQueue_impl(ol_queue_handle_t Queue) {
auto *Device = Queue->Device;
// This is safe; as soon as olDestroyQueue is called it is not possible to add
diff --git a/offload/unittests/OffloadAPI/CMakeLists.txt b/offload/unittests/OffloadAPI/CMakeLists.txt
index b2d51442..b31d33e 100644
--- a/offload/unittests/OffloadAPI/CMakeLists.txt
+++ b/offload/unittests/OffloadAPI/CMakeLists.txt
@@ -27,7 +27,9 @@ add_offload_unittest("memory"
memory/olMemAlloc.cpp
memory/olMemFill.cpp
memory/olMemFree.cpp
- memory/olMemcpy.cpp)
+ memory/olMemcpy.cpp
+ memory/olGetMemInfo.cpp
+ memory/olGetMemInfoSize.cpp)
add_offload_unittest("platform"
platform/olGetPlatformInfo.cpp
diff --git a/offload/unittests/OffloadAPI/memory/olGetMemInfo.cpp b/offload/unittests/OffloadAPI/memory/olGetMemInfo.cpp
new file mode 100644
index 0000000..b6ed3af
--- /dev/null
+++ b/offload/unittests/OffloadAPI/memory/olGetMemInfo.cpp
@@ -0,0 +1,140 @@
+//===------- Offload API tests - olGetMemInfo -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "../common/Fixtures.hpp"
+#include <OffloadAPI.h>
+#include <gtest/gtest.h>
+
+constexpr size_t SIZE = 1024;
+
+struct olGetMemInfoBaseTest : OffloadDeviceTest {
+ void *OffsetPtr() { return &reinterpret_cast<char *>(Ptr)[123]; }
+
+ void *Ptr;
+};
+
+template <ol_alloc_type_t AllocType>
+struct olGetMemInfoTest : olGetMemInfoBaseTest {
+ void SetUp() override {
+ RETURN_ON_FATAL_FAILURE(OffloadDeviceTest::SetUp());
+ ASSERT_SUCCESS(olMemAlloc(Device, AllocType, SIZE, &Ptr));
+ }
+
+ void TearDown() override {
+ ASSERT_SUCCESS(olMemFree(Platform, Ptr));
+ RETURN_ON_FATAL_FAILURE(OffloadDeviceTest::TearDown());
+ }
+};
+using olGetMemInfoDeviceTest = olGetMemInfoTest<OL_ALLOC_TYPE_DEVICE>;
+OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olGetMemInfoDeviceTest);
+using olGetMemInfoManagedTest = olGetMemInfoTest<OL_ALLOC_TYPE_MANAGED>;
+OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olGetMemInfoManagedTest);
+using olGetMemInfoHostTest = olGetMemInfoTest<OL_ALLOC_TYPE_HOST>;
+OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olGetMemInfoHostTest);
+
+#define PER_ALLOC_TEST(FUNCTION) \
+ TEST_P(olGetMemInfoDeviceTest, FUNCTION) { \
+ FUNCTION(this, Ptr, OL_ALLOC_TYPE_DEVICE); \
+ } \
+ TEST_P(olGetMemInfoManagedTest, FUNCTION) { \
+ FUNCTION(this, Ptr, OL_ALLOC_TYPE_MANAGED); \
+ } \
+ TEST_P(olGetMemInfoHostTest, FUNCTION) { \
+ FUNCTION(this, OffsetPtr(), OL_ALLOC_TYPE_HOST); \
+ } \
+ TEST_P(olGetMemInfoDeviceTest, FUNCTION##Offset) { \
+ FUNCTION(this, Ptr, OL_ALLOC_TYPE_DEVICE); \
+ } \
+ TEST_P(olGetMemInfoManagedTest, FUNCTION##Offset) { \
+ FUNCTION(this, OffsetPtr(), OL_ALLOC_TYPE_MANAGED); \
+ } \
+ TEST_P(olGetMemInfoHostTest, FUNCTION##Offset) { \
+ FUNCTION(this, OffsetPtr(), OL_ALLOC_TYPE_HOST); \
+ }
+
+void SuccessDevice(olGetMemInfoBaseTest *Fixture, void *Ptr,
+ ol_alloc_type_t Type) {
+ ol_device_handle_t RetrievedDevice;
+ ASSERT_SUCCESS(olGetMemInfo(Fixture->Platform, Fixture->Ptr,
+ OL_MEM_INFO_DEVICE, sizeof(RetrievedDevice),
+ &RetrievedDevice));
+ ASSERT_EQ(RetrievedDevice, Fixture->Device);
+}
+PER_ALLOC_TEST(SuccessDevice);
+
+void SuccessBase(olGetMemInfoBaseTest *Fixture, void *Ptr,
+ ol_alloc_type_t Type) {
+ void *RetrievedBase;
+ ASSERT_SUCCESS(olGetMemInfo(Fixture->Platform, Fixture->Ptr, OL_MEM_INFO_BASE,
+ sizeof(RetrievedBase), &RetrievedBase));
+ ASSERT_EQ(RetrievedBase, Fixture->Ptr);
+}
+PER_ALLOC_TEST(SuccessBase);
+
+void SuccessSize(olGetMemInfoBaseTest *Fixture, void *Ptr,
+ ol_alloc_type_t Type) {
+ size_t RetrievedSize;
+ ASSERT_SUCCESS(olGetMemInfo(Fixture->Platform, Fixture->Ptr, OL_MEM_INFO_SIZE,
+ sizeof(RetrievedSize), &RetrievedSize));
+ ASSERT_EQ(RetrievedSize, SIZE);
+}
+PER_ALLOC_TEST(SuccessSize);
+
+void SuccessType(olGetMemInfoBaseTest *Fixture, void *Ptr,
+ ol_alloc_type_t Type) {
+ ol_alloc_type_t RetrievedType;
+ ASSERT_SUCCESS(olGetMemInfo(Fixture->Platform, Fixture->Ptr, OL_MEM_INFO_TYPE,
+ sizeof(RetrievedType), &RetrievedType));
+ ASSERT_EQ(RetrievedType, Type);
+}
+PER_ALLOC_TEST(SuccessType);
+
+TEST_P(olGetMemInfoDeviceTest, InvalidNotFound) {
+ // Assuming that we aren't unlucky and happen to get 0x1234 as a random
+ // pointer
+ void *RetrievedBase;
+ ASSERT_ERROR(OL_ERRC_NOT_FOUND,
+ olGetMemInfo(Platform, reinterpret_cast<void *>(0x1234),
+ OL_MEM_INFO_BASE, sizeof(RetrievedBase),
+ &RetrievedBase));
+}
+
+TEST_P(olGetMemInfoDeviceTest, InvalidNullPtr) {
+ ol_device_handle_t RetrievedDevice;
+ ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER,
+ olGetMemInfo(Platform, nullptr, OL_MEM_INFO_DEVICE,
+ sizeof(RetrievedDevice), &RetrievedDevice));
+}
+
+TEST_P(olGetMemInfoDeviceTest, NullPlatform) {
+ ol_device_handle_t RetrievedDevice;
+ ASSERT_ERROR(OL_ERRC_INVALID_NULL_HANDLE,
+ olGetMemInfo(nullptr, Ptr, OL_MEM_INFO_DEVICE,
+ sizeof(RetrievedDevice), &RetrievedDevice));
+}
+
+TEST_P(olGetMemInfoDeviceTest, InvalidSizeZero) {
+ ol_device_handle_t RetrievedDevice;
+ ASSERT_ERROR(
+ OL_ERRC_INVALID_SIZE,
+ olGetMemInfo(Platform, Ptr, OL_MEM_INFO_DEVICE, 0, &RetrievedDevice));
+}
+
+TEST_P(olGetMemInfoDeviceTest, InvalidSizeSmall) {
+ ol_device_handle_t RetrievedDevice;
+ ASSERT_ERROR(OL_ERRC_INVALID_SIZE,
+ olGetMemInfo(Platform, Ptr, OL_MEM_INFO_DEVICE,
+ sizeof(RetrievedDevice) - 1, &RetrievedDevice));
+}
+
+TEST_P(olGetMemInfoDeviceTest, InvalidNullPointerPropValue) {
+ ol_device_handle_t RetrievedDevice;
+ ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER,
+ olGetMemInfo(Platform, Ptr, OL_MEM_INFO_DEVICE,
+ sizeof(RetrievedDevice), nullptr));
+}
diff --git a/offload/unittests/OffloadAPI/memory/olGetMemInfoSize.cpp b/offload/unittests/OffloadAPI/memory/olGetMemInfoSize.cpp
new file mode 100644
index 0000000..907738e
--- /dev/null
+++ b/offload/unittests/OffloadAPI/memory/olGetMemInfoSize.cpp
@@ -0,0 +1,70 @@
+//===------- Offload API tests - olGetMemInfoSize -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <OffloadAPI.h>
+
+#include "../common/Fixtures.hpp"
+
+struct olGetMemInfoSizeTest : OffloadDeviceTest {
+ void *OffsetPtr() { return &reinterpret_cast<char *>(Ptr)[123]; }
+
+ void SetUp() override {
+ RETURN_ON_FATAL_FAILURE(OffloadDeviceTest::SetUp());
+ ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, 0x1024, &Ptr));
+ }
+
+ void TearDown() override {
+ ASSERT_SUCCESS(olMemFree(Platform, Ptr));
+ RETURN_ON_FATAL_FAILURE(OffloadDeviceTest::TearDown());
+ }
+
+ void *Ptr;
+};
+OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olGetMemInfoSizeTest);
+
+TEST_P(olGetMemInfoSizeTest, SuccessDevice) {
+ size_t Size = 0;
+ ASSERT_SUCCESS(olGetMemInfoSize(Platform, Ptr, OL_MEM_INFO_DEVICE, &Size));
+ ASSERT_EQ(Size, sizeof(ol_device_handle_t));
+}
+
+TEST_P(olGetMemInfoSizeTest, SuccessBase) {
+ size_t Size = 0;
+ ASSERT_SUCCESS(olGetMemInfoSize(Platform, Ptr, OL_MEM_INFO_BASE, &Size));
+ ASSERT_EQ(Size, sizeof(void *));
+}
+
+TEST_P(olGetMemInfoSizeTest, SuccessSize) {
+ size_t Size = 0;
+ ASSERT_SUCCESS(olGetMemInfoSize(Platform, Ptr, OL_MEM_INFO_SIZE, &Size));
+ ASSERT_EQ(Size, sizeof(size_t));
+}
+
+TEST_P(olGetMemInfoSizeTest, SuccessType) {
+ size_t Size = 0;
+ ASSERT_SUCCESS(olGetMemInfoSize(Platform, Ptr, OL_MEM_INFO_TYPE, &Size));
+ ASSERT_EQ(Size, sizeof(ol_alloc_type_t));
+}
+
+TEST_P(olGetMemInfoSizeTest, InvalidNullHandle) {
+ size_t Size = 0;
+ ASSERT_ERROR(OL_ERRC_INVALID_NULL_HANDLE,
+ olGetMemInfoSize(nullptr, Ptr, OL_MEM_INFO_DEVICE, &Size));
+}
+
+TEST_P(olGetMemInfoSizeTest, InvalidSymbolInfoEnumeration) {
+ size_t Size = 0;
+ ASSERT_ERROR(
+ OL_ERRC_INVALID_ENUMERATION,
+ olGetMemInfoSize(Platform, Ptr, OL_MEM_INFO_FORCE_UINT32, &Size));
+}
+
+TEST_P(olGetMemInfoSizeTest, InvalidNullPointer) {
+ ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER,
+ olGetMemInfoSize(Platform, Ptr, OL_MEM_INFO_DEVICE, nullptr));
+}