Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion test_conformance/SVM/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ set(${MODULE_NAME}_SOURCES
test_enqueue_api.cpp
test_fine_grain_memory_consistency.cpp
test_fine_grain_sync_buffers.cpp
test_migrate.cpp
test_negative_memcpy.cpp
test_pointer_passing.cpp
test_set_kernel_exec_info_svm_ptrs.cpp
test_shared_address_space_coarse_grain.cpp
test_shared_address_space_fine_grain.cpp
test_shared_address_space_fine_grain_buffers.cpp
test_shared_sub_buffers.cpp
test_migrate.cpp
)

set_gnulike_module_compile_flags("-Wno-sometimes-uninitialized -Wno-sign-compare")
Expand Down
107 changes: 107 additions & 0 deletions test_conformance/SVM/test_negative_memcpy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//
// Copyright (c) 2025 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "common.h"

REGISTER_TEST(svm_negative_memcpy_overlap)
{
cl_int err = CL_SUCCESS;

cl_device_svm_capabilities caps = 0;
err = clGetDeviceInfo(device, CL_DEVICE_SVM_CAPABILITIES, sizeof(caps),
&caps, NULL);

if (err != CL_SUCCESS || caps == 0)
{
log_error("svm_negative_memcpy_overlap: SVM is not supported on this "
"device\n");
return TEST_SKIP;
}

clContextWrapper contextWrapper = NULL;
clCommandQueueWrapper queues[MAXQ];
cl_uint num_devices = 0;
err = create_cl_objects(device, NULL, &contextWrapper, NULL, &queues[0],
&num_devices, 0);
test_error(err, "svm_negative_memcpy_overlap: create_cl_objects failed");

queue = queues[0];

const size_t dataSize = 32;

clSVMWrapper data_buf =
clSVMWrapper(contextWrapper, dataSize * 2, CL_MEM_READ_WRITE);

test_assert_error(data_buf() != nullptr, "clSVMAlloc failed");

// 1. A case where the end of the source memory partially overlaps the
// beginning of the destination memory.
{
char *src = (char *)data_buf();
char *dst = src + dataSize / 2;

err = clEnqueueSVMMemcpy(queue, CL_TRUE, dst, src, dataSize, 0, NULL,
NULL);

if (err != CL_MEM_COPY_OVERLAP)
{
log_error(
"svm_negative_memcpy_overlap: invalid result for "
"clEnqueueSVMMemcpy, expected CL_MEM_COPY_OVERLAP, got %s\n",
IGetErrorString(err));
return TEST_FAIL;
}
}

// 2. A case where the beginning of the source memory partially overlaps the
// end of the destination memory.
{
char *dst = (char *)data_buf();
char *src = dst + dataSize / 2;

err = clEnqueueSVMMemcpy(queue, CL_TRUE, dst, src, dataSize, 0, NULL,
NULL);

if (err != CL_MEM_COPY_OVERLAP)
{
log_error(
"svm_negative_memcpy_overlap: invalid result for "
"clEnqueueSVMMemcpy, expected CL_MEM_COPY_OVERLAP, got %s\n",
IGetErrorString(err));
return TEST_FAIL;
}
}

// 3. A case where the source memory completely overlaps the destination
// memory.
{
char *src = (char *)data_buf();
char *dst = (char *)data_buf();

err = clEnqueueSVMMemcpy(queue, CL_TRUE, dst, src, dataSize, 0, NULL,
NULL);

if (err != CL_MEM_COPY_OVERLAP)
{
log_error(
"svm_negative_memcpy_overlap: invalid result for "
"clEnqueueSVMMemcpy, expected CL_MEM_COPY_OVERLAP, got %s\n",
IGetErrorString(err));
return TEST_FAIL;
}
}

return TEST_PASS;
}