Skip to content

Commit 193c965

Browse files
aarongreigkbenzie
authored andcommitted
Merge pull request #2121 from nrspruit/error_after_free_syclos
[L0] Refcnt Parent Buffer on Sub Buffer Create and die on use of buffer after free
1 parent 5be8f77 commit 193c965

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

source/adapters/level_zero/memory.cpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1990,19 +1990,30 @@ ur_result_t _ur_buffer::getZeHandle(char *&ZeHandle, access_mode_t AccessMode,
19901990

19911991
auto &Allocation = Allocations[Device];
19921992

1993+
if (this->isFreed) {
1994+
die("getZeHandle() buffer already released, no valid handles.");
1995+
}
1996+
19931997
// Sub-buffers don't maintain own allocations but rely on parent buffer.
19941998
if (SubBuffer) {
1995-
UR_CALL(SubBuffer->Parent->getZeHandle(ZeHandle, AccessMode, Device,
1996-
phWaitEvents, numWaitEvents));
1997-
ZeHandle += SubBuffer->Origin;
1998-
// Still store the allocation info in the PI sub-buffer for
1999-
// getZeHandlePtr to work. At least zeKernelSetArgumentValue needs to
2000-
// be given a pointer to the allocation handle rather than its value.
2001-
//
2002-
Allocation.ZeHandle = ZeHandle;
2003-
Allocation.ReleaseAction = allocation_t::keep;
2004-
LastDeviceWithValidAllocation = Device;
2005-
return UR_RESULT_SUCCESS;
1999+
// Verify that the Parent Buffer is still valid or if it has been freed.
2000+
if (SubBuffer->Parent && !SubBuffer->Parent->isFreed) {
2001+
UR_CALL(SubBuffer->Parent->getZeHandle(ZeHandle, AccessMode, Device,
2002+
phWaitEvents, numWaitEvents));
2003+
ZeHandle += SubBuffer->Origin;
2004+
// Still store the allocation info in the PI sub-buffer for
2005+
// getZeHandlePtr to work. At least zeKernelSetArgumentValue needs to
2006+
// be given a pointer to the allocation handle rather than its value.
2007+
//
2008+
Allocation.ZeHandle = ZeHandle;
2009+
Allocation.ReleaseAction = allocation_t::keep;
2010+
LastDeviceWithValidAllocation = Device;
2011+
return UR_RESULT_SUCCESS;
2012+
} else {
2013+
// Return an error if the parent buffer is already gone.
2014+
die("getZeHandle() SubBuffer's parent already released, no valid "
2015+
"handles.");
2016+
}
20062017
}
20072018

20082019
// First handle case where the buffer is represented by only
@@ -2263,6 +2274,7 @@ ur_result_t _ur_buffer::free() {
22632274
die("_ur_buffer::free(): Unhandled release action");
22642275
}
22652276
ZeHandle = nullptr; // don't leave hanging pointers
2277+
this->isFreed = true;
22662278
}
22672279
return UR_RESULT_SUCCESS;
22682280
}

source/adapters/level_zero/memory.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ struct _ur_buffer final : ur_mem_handle_t_ {
112112
// Sub-buffer constructor
113113
_ur_buffer(_ur_buffer *Parent, size_t Origin, size_t Size)
114114
: ur_mem_handle_t_(Parent->UrContext),
115-
Size(Size), SubBuffer{{Parent, Origin}} {}
115+
Size(Size), SubBuffer{{Parent, Origin}} {
116+
// Retain the Parent Buffer due to the Creation of the SubBuffer.
117+
Parent->RefCount.increment();
118+
}
116119

117120
// Interop-buffer constructor
118121
_ur_buffer(ur_context_handle_t Context, size_t Size,
@@ -140,6 +143,9 @@ struct _ur_buffer final : ur_mem_handle_t_ {
140143
// Frees all allocations made for the buffer.
141144
ur_result_t free();
142145

146+
// Tracks if this buffer is freed already or should be considered valid.
147+
bool isFreed{false};
148+
143149
// Information about a single allocation representing this buffer.
144150
struct allocation_t {
145151
// Level Zero memory handle is really just a naked pointer.

0 commit comments

Comments
 (0)