Skip to content

Commit f0bce89

Browse files
igchorKornevNikita
authored andcommitted
[SYCL][UR][L0 v2] Fix urMemBufferCreateWithNativeHandle (#17698)
The implementation incorrectly assumed that hDevice is always set for memory type other than host which resulted in nullptr dereference in ur_discrete_buffer_handle_t ctor. The assumption is not true for shared allocations. Implement a separate handle type to handle shared allocations: the implementation will just use the allocation directly.
1 parent 76e9ac0 commit f0bce89

File tree

4 files changed

+125
-2
lines changed

4 files changed

+125
-2
lines changed

unified-runtime/source/adapters/level_zero/v2/memory.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ ur_discrete_buffer_handle_t::ur_discrete_buffer_handle_t(
233233
hDevice = hDevice ? hDevice : hContext->getDevices()[0];
234234
devicePtr = allocateOnDevice(hDevice, size);
235235
} else {
236+
assert(hDevice);
236237
this->IsInteropNativeHandle = interopNativeHandle;
237238
deviceAllocations[hDevice->Id.value()] = usm_unique_ptr_t(
238239
devicePtr, [this, hContext = this->hContext, ownZePtr](void *ptr) {
@@ -363,6 +364,34 @@ void ur_discrete_buffer_handle_t::unmapHostPtr(
363364
hostAllocations.erase(hostAlloc);
364365
}
365366

367+
ur_shared_buffer_handle_t::ur_shared_buffer_handle_t(
368+
ur_context_handle_t hContext, void *sharedPtr, size_t size,
369+
device_access_mode_t accesMode, bool ownDevicePtr)
370+
: ur_mem_buffer_t(hContext, size, accesMode),
371+
ptr(sharedPtr, [hContext, ownDevicePtr](void *ptr) {
372+
if (!ownDevicePtr || !checkL0LoaderTeardown()) {
373+
return;
374+
}
375+
ZE_CALL_NOCHECK(zeMemFree, (hContext->getZeHandle(), ptr));
376+
}) {}
377+
378+
void *ur_shared_buffer_handle_t::getDevicePtr(
379+
ur_device_handle_t, device_access_mode_t, size_t offset, size_t,
380+
std::function<void(void *src, void *dst, size_t)>) {
381+
return reinterpret_cast<char *>(ptr.get()) + offset;
382+
}
383+
384+
void *ur_shared_buffer_handle_t::mapHostPtr(
385+
ur_map_flags_t, size_t offset, size_t,
386+
std::function<void(void *src, void *dst, size_t)>) {
387+
return reinterpret_cast<char *>(ptr.get()) + offset;
388+
}
389+
390+
void ur_shared_buffer_handle_t::unmapHostPtr(
391+
void *, std::function<void(void *src, void *dst, size_t)>) {
392+
// nop
393+
}
394+
366395
static bool useHostBuffer(ur_context_handle_t hContext) {
367396
// We treat integrated devices (physical memory shared with the CPU)
368397
// differently from discrete devices (those with distinct memories).
@@ -587,6 +616,10 @@ ur_result_t urMemBufferCreateWithNativeHandle(
587616
hContext, ptr, size, accessMode, ownNativeHandle, true);
588617
// if useHostBuffer(hContext) is true but the allocation is on device, we'll
589618
// treat it as discrete memory
619+
} else if (memoryAttrs.type == ZE_MEMORY_TYPE_SHARED) {
620+
// For shared allocation, we can use it directly
621+
*phMem = ur_mem_handle_t_::create<ur_shared_buffer_handle_t>(
622+
hContext, ptr, size, accessMode, ownNativeHandle);
590623
} else {
591624
if (memoryAttrs.type == ZE_MEMORY_TYPE_HOST) {
592625
// For host allocation, we need to copy the data to a device buffer
@@ -595,7 +628,8 @@ ur_result_t urMemBufferCreateWithNativeHandle(
595628
hContext, hDevice, nullptr, size, accessMode, ptr, ownNativeHandle,
596629
true);
597630
} else {
598-
// For device/shared allocation, we can use it directly
631+
// For device allocation, we can use it directly
632+
assert(hDevice);
599633
*phMem = ur_mem_handle_t_::create<ur_discrete_buffer_handle_t>(
600634
hContext, hDevice, ptr, size, accessMode, nullptr, ownNativeHandle,
601635
true);

unified-runtime/source/adapters/level_zero/v2/memory.hpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,24 @@ struct ur_discrete_buffer_handle_t : ur_mem_buffer_t {
161161
size_t size);
162162
};
163163

164+
struct ur_shared_buffer_handle_t : ur_mem_buffer_t {
165+
ur_shared_buffer_handle_t(ur_context_handle_t hContext, void *devicePtr,
166+
size_t size, device_access_mode_t accesMode,
167+
bool ownDevicePtr);
168+
169+
void *
170+
getDevicePtr(ur_device_handle_t, device_access_mode_t, size_t offset,
171+
size_t size,
172+
std::function<void(void *src, void *dst, size_t)>) override;
173+
void *mapHostPtr(ur_map_flags_t, size_t offset, size_t size,
174+
std::function<void(void *src, void *dst, size_t)>) override;
175+
void unmapHostPtr(void *pMappedPtr,
176+
std::function<void(void *src, void *dst, size_t)>) override;
177+
178+
private:
179+
usm_unique_ptr_t ptr;
180+
};
181+
164182
struct ur_mem_sub_buffer_t : ur_mem_buffer_t {
165183
ur_mem_sub_buffer_t(ur_mem_handle_t hParent, size_t offset, size_t size,
166184
device_access_mode_t accesMode);
@@ -263,6 +281,7 @@ struct ur_mem_handle_t_ {
263281
: mem(std::in_place_type<T>, std::forward<Args>(args)...) {}
264282

265283
std::variant<ur_usm_handle_t, ur_integrated_buffer_handle_t,
266-
ur_discrete_buffer_handle_t, ur_mem_sub_buffer_t, ur_mem_image_t>
284+
ur_discrete_buffer_handle_t, ur_shared_buffer_handle_t,
285+
ur_mem_sub_buffer_t, ur_mem_image_t>
267286
mem;
268287
};

unified-runtime/test/adapters/level_zero/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,15 @@ function(add_adapter_tests adapter)
9494
ENVIRONMENT
9595
"UR_ADAPTERS_FORCE_LOAD=\"$<TARGET_FILE:ur_adapter_${adapter}>\""
9696
)
97+
98+
add_adapter_test(${adapter}_mem_buffer_create_with_native_handle
99+
FIXTURE DEVICES
100+
SOURCES
101+
urMemBufferCreateWithNativeHandleShared.cpp
102+
ENVIRONMENT
103+
"UR_ADAPTERS_FORCE_LOAD=\"$<TARGET_FILE:ur_adapter_${adapter}>\""
104+
)
105+
target_link_libraries(test-adapter-${adapter}_mem_buffer_create_with_native_handle PRIVATE LevelZeroLoader LevelZeroLoader-Headers)
97106
endfunction()
98107

99108
if(UR_BUILD_ADAPTER_L0)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (C) 2025 Intel Corporation
2+
// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM
3+
// Exceptions. See LICENSE.TXT
4+
//
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
7+
#include "ur_api.h"
8+
#include "uur/checks.h"
9+
#include "uur/raii.h"
10+
#include "ze_api.h"
11+
#include <uur/fixtures.h>
12+
13+
using urMemBufferCreateWithNativeHandleTest = uur::urQueueTest;
14+
UUR_INSTANTIATE_DEVICE_TEST_SUITE(urMemBufferCreateWithNativeHandleTest);
15+
16+
TEST_P(urMemBufferCreateWithNativeHandleTest, SharedBufferIsUsedDirectly) {
17+
UUR_KNOWN_FAILURE_ON(uur::LevelZero{});
18+
19+
// Initialize Level Zero driver is required if this test is linked statically
20+
// with Level Zero loader, the driver will not be init otherwise.
21+
zeInit(ZE_INIT_FLAG_GPU_ONLY);
22+
23+
ur_native_handle_t nativeContext;
24+
ASSERT_SUCCESS(urContextGetNativeHandle(context, &nativeContext));
25+
26+
ur_native_handle_t nativeDevice;
27+
ASSERT_SUCCESS(urDeviceGetNativeHandle(device, &nativeDevice));
28+
29+
ze_device_mem_alloc_desc_t DeviceDesc = {};
30+
DeviceDesc.stype = ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC;
31+
DeviceDesc.ordinal = 0;
32+
DeviceDesc.flags = 0;
33+
DeviceDesc.pNext = nullptr;
34+
35+
ze_host_mem_alloc_desc_t HostDesc = {};
36+
HostDesc.stype = ZE_STRUCTURE_TYPE_HOST_MEM_ALLOC_DESC;
37+
HostDesc.pNext = nullptr;
38+
HostDesc.flags = 0;
39+
40+
void *SharedBuffer = nullptr;
41+
ASSERT_EQ(
42+
zeMemAllocShared(reinterpret_cast<ze_context_handle_t>(nativeContext),
43+
&DeviceDesc, &HostDesc, 12 * sizeof(int), 1, nullptr,
44+
&SharedBuffer),
45+
ZE_RESULT_SUCCESS);
46+
47+
uur::raii::Mem buffer;
48+
ASSERT_SUCCESS(urMemBufferCreateWithNativeHandle(
49+
reinterpret_cast<ur_native_handle_t>(SharedBuffer), context, nullptr,
50+
buffer.ptr()));
51+
52+
void *mappedPtr;
53+
ASSERT_SUCCESS(urEnqueueMemBufferMap(queue, buffer.get(), true, 0, 0,
54+
12 * sizeof(int), 0, nullptr, nullptr,
55+
&mappedPtr));
56+
57+
ASSERT_EQ(mappedPtr, SharedBuffer);
58+
ASSERT_EQ(zeMemFree(reinterpret_cast<ze_context_handle_t>(nativeContext),
59+
SharedBuffer),
60+
ZE_RESULT_SUCCESS);
61+
}

0 commit comments

Comments
 (0)