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
119 changes: 119 additions & 0 deletions test_conformance/SVM/test_enqueue_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,3 +349,122 @@ REGISTER_TEST(svm_enqueue_api)

return 0;
}

// Tests corrupting the pattern before clEnqueueSVMMemFill is executed
REGISTER_TEST(svm_memfill_pattern_lifetime)
{
constexpr cl_int FILL_PATTERN = 0x12345678;

clContextWrapper contextWrapper = nullptr;
clCommandQueueWrapper queues[MAXQ];
cl_uint num_devices = 0;
cl_int err = CL_SUCCESS;

const size_t svm_size = num_elements * sizeof(cl_int);

cl_int *svm_ptr = nullptr;
cl_int *pattern = nullptr;
cl_event user_event = nullptr;
cl_event fill_event = nullptr;

int result = TEST_FAIL;

err =
create_cl_objects(device, nullptr, &contextWrapper, nullptr, &queues[0],
&num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
if (err) goto cleanup;

context = contextWrapper;
queue = queues[0];

svm_ptr = static_cast<cl_int *>(
clSVMAlloc(context, CL_MEM_READ_WRITE, svm_size, 0));
if (!svm_ptr)
{
log_error("clSVMAlloc failed\n");
goto cleanup;
}

user_event = clCreateUserEvent(context, &err);
if (err != CL_SUCCESS)
{
print_error(err, "clCreateUserEvent failed");
goto cleanup;
}

pattern = static_cast<cl_int *>(malloc(sizeof(cl_int)));
if (!pattern)
{
log_error("Failed to allocate pattern memory\n");
goto cleanup;
}
*pattern = FILL_PATTERN;

err = clEnqueueSVMMemFill(queue, svm_ptr, pattern, sizeof(cl_int), svm_size,
1, &user_event, &fill_event);
if (err != CL_SUCCESS)
{
print_error(err, "clEnqueueSVMMemFill failed");
goto cleanup;
}

/* corrupt pattern while command is blocked */
*pattern = static_cast<cl_int>(0xDEADBEEF);

err = clSetUserEventStatus(user_event, CL_COMPLETE);
if (err != CL_SUCCESS)
{
print_error(err, "clSetUserEventStatus failed");
goto cleanup;
}

err = clWaitForEvents(1, &fill_event);
if (err != CL_SUCCESS)
{
print_error(err, "clWaitForEvents failed");
goto cleanup;
}

err = clEnqueueSVMMap(queue, CL_TRUE, CL_MAP_READ, svm_ptr, svm_size, 0,
nullptr, nullptr);
if (err != CL_SUCCESS)
{
print_error(err, "clEnqueueSVMMap failed");
goto cleanup;
}

for (size_t i = 0; i < num_elements; i++)
{
if (svm_ptr[i] != FILL_PATTERN)
{
log_error("Verification failed at index %zu: expected 0x%08x, got "
"0x%08x\n",
i, FILL_PATTERN, svm_ptr[i]);
goto cleanup;
}
}

err = clEnqueueSVMUnmap(queue, svm_ptr, 0, nullptr, nullptr);
if (err != CL_SUCCESS)
{
print_error(err, "clEnqueueSVMUnmap failed");
goto cleanup;
}

err = clFinish(queue);
if (err != CL_SUCCESS)
{
print_error(err, "clFinish failed");
goto cleanup;
}

result = TEST_PASS;

cleanup:
if (fill_event) clReleaseEvent(fill_event);
if (user_event) clReleaseEvent(user_event);
if (pattern) free(pattern);
if (svm_ptr) clSVMFree(context, svm_ptr);
Comment on lines +464 to +467
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here - can we use wrappers so we don't need to do this cleanup manually?


return result;
}
123 changes: 122 additions & 1 deletion test_conformance/buffers/test_buffer_fill.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Copyright (c) 2017 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
Expand Down Expand Up @@ -557,6 +557,17 @@ static int verify_fill_struct( void *ptr1, void *ptr2, int n )
}


static int verify_pattern_lifetime(cl_int *buffer, size_t num_elements,
cl_int expected_value)
{
for (size_t i = 0; i < num_elements; i++)
{
if (buffer[i] != expected_value) return -1;
}
return 0;
}


static int test_buffer_fill(cl_device_id deviceID, cl_context context,
cl_command_queue queue, int num_elements,
size_t size, char *type, int loops, void *inptr[5],
Expand Down Expand Up @@ -709,6 +720,102 @@ static int test_buffer_fill(cl_device_id deviceID, cl_context context,
} // end test_buffer_fill()


static int test_fill_reused_pattern(cl_device_id device_id, cl_context context,
cl_command_queue queue, int num_elements)
{
cl_int err;
const size_t buffer_bytes = num_elements * sizeof(cl_int);

cl_mem buffer = nullptr;
cl_event user_event = nullptr;
cl_event fill_event = nullptr;
cl_int *pattern = nullptr;
cl_int *host_buffer = nullptr;

int result = TEST_FAIL;

buffer =
clCreateBuffer(context, CL_MEM_READ_WRITE, buffer_bytes, nullptr, &err);
if (err != CL_SUCCESS)
{
print_error(err, "clCreateBuffer failed");
goto cleanup;
}

user_event = clCreateUserEvent(context, &err);
if (err != CL_SUCCESS)
{
print_error(err, "clCreateUserEvent failed");
goto cleanup;
}

pattern = static_cast<cl_int *>(malloc(sizeof(cl_int)));
if (!pattern)
{
log_error("Failed to allocate pattern memory\n");
goto cleanup;
}
*pattern = TEST_PRIME_INT;

err = clEnqueueFillBuffer(queue, buffer, pattern, sizeof(cl_int), 0,
buffer_bytes, 1, &user_event, &fill_event);
if (err != CL_SUCCESS)
{
print_error(err, "clEnqueueFillBuffer failed");
goto cleanup;
}

/* Modify pattern while command is blocked */
*pattern = static_cast<cl_int>(0xDEADBEEF);

err = clSetUserEventStatus(user_event, CL_COMPLETE);
if (err != CL_SUCCESS)
{
print_error(err, "clSetUserEventStatus failed");
goto cleanup;
}

err = clWaitForEvents(1, &fill_event);
if (err != CL_SUCCESS)
{
print_error(err, "clWaitForEvents failed");
goto cleanup;
}

host_buffer = static_cast<cl_int *>(malloc(buffer_bytes));
if (!host_buffer)
{
log_error("Failed to allocate host buffer\n");
goto cleanup;
}

err = clEnqueueReadBuffer(queue, buffer, CL_TRUE, 0, buffer_bytes,
host_buffer, 0, nullptr, nullptr);
if (err != CL_SUCCESS)
{
print_error(err, "clEnqueueReadBuffer failed");
goto cleanup;
}

if (verify_pattern_lifetime(host_buffer, num_elements, TEST_PRIME_INT) != 0)
{
log_error("buffer_fill pattern lifetime test failed - driver used "
"freed/corrupted pattern memory\n");
goto cleanup;
}

result = TEST_PASS;

cleanup:
if (host_buffer) free(host_buffer);
if (pattern) free(pattern);
if (fill_event) clReleaseEvent(fill_event);
if (user_event) clReleaseEvent(user_event);
if (buffer) clReleaseMemObject(buffer);
Comment on lines +810 to +814
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the RAII wrappers and either std::vectors or smart pointers in these tests so we don't need to clean this up manually?


return result;
} // end test_fill_pattern_freed_and_corrupted()

REGISTER_TEST(buffer_fill_struct)
{
TestStruct pattern;
Expand Down Expand Up @@ -1510,3 +1617,17 @@ REGISTER_TEST(buffer_fill_float)
return err;

} // end test_buffer_float_fill()


REGISTER_TEST(buffer_fill_pattern_lifetime)
{
int err = 0;
if (test_fill_reused_pattern(device, context, queue, num_elements)
!= TEST_PASS)
{
err++;
}

return err;

} // end test_buffer_fill_pattern_lifetime()
Loading