Mem-leaks from conformance pipes (#772)

Fix various memory leaks around events.
Convert test to use supplied typewrappers
to avoid memory leaks. Also use error helper
functions to reduce code size.
Use stringstreams to synthesize kernel sources, and
raw c+11 string literals.

Signed-off-by: John Kesapides <john.kesapides@arm.com>
This commit is contained in:
John Kesapides
2020-05-22 13:26:05 +01:00
committed by GitHub
parent ee2d0921dc
commit 094cc04e16
6 changed files with 790 additions and 1937 deletions

View File

@@ -79,28 +79,32 @@ static int verify_result(void *ptr1, void *ptr2, int n)
int test_pipe_query_functions(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
cl_mem pipe;
cl_mem buffers[4];
void *outptr1;
void *outptr2;
cl_int *inptr;
cl_program program;
cl_kernel kernel[3];
size_t global_work_size[3];
size_t half_global_work_size[3];
size_t global_work_size_pipe_query[3];
cl_int pipe_max_packets, pipe_num_packets;
cl_int err;
cl_int size;
cl_int i;
cl_event producer_sync_event = NULL;
cl_event consumer_sync_event = NULL;
cl_event pipe_query_sync_event = NULL;
cl_event pipe_read_sync_event = NULL;
MTdata d = init_genrand( gRandomSeed );
const char* kernelName[] = {"test_pipe_write", "test_pipe_read", "test_pipe_query_functions"};
clMemWrapper pipe;
clMemWrapper buffers[4];
void *outptr1;
void *outptr2;
cl_int *inptr;
clProgramWrapper program;
clKernelWrapper kernel[3];
size_t global_work_size[3];
size_t half_global_work_size[3];
size_t global_work_size_pipe_query[3];
cl_int pipe_max_packets, pipe_num_packets;
cl_int err;
cl_int size;
cl_int i;
clEventWrapper producer_sync_event = NULL;
clEventWrapper consumer_sync_event = NULL;
clEventWrapper pipe_query_sync_event = NULL;
clEventWrapper pipe_read_sync_event = NULL;
BufferOwningPtr<cl_int> BufferInPtr;
BufferOwningPtr<cl_int> BufferOutPtr1;
BufferOwningPtr<cl_int> BufferOutPtr2;
MTdataHolder d(gRandomSeed);
const char *kernelName[] = { "test_pipe_write", "test_pipe_read",
"test_pipe_query_functions" };
size_t min_alignment = get_min_alignment(context);
size_t min_alignment = get_min_alignment(context);
size = sizeof(int) * num_elements;
global_work_size[0] = (cl_uint)num_elements;
@@ -109,98 +113,43 @@ int test_pipe_query_functions(cl_device_id deviceID, cl_context context, cl_comm
inptr = (int *)align_malloc(size, min_alignment);
for(i = 0; i < num_elements; i++){
for (i = 0; i < num_elements; i++)
{
inptr[i] = TEST_PRIME_INT;
}
BufferInPtr.reset(inptr, nullptr, 0, size, true);
buffers[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, size, inptr, &err);
if(err){
clReleaseMemObject(buffers[0]);
print_error(err, " clCreateBuffer failed\n");
return -1;
}
test_error_ret(err, " clCreateBuffer failed", -1);
outptr1 = align_malloc(size/2, min_alignment);
outptr2 = align_malloc(size, min_alignment);
BufferOutPtr1.reset(outptr1, nullptr, 0, size, true);
BufferOutPtr2.reset(outptr2, nullptr, 0, size, true);
buffers[1] = clCreateBuffer(context, CL_MEM_HOST_READ_ONLY, size, NULL, &err);
if ( err ){
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
align_free( outptr1 );
print_error(err, " clCreateBuffer failed\n" );
return -1;
}
test_error_ret(err, " clCreateBuffer failed", -1);
buffers[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(int), NULL, &err);
if ( err ){
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
align_free( outptr1 );
print_error(err, " clCreateBuffer failed\n" );
return -1;
}
test_error_ret(err, " clCreateBuffer failed", -1);
buffers[3] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(int), NULL, &err);
if ( err ){
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
align_free( outptr1 );
print_error(err, " clCreateBuffer failed\n" );
return -1;
}
test_error_ret(err, " clCreateBuffer failed", -1);
pipe = clCreatePipe(context, CL_MEM_HOST_NO_ACCESS, sizeof(int), num_elements, NULL, &err);
if(err){
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
align_free( outptr1 );
clReleaseMemObject(pipe);
print_error(err, " clCreatePipe failed\n");
return -1;
}
test_error_ret(err, " clCreatePipe failed", -1);
// Create producer kernel
err = create_single_kernel_helper_with_build_options(context, &program, &kernel[0], 1, (const char**)&pipe_query_functions_kernel_code, kernelName[0], "-cl-std=CL2.0");
if(err){
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
align_free(outptr1);
print_error(err, "Error creating program\n");
return -1;
}
test_error_ret(err, " Error creating program", -1);
//Create consumer kernel
kernel[1] = clCreateKernel(program, kernelName[1], &err);
if( kernel[1] == NULL || err != CL_SUCCESS)
{
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
align_free(outptr1);
print_error(err, "Error creating kernel\n");
return -1;
}
test_error_ret(err, " Error creating kernel", -1);
//Create pipe query functions kernel
kernel[2] = clCreateKernel(program, kernelName[2], &err);
if( kernel[1] == NULL || err != CL_SUCCESS)
{
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
align_free(outptr1);
print_error(err, "Error creating kernel\n");
return -1;
}
test_error_ret(err, " Error creating kernel", -1);
err = clSetKernelArg(kernel[0], 0, sizeof(cl_mem), (void*)&buffers[0]);
err |= clSetKernelArg(kernel[0], 1, sizeof(cl_mem), (void*)&pipe);
@@ -209,104 +158,21 @@ int test_pipe_query_functions(cl_device_id deviceID, cl_context context, cl_comm
err |= clSetKernelArg(kernel[2], 0, sizeof(cl_mem), (void*)&pipe);
err |= clSetKernelArg(kernel[2], 1, sizeof(cl_mem), (void*)&buffers[2]);
err |= clSetKernelArg(kernel[2], 2, sizeof(cl_mem), (void*)&buffers[3]);
if ( err != CL_SUCCESS ){
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseProgram(program);
align_free(outptr1);
print_error(err, " clSetKernelArg failed\n");
return -1;
}
test_error_ret(err, " clSetKernelArg failed", -1);
// Launch Producer kernel
err = clEnqueueNDRangeKernel( queue, kernel[0], 1, NULL, global_work_size, NULL, 0, NULL, &producer_sync_event );
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueNDRangeKernel failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueNDRangeKernel failed", -1);
// Launch Pipe query kernel
err = clEnqueueNDRangeKernel( queue, kernel[2], 1, NULL, global_work_size_pipe_query, NULL, 1, &producer_sync_event, &pipe_query_sync_event );
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueNDRangeKernel failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueNDRangeKernel failed", -1);
err = clEnqueueReadBuffer(queue, buffers[2], true, 0, sizeof(cl_int), &pipe_num_packets, 1, &pipe_query_sync_event, NULL);
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueReadBuffer failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueReadBuffer failed", -1);
err = clEnqueueReadBuffer(queue, buffers[3], true, 0, sizeof(cl_int), &pipe_max_packets, 1, &pipe_query_sync_event, NULL);
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueReadBuffer failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueReadBuffer failed", -1);
if(pipe_num_packets != num_elements || pipe_max_packets != num_elements)
{
@@ -316,85 +182,20 @@ int test_pipe_query_functions(cl_device_id deviceID, cl_context context, cl_comm
// Launch Consumer kernel with half the previous global size
err = clEnqueueNDRangeKernel( queue, kernel[1], 1, NULL, half_global_work_size, NULL, 1, &producer_sync_event, &consumer_sync_event );
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueNDRangeKernel failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueNDRangeKernel failed", -1);
err = clEnqueueReadBuffer(queue, buffers[1], true, 0, size / 2, outptr1, 1, &consumer_sync_event, NULL);
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueReadBuffer failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueReadBuffer failed", -1);
// We will reuse this variable so release the previous referred event.
clReleaseEvent(pipe_query_sync_event);
// Launch Pipe query kernel
err = clEnqueueNDRangeKernel( queue, kernel[2], 1, NULL, global_work_size_pipe_query, NULL, 1, &consumer_sync_event, &pipe_query_sync_event );
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueNDRangeKernel failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueNDRangeKernel failed", -1);
err = clEnqueueReadBuffer(queue, buffers[2], true, 0, sizeof(cl_int), &pipe_num_packets, 1, &pipe_query_sync_event, &pipe_read_sync_event);
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueReadBuffer failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueReadBuffer failed", -1);
// After consumer kernel consumes num_elements/2 from the pipe,
// there are (num_elements - num_elements/2) remaining package in the pipe.
@@ -404,68 +205,24 @@ int test_pipe_query_functions(cl_device_id deviceID, cl_context context, cl_comm
return -1;
}
// We will reuse this variable so release the previous referred event.
clReleaseEvent(producer_sync_event);
// Launch Producer kernel to fill the pipe again
global_work_size[0] = pipe_num_packets;
err = clEnqueueNDRangeKernel( queue, kernel[0], 1, NULL, global_work_size, NULL, 1, &pipe_read_sync_event, &producer_sync_event );
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueNDRangeKernel failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueNDRangeKernel failed", -1);
// We will reuse this variable so release the previous referred event.
clReleaseEvent(pipe_query_sync_event);
// Launch Pipe query kernel
err = clEnqueueNDRangeKernel( queue, kernel[2], 1, NULL, global_work_size_pipe_query, NULL, 1, &producer_sync_event, &pipe_query_sync_event );
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueNDRangeKernel failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueNDRangeKernel failed", -1);
// We will reuse this variable so release the previous referred event.
clReleaseEvent(pipe_read_sync_event);
err = clEnqueueReadBuffer(queue, buffers[2], true, 0, sizeof(cl_int), &pipe_num_packets, 1, &pipe_query_sync_event, &pipe_read_sync_event);
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueReadBuffer failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueReadBuffer failed", -1);
if(pipe_num_packets != num_elements)
{
@@ -473,48 +230,16 @@ int test_pipe_query_functions(cl_device_id deviceID, cl_context context, cl_comm
return -1;
}
// We will reuse this variable so release the previous referred event.
clReleaseEvent(consumer_sync_event);
// Launch Consumer kernel to consume all packets from pipe
global_work_size[0] = pipe_num_packets;
err = clEnqueueNDRangeKernel( queue, kernel[1], 1, NULL, global_work_size, NULL, 1, &pipe_read_sync_event, &consumer_sync_event );
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueNDRangeKernel failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueNDRangeKernel failed", -1);
err = clEnqueueReadBuffer(queue, buffers[1], true, 0, size, outptr2, 1, &consumer_sync_event, NULL);
if ( err != CL_SUCCESS ){
print_error( err, " clEnqueueReadBuffer failed\n" );
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return -1;
}
test_error_ret(err, " clEnqueueReadBuffer failed", -1);
if( verify_result(outptr1, outptr2, num_elements )){
log_error("test_pipe_query_functions failed\n");
@@ -523,22 +248,6 @@ int test_pipe_query_functions(cl_device_id deviceID, cl_context context, cl_comm
else {
log_info("test_pipe_query_functions passed\n");
}
//cleanup
clReleaseMemObject(buffers[0]);
clReleaseMemObject(buffers[1]);
clReleaseMemObject(buffers[2]);
clReleaseMemObject(buffers[3]);
clReleaseMemObject(pipe);
clReleaseKernel(kernel[0]);
clReleaseKernel(kernel[1]);
clReleaseKernel(kernel[2]);
clReleaseEvent(producer_sync_event);
clReleaseEvent(consumer_sync_event);
clReleaseEvent(pipe_query_sync_event);
clReleaseEvent(pipe_read_sync_event);
clReleaseProgram(program);
align_free(outptr1);
return 0;
}