Skip to content

Commit dc2da9f

Browse files
RossBruntongithub-actions[bot]
authored andcommitted
Automerge: [Offload] Add olGetMemInfo with platform-less API (#159581)
2 parents a30ebe0 + ea0e518 commit dc2da9f

File tree

5 files changed

+300
-1
lines changed

5 files changed

+300
-1
lines changed

offload/liboffload/API/Memory.td

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,56 @@ def olMemFree : Function {
4545
let returns = [];
4646
}
4747

48+
def ol_mem_info_t : Enum {
49+
let desc = "Supported memory info.";
50+
let is_typed = 1;
51+
let etors = [
52+
TaggedEtor<"DEVICE", "ol_device_handle_t", "The handle of the device associated with the allocation.">,
53+
TaggedEtor<"BASE", "void *", "Base address of this allocation.">,
54+
TaggedEtor<"SIZE", "size_t", "Size of this allocation in bytes.">,
55+
TaggedEtor<"TYPE", "ol_alloc_type_t", "Type of this allocation.">,
56+
];
57+
}
58+
59+
def olGetMemInfo : Function {
60+
let desc = "Queries the given property of a memory allocation allocated with olMemAlloc.";
61+
let details = [
62+
"`olGetMemInfoSize` can be used to query the storage size required for the given query.",
63+
"The provided pointer can point to any location inside the allocation.",
64+
];
65+
let params = [
66+
Param<"const void *", "Ptr", "pointer to the allocated memory", PARAM_IN>,
67+
Param<"ol_mem_info_t", "PropName", "type of the info to retrieve", PARAM_IN>,
68+
Param<"size_t", "PropSize", "the number of bytes pointed to by PropValue.", PARAM_IN>,
69+
TypeTaggedParam<"void*", "PropValue", "array of bytes holding the info. "
70+
"If Size is not equal to or greater to the real number of bytes needed to return the info "
71+
"then the OL_ERRC_INVALID_SIZE error is returned and pPlatformInfo is not used.", PARAM_OUT,
72+
TypeInfo<"PropName" , "PropSize">>
73+
];
74+
let returns = [
75+
Return<"OL_ERRC_INVALID_SIZE", [
76+
"`PropSize == 0`",
77+
"If `PropSize` is less than the real number of bytes needed to return the info."
78+
]>,
79+
Return<"OL_ERRC_NOT_FOUND", ["memory was not allocated by liboffload"]>
80+
];
81+
}
82+
83+
def olGetMemInfoSize : Function {
84+
let desc = "Returns the storage size of the given queue query.";
85+
let details = [
86+
"The provided pointer can point to any location inside the allocation.",
87+
];
88+
let params = [
89+
Param<"const void *", "Ptr", "pointer to the allocated memory", PARAM_IN>,
90+
Param<"ol_mem_info_t", "PropName", "type of the info to query", PARAM_IN>,
91+
Param<"size_t*", "PropSizeRet", "pointer to the number of bytes required to store the query", PARAM_OUT>
92+
];
93+
let returns = [
94+
Return<"OL_ERRC_NOT_FOUND", ["memory was not allocated by liboffload"]>
95+
];
96+
}
97+
4898
def olMemcpy : Function {
4999
let desc = "Enqueue a memcpy operation.";
50100
let details = [

offload/liboffload/src/OffloadImpl.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,60 @@ Error olMemFree_impl(void *Address) {
699699
return Error::success();
700700
}
701701

702+
Error olGetMemInfoImplDetail(const void *Ptr, ol_mem_info_t PropName,
703+
size_t PropSize, void *PropValue,
704+
size_t *PropSizeRet) {
705+
InfoWriter Info(PropSize, PropValue, PropSizeRet);
706+
std::lock_guard<std::mutex> Lock(OffloadContext::get().AllocInfoMapMutex);
707+
708+
auto &AllocBases = OffloadContext::get().AllocBases;
709+
auto &AllocInfoMap = OffloadContext::get().AllocInfoMap;
710+
const AllocInfo *Alloc = nullptr;
711+
if (AllocInfoMap.contains(Ptr)) {
712+
// Fast case, we have been given the base pointer directly
713+
Alloc = &AllocInfoMap.at(Ptr);
714+
} else {
715+
// Slower case, we need to look up the base pointer first
716+
// Find the first memory allocation whose end is after the target pointer,
717+
// and then check to see if it is in range
718+
auto Loc = std::lower_bound(AllocBases.begin(), AllocBases.end(), Ptr,
719+
[&](const void *Iter, const void *Val) {
720+
return AllocInfoMap.at(Iter).End <= Val;
721+
});
722+
if (Loc == AllocBases.end() || Ptr < AllocInfoMap.at(*Loc).Start)
723+
return Plugin::error(ErrorCode::NOT_FOUND,
724+
"allocated memory information not found");
725+
Alloc = &AllocInfoMap.at(*Loc);
726+
}
727+
728+
switch (PropName) {
729+
case OL_MEM_INFO_DEVICE:
730+
return Info.write<ol_device_handle_t>(Alloc->Device);
731+
case OL_MEM_INFO_BASE:
732+
return Info.write<void *>(Alloc->Start);
733+
case OL_MEM_INFO_SIZE:
734+
return Info.write<size_t>(static_cast<char *>(Alloc->End) -
735+
static_cast<char *>(Alloc->Start));
736+
case OL_MEM_INFO_TYPE:
737+
return Info.write<ol_alloc_type_t>(Alloc->Type);
738+
default:
739+
return createOffloadError(ErrorCode::INVALID_ENUMERATION,
740+
"olGetMemInfo enum '%i' is invalid", PropName);
741+
}
742+
743+
return Error::success();
744+
}
745+
746+
Error olGetMemInfo_impl(const void *Ptr, ol_mem_info_t PropName,
747+
size_t PropSize, void *PropValue) {
748+
return olGetMemInfoImplDetail(Ptr, PropName, PropSize, PropValue, nullptr);
749+
}
750+
751+
Error olGetMemInfoSize_impl(const void *Ptr, ol_mem_info_t PropName,
752+
size_t *PropSizeRet) {
753+
return olGetMemInfoImplDetail(Ptr, PropName, 0, nullptr, PropSizeRet);
754+
}
755+
702756
Error olCreateQueue_impl(ol_device_handle_t Device, ol_queue_handle_t *Queue) {
703757
auto CreatedQueue = std::make_unique<ol_queue_impl_t>(nullptr, Device);
704758

offload/unittests/OffloadAPI/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ add_offload_unittest("memory"
2727
memory/olMemAlloc.cpp
2828
memory/olMemFill.cpp
2929
memory/olMemFree.cpp
30-
memory/olMemcpy.cpp)
30+
memory/olMemcpy.cpp
31+
memory/olGetMemInfo.cpp
32+
memory/olGetMemInfoSize.cpp)
3133

3234
add_offload_unittest("platform"
3335
platform/olGetPlatformInfo.cpp
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//===------- Offload API tests - olGetMemInfo -----------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "../common/Fixtures.hpp"
10+
#include <OffloadAPI.h>
11+
#include <gtest/gtest.h>
12+
13+
constexpr size_t SIZE = 1024;
14+
15+
struct olGetMemInfoBaseTest : OffloadDeviceTest {
16+
void *OffsetPtr() { return &reinterpret_cast<char *>(Ptr)[123]; }
17+
18+
void *Ptr;
19+
};
20+
21+
template <ol_alloc_type_t AllocType>
22+
struct olGetMemInfoTest : olGetMemInfoBaseTest {
23+
void SetUp() override {
24+
RETURN_ON_FATAL_FAILURE(OffloadDeviceTest::SetUp());
25+
ASSERT_SUCCESS(olMemAlloc(Device, AllocType, SIZE, &Ptr));
26+
}
27+
28+
void TearDown() override {
29+
ASSERT_SUCCESS(olMemFree(Ptr));
30+
RETURN_ON_FATAL_FAILURE(OffloadDeviceTest::TearDown());
31+
}
32+
};
33+
using olGetMemInfoDeviceTest = olGetMemInfoTest<OL_ALLOC_TYPE_DEVICE>;
34+
OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olGetMemInfoDeviceTest);
35+
using olGetMemInfoManagedTest = olGetMemInfoTest<OL_ALLOC_TYPE_MANAGED>;
36+
OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olGetMemInfoManagedTest);
37+
using olGetMemInfoHostTest = olGetMemInfoTest<OL_ALLOC_TYPE_HOST>;
38+
OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olGetMemInfoHostTest);
39+
40+
#define PER_ALLOC_TEST(FUNCTION) \
41+
TEST_P(olGetMemInfoDeviceTest, FUNCTION) { \
42+
FUNCTION(this, Ptr, OL_ALLOC_TYPE_DEVICE); \
43+
} \
44+
TEST_P(olGetMemInfoManagedTest, FUNCTION) { \
45+
FUNCTION(this, Ptr, OL_ALLOC_TYPE_MANAGED); \
46+
} \
47+
TEST_P(olGetMemInfoHostTest, FUNCTION) { \
48+
FUNCTION(this, OffsetPtr(), OL_ALLOC_TYPE_HOST); \
49+
} \
50+
TEST_P(olGetMemInfoDeviceTest, FUNCTION##Offset) { \
51+
FUNCTION(this, Ptr, OL_ALLOC_TYPE_DEVICE); \
52+
} \
53+
TEST_P(olGetMemInfoManagedTest, FUNCTION##Offset) { \
54+
FUNCTION(this, OffsetPtr(), OL_ALLOC_TYPE_MANAGED); \
55+
} \
56+
TEST_P(olGetMemInfoHostTest, FUNCTION##Offset) { \
57+
FUNCTION(this, OffsetPtr(), OL_ALLOC_TYPE_HOST); \
58+
}
59+
60+
void SuccessDevice(olGetMemInfoBaseTest *Fixture, void *Ptr,
61+
ol_alloc_type_t Type) {
62+
ol_device_handle_t RetrievedDevice;
63+
ASSERT_SUCCESS(olGetMemInfo(Fixture->Ptr, OL_MEM_INFO_DEVICE,
64+
sizeof(RetrievedDevice), &RetrievedDevice));
65+
ASSERT_EQ(RetrievedDevice, Fixture->Device);
66+
}
67+
PER_ALLOC_TEST(SuccessDevice);
68+
69+
void SuccessBase(olGetMemInfoBaseTest *Fixture, void *Ptr,
70+
ol_alloc_type_t Type) {
71+
void *RetrievedBase;
72+
ASSERT_SUCCESS(olGetMemInfo(Fixture->Ptr, OL_MEM_INFO_BASE,
73+
sizeof(RetrievedBase), &RetrievedBase));
74+
ASSERT_EQ(RetrievedBase, Fixture->Ptr);
75+
}
76+
PER_ALLOC_TEST(SuccessBase);
77+
78+
void SuccessSize(olGetMemInfoBaseTest *Fixture, void *Ptr,
79+
ol_alloc_type_t Type) {
80+
size_t RetrievedSize;
81+
ASSERT_SUCCESS(olGetMemInfo(Fixture->Ptr, OL_MEM_INFO_SIZE,
82+
sizeof(RetrievedSize), &RetrievedSize));
83+
ASSERT_EQ(RetrievedSize, SIZE);
84+
}
85+
PER_ALLOC_TEST(SuccessSize);
86+
87+
void SuccessType(olGetMemInfoBaseTest *Fixture, void *Ptr,
88+
ol_alloc_type_t Type) {
89+
ol_alloc_type_t RetrievedType;
90+
ASSERT_SUCCESS(olGetMemInfo(Fixture->Ptr, OL_MEM_INFO_TYPE,
91+
sizeof(RetrievedType), &RetrievedType));
92+
ASSERT_EQ(RetrievedType, Type);
93+
}
94+
PER_ALLOC_TEST(SuccessType);
95+
96+
TEST_P(olGetMemInfoDeviceTest, InvalidNotFound) {
97+
// Assuming that we aren't unlucky and happen to get 0x1234 as a random
98+
// pointer
99+
void *RetrievedBase;
100+
ASSERT_ERROR(OL_ERRC_NOT_FOUND,
101+
olGetMemInfo(reinterpret_cast<void *>(0x1234), OL_MEM_INFO_BASE,
102+
sizeof(RetrievedBase), &RetrievedBase));
103+
}
104+
105+
TEST_P(olGetMemInfoDeviceTest, InvalidNullPtr) {
106+
ol_device_handle_t RetrievedDevice;
107+
ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER,
108+
olGetMemInfo(nullptr, OL_MEM_INFO_DEVICE,
109+
sizeof(RetrievedDevice), &RetrievedDevice));
110+
}
111+
112+
TEST_P(olGetMemInfoDeviceTest, InvalidSizeZero) {
113+
ol_device_handle_t RetrievedDevice;
114+
ASSERT_ERROR(OL_ERRC_INVALID_SIZE,
115+
olGetMemInfo(Ptr, OL_MEM_INFO_DEVICE, 0, &RetrievedDevice));
116+
}
117+
118+
TEST_P(olGetMemInfoDeviceTest, InvalidSizeSmall) {
119+
ol_device_handle_t RetrievedDevice;
120+
ASSERT_ERROR(OL_ERRC_INVALID_SIZE,
121+
olGetMemInfo(Ptr, OL_MEM_INFO_DEVICE,
122+
sizeof(RetrievedDevice) - 1, &RetrievedDevice));
123+
}
124+
125+
TEST_P(olGetMemInfoDeviceTest, InvalidNullPointerPropValue) {
126+
ol_device_handle_t RetrievedDevice;
127+
ASSERT_ERROR(
128+
OL_ERRC_INVALID_NULL_POINTER,
129+
olGetMemInfo(Ptr, OL_MEM_INFO_DEVICE, sizeof(RetrievedDevice), nullptr));
130+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//===------- Offload API tests - olGetMemInfoSize -------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <OffloadAPI.h>
10+
11+
#include "../common/Fixtures.hpp"
12+
13+
struct olGetMemInfoSizeTest : OffloadDeviceTest {
14+
void *OffsetPtr() { return &reinterpret_cast<char *>(Ptr)[123]; }
15+
16+
void SetUp() override {
17+
RETURN_ON_FATAL_FAILURE(OffloadDeviceTest::SetUp());
18+
ASSERT_SUCCESS(olMemAlloc(Device, OL_ALLOC_TYPE_DEVICE, 0x1024, &Ptr));
19+
}
20+
21+
void TearDown() override {
22+
ASSERT_SUCCESS(olMemFree(Ptr));
23+
RETURN_ON_FATAL_FAILURE(OffloadDeviceTest::TearDown());
24+
}
25+
26+
void *Ptr;
27+
};
28+
OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olGetMemInfoSizeTest);
29+
30+
TEST_P(olGetMemInfoSizeTest, SuccessDevice) {
31+
size_t Size = 0;
32+
ASSERT_SUCCESS(olGetMemInfoSize(Ptr, OL_MEM_INFO_DEVICE, &Size));
33+
ASSERT_EQ(Size, sizeof(ol_device_handle_t));
34+
}
35+
36+
TEST_P(olGetMemInfoSizeTest, SuccessBase) {
37+
size_t Size = 0;
38+
ASSERT_SUCCESS(olGetMemInfoSize(Ptr, OL_MEM_INFO_BASE, &Size));
39+
ASSERT_EQ(Size, sizeof(void *));
40+
}
41+
42+
TEST_P(olGetMemInfoSizeTest, SuccessSize) {
43+
size_t Size = 0;
44+
ASSERT_SUCCESS(olGetMemInfoSize(Ptr, OL_MEM_INFO_SIZE, &Size));
45+
ASSERT_EQ(Size, sizeof(size_t));
46+
}
47+
48+
TEST_P(olGetMemInfoSizeTest, SuccessType) {
49+
size_t Size = 0;
50+
ASSERT_SUCCESS(olGetMemInfoSize(Ptr, OL_MEM_INFO_TYPE, &Size));
51+
ASSERT_EQ(Size, sizeof(ol_alloc_type_t));
52+
}
53+
54+
TEST_P(olGetMemInfoSizeTest, InvalidSymbolInfoEnumeration) {
55+
size_t Size = 0;
56+
ASSERT_ERROR(OL_ERRC_INVALID_ENUMERATION,
57+
olGetMemInfoSize(Ptr, OL_MEM_INFO_FORCE_UINT32, &Size));
58+
}
59+
60+
TEST_P(olGetMemInfoSizeTest, InvalidNullPointer) {
61+
ASSERT_ERROR(OL_ERRC_INVALID_NULL_POINTER,
62+
olGetMemInfoSize(Ptr, OL_MEM_INFO_DEVICE, nullptr));
63+
}

0 commit comments

Comments
 (0)