diff --git a/test_conformance/api/CMakeLists.txt b/test_conformance/api/CMakeLists.txt index d330b4b1..3d58ffb2 100644 --- a/test_conformance/api/CMakeLists.txt +++ b/test_conformance/api/CMakeLists.txt @@ -27,6 +27,7 @@ set(${MODULE_NAME}_SOURCES test_sub_group_dispatch.cpp test_clone_kernel.cpp test_zero_sized_enqueue.cpp + test_context_destructor_callback.cpp ) include(../CMakeCommon.txt) diff --git a/test_conformance/api/main.cpp b/test_conformance/api/main.cpp index 72cbbea8..314b9de6 100644 --- a/test_conformance/api/main.cpp +++ b/test_conformance/api/main.cpp @@ -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 @@ -26,107 +26,107 @@ #endif // FIXME: To use certain functions in harness/imageHelpers.h -// (for example, generate_random_image_data()), the tests are required to declare -// the following variables (): +// (for example, generate_random_image_data()), the tests are required to +// declare the following variables (): test_definition test_list[] = { - ADD_TEST( get_platform_info ), - ADD_TEST_VERSION( get_sampler_info, Version(2, 0) ), - ADD_TEST( get_sampler_info_compatibility ), - ADD_TEST_VERSION( get_command_queue_info, Version(2, 0) ), - ADD_TEST( get_command_queue_info_compatibility ), - ADD_TEST( get_context_info ), - ADD_TEST( get_device_info ), - ADD_TEST( enqueue_task ), - ADD_TEST( binary_get ), - ADD_TEST( binary_create ), - ADD_TEST( kernel_required_group_size ), + ADD_TEST(get_platform_info), + ADD_TEST_VERSION(get_sampler_info, Version(2, 0)), + ADD_TEST(get_sampler_info_compatibility), + ADD_TEST_VERSION(get_command_queue_info, Version(2, 0)), + ADD_TEST(get_command_queue_info_compatibility), + ADD_TEST(get_context_info), + ADD_TEST(get_device_info), + ADD_TEST(enqueue_task), + ADD_TEST(binary_get), + ADD_TEST(binary_create), + ADD_TEST(kernel_required_group_size), - ADD_TEST( release_kernel_order ), - ADD_TEST( release_during_execute ), + ADD_TEST(release_kernel_order), + ADD_TEST(release_during_execute), - ADD_TEST( load_single_kernel ), - ADD_TEST( load_two_kernels ), - ADD_TEST( load_two_kernels_in_one ), - ADD_TEST( load_two_kernels_manually ), - ADD_TEST( get_program_info_kernel_names ), - ADD_TEST( get_kernel_arg_info ), - ADD_TEST( get_kernel_arg_info_compatibility ), - ADD_TEST( create_kernels_in_program ), - ADD_TEST( get_kernel_info ), - ADD_TEST( execute_kernel_local_sizes ), - ADD_TEST( set_kernel_arg_by_index ), - ADD_TEST( set_kernel_arg_constant ), - ADD_TEST( set_kernel_arg_struct_array ), - ADD_TEST( kernel_global_constant ), + ADD_TEST(load_single_kernel), + ADD_TEST(load_two_kernels), + ADD_TEST(load_two_kernels_in_one), + ADD_TEST(load_two_kernels_manually), + ADD_TEST(get_program_info_kernel_names), + ADD_TEST(get_kernel_arg_info), + ADD_TEST(get_kernel_arg_info_compatibility), + ADD_TEST(create_kernels_in_program), + ADD_TEST(get_kernel_info), + ADD_TEST(execute_kernel_local_sizes), + ADD_TEST(set_kernel_arg_by_index), + ADD_TEST(set_kernel_arg_constant), + ADD_TEST(set_kernel_arg_struct_array), + ADD_TEST(kernel_global_constant), - ADD_TEST( min_max_thread_dimensions ), - ADD_TEST( min_max_work_items_sizes ), - ADD_TEST( min_max_work_group_size ), - ADD_TEST( min_max_read_image_args ), - ADD_TEST( min_max_write_image_args ), - ADD_TEST( min_max_mem_alloc_size ), - ADD_TEST( min_max_image_2d_width ), - ADD_TEST( min_max_image_2d_height ), - ADD_TEST( min_max_image_3d_width ), - ADD_TEST( min_max_image_3d_height ), - ADD_TEST( min_max_image_3d_depth ), - ADD_TEST( min_max_image_array_size ), - ADD_TEST( min_max_image_buffer_size ), - ADD_TEST( min_max_parameter_size ), - ADD_TEST( min_max_samplers ), - ADD_TEST( min_max_constant_buffer_size ), - ADD_TEST( min_max_constant_args ), - ADD_TEST( min_max_compute_units ), - ADD_TEST( min_max_address_bits ), - ADD_TEST( min_max_single_fp_config ), - ADD_TEST( min_max_double_fp_config ), - ADD_TEST( min_max_local_mem_size ), - ADD_TEST( min_max_kernel_preferred_work_group_size_multiple ), - ADD_TEST( min_max_execution_capabilities ), - ADD_TEST( min_max_queue_properties ), - ADD_TEST( min_max_device_version ), - ADD_TEST( min_max_language_version ), + ADD_TEST(min_max_thread_dimensions), + ADD_TEST(min_max_work_items_sizes), + ADD_TEST(min_max_work_group_size), + ADD_TEST(min_max_read_image_args), + ADD_TEST(min_max_write_image_args), + ADD_TEST(min_max_mem_alloc_size), + ADD_TEST(min_max_image_2d_width), + ADD_TEST(min_max_image_2d_height), + ADD_TEST(min_max_image_3d_width), + ADD_TEST(min_max_image_3d_height), + ADD_TEST(min_max_image_3d_depth), + ADD_TEST(min_max_image_array_size), + ADD_TEST(min_max_image_buffer_size), + ADD_TEST(min_max_parameter_size), + ADD_TEST(min_max_samplers), + ADD_TEST(min_max_constant_buffer_size), + ADD_TEST(min_max_constant_args), + ADD_TEST(min_max_compute_units), + ADD_TEST(min_max_address_bits), + ADD_TEST(min_max_single_fp_config), + ADD_TEST(min_max_double_fp_config), + ADD_TEST(min_max_local_mem_size), + ADD_TEST(min_max_kernel_preferred_work_group_size_multiple), + ADD_TEST(min_max_execution_capabilities), + ADD_TEST(min_max_queue_properties), + ADD_TEST(min_max_device_version), + ADD_TEST(min_max_language_version), - ADD_TEST( kernel_arg_changes ), - ADD_TEST( kernel_arg_multi_setup_random ), + ADD_TEST(kernel_arg_changes), + ADD_TEST(kernel_arg_multi_setup_random), - ADD_TEST( native_kernel ), + ADD_TEST(native_kernel), - ADD_TEST( create_context_from_type ), + ADD_TEST(create_context_from_type), - ADD_TEST( platform_extensions ), - ADD_TEST( get_platform_ids ), - ADD_TEST( bool_type ), + ADD_TEST(platform_extensions), + ADD_TEST(get_platform_ids), + ADD_TEST(bool_type), - ADD_TEST( repeated_setup_cleanup ), + ADD_TEST(repeated_setup_cleanup), - ADD_TEST( retain_queue_single ), - ADD_TEST( retain_queue_multiple ), - ADD_TEST( retain_mem_object_single ), - ADD_TEST( retain_mem_object_multiple ), - ADD_TEST( retain_mem_object_set_kernel_arg ), - ADD_TEST( min_data_type_align_size_alignment ), + ADD_TEST(retain_queue_single), + ADD_TEST(retain_queue_multiple), + ADD_TEST(retain_mem_object_single), + ADD_TEST(retain_mem_object_multiple), + ADD_TEST(retain_mem_object_set_kernel_arg), + ADD_TEST(min_data_type_align_size_alignment), - ADD_TEST( mem_object_destructor_callback ), - ADD_TEST( null_buffer_arg ), - ADD_TEST( get_buffer_info ), - ADD_TEST( get_image2d_info ), - ADD_TEST( get_image3d_info ), - ADD_TEST( get_image1d_info ), - ADD_TEST( get_image1d_array_info ), - ADD_TEST( get_image2d_array_info ), - ADD_TEST( queue_hint ), - ADD_TEST( queue_properties ), - ADD_TEST_VERSION( sub_group_dispatch, Version(2, 1) ), - ADD_TEST_VERSION( clone_kernel, Version(2, 1) ), - ADD_TEST_VERSION( zero_sized_enqueue, Version(2, 1) ), + ADD_TEST_VERSION(context_destructor_callback, Version(3, 0)), + ADD_TEST(mem_object_destructor_callback), + ADD_TEST(null_buffer_arg), + ADD_TEST(get_buffer_info), + ADD_TEST(get_image2d_info), + ADD_TEST(get_image3d_info), + ADD_TEST(get_image1d_info), + ADD_TEST(get_image1d_array_info), + ADD_TEST(get_image2d_array_info), + ADD_TEST(queue_hint), + ADD_TEST(queue_properties), + ADD_TEST_VERSION(sub_group_dispatch, Version(2, 1)), + ADD_TEST_VERSION(clone_kernel, Version(2, 1)), + ADD_TEST_VERSION(zero_sized_enqueue, Version(2, 1)), }; -const int test_num = ARRAY_SIZE( test_list ); +const int test_num = ARRAY_SIZE(test_list); int main(int argc, const char *argv[]) { - return runTestHarness( argc, argv, test_num, test_list, false, false, 0 ); + return runTestHarness(argc, argv, test_num, test_list, false, false, 0); } - diff --git a/test_conformance/api/procs.h b/test_conformance/api/procs.h index 10b3ea3d..b3a29515 100644 --- a/test_conformance/api/procs.h +++ b/test_conformance/api/procs.h @@ -98,7 +98,14 @@ extern int test_retain_mem_object_multiple(cl_device_id deviceID, cl_cont extern int test_retain_mem_object_set_kernel_arg(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); extern int test_min_data_type_align_size_alignment(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems ); -extern int test_mem_object_destructor_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements); +extern int test_context_destructor_callback(cl_device_id deviceID, + cl_context context, + cl_command_queue queue, + int num_elements); +extern int test_mem_object_destructor_callback(cl_device_id deviceID, + cl_context context, + cl_command_queue queue, + int num_elements); extern int test_null_buffer_arg( cl_device_id device_id, cl_context context, cl_command_queue queue, int num_elements ); extern int test_get_buffer_info( cl_device_id deviceID, cl_context context, cl_command_queue ignoreQueue, int num_elements ); diff --git a/test_conformance/api/test_context_destructor_callback.cpp b/test_conformance/api/test_context_destructor_callback.cpp new file mode 100644 index 00000000..1d73a3c4 --- /dev/null +++ b/test_conformance/api/test_context_destructor_callback.cpp @@ -0,0 +1,93 @@ +// +// Copyright (c) 2020 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 "testBase.h" + +static volatile cl_int sDestructorIndex; + +void CL_CALLBACK context_destructor_callback(cl_context context, void *userData) +{ + int *userPtr = (int *)userData; + + // ordering of callbacks is guaranteed, meaning we don't need to do atomic + // operation here + *userPtr = ++sDestructorIndex; +} + +int test_context_destructor_callback(cl_device_id deviceID, cl_context context, + cl_command_queue queue, int num_elements) +{ + cl_int error; + clContextWrapper localContext = + clCreateContext(NULL, 1, &deviceID, NULL, NULL, &error); + test_error(error, "Unable to create local context"); + + // Set up some variables to catch the order in which callbacks are called + volatile int callbackOrders[3] = { 0, 0, 0 }; + sDestructorIndex = 0; + + // Set up the callbacks + error = clSetContextDestructorCallback( + localContext, context_destructor_callback, (void *)&callbackOrders[0]); + test_error(error, "Unable to set destructor callback"); + + error = clSetContextDestructorCallback( + localContext, context_destructor_callback, (void *)&callbackOrders[1]); + test_error(error, "Unable to set destructor callback"); + + error = clSetContextDestructorCallback( + localContext, context_destructor_callback, (void *)&callbackOrders[2]); + test_error(error, "Unable to set destructor callback"); + + // Now release the context, which SHOULD call the callbacks + error = clReleaseContext(localContext); + test_error(error, "Unable to release local context"); + + // Note: since we manually released the context, we need to set it to NULL + // to prevent a double-release + localContext = NULL; + + // At this point, all three callbacks should have already been called + int numErrors = 0; + for (int i = 0; i < 3; i++) + { + // Spin waiting for the release to finish. If you don't call the + // context_destructor_callback, you will not pass the test. + log_info("\tWaiting for callback %d...\n", i); + int wait = 0; + while (0 == callbackOrders[i]) + { + usleep(100000); // 1/10th second + if (++wait >= 10 * 10) + { + log_error("\tERROR: Callback %d was not called within 10 " + "seconds! Assuming failure.\n", + i + 1); + numErrors++; + break; + } + } + + if (callbackOrders[i] != 3 - i) + { + log_error("\tERROR: Callback %d was called in the wrong order! " + "(Was called order %d, should have been order %d)\n", + i + 1, callbackOrders[i], 3 - i); + numErrors++; + } + } + + return (numErrors > 0) ? TEST_FAIL : TEST_PASS; +} diff --git a/test_conformance/api/test_mem_objects.cpp b/test_conformance/api/test_mem_objects.cpp index b0dc99d4..c29613f9 100644 --- a/test_conformance/api/test_mem_objects.cpp +++ b/test_conformance/api/test_mem_objects.cpp @@ -1,6 +1,6 @@ // -// Copyright (c) 2017 The Khronos Group Inc. -// +// Copyright (c) 2020 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 @@ -17,92 +17,109 @@ static volatile cl_int sDestructorIndex; -void CL_CALLBACK mem_destructor_callback( cl_mem memObject, void * userData ) +void CL_CALLBACK mem_destructor_callback(cl_mem memObject, void *userData) { - int * userPtr = (int *)userData; + int *userPtr = (int *)userData; - // ordering of callbacks is guaranteed, meaning we don't need to do atomic operation here + // ordering of callbacks is guaranteed, meaning we don't need to do atomic + // operation here *userPtr = ++sDestructorIndex; } -#ifndef ABS -#define ABS( x ) ( ( x < 0 ) ? -x : x ) -#endif - -int test_mem_object_destructor_callback_single( clMemWrapper &memObject ) +int test_mem_object_destructor_callback_single(clMemWrapper &memObject) { cl_int error; - int i; // Set up some variables to catch the order in which callbacks are called - volatile int callbackOrders[ 3 ] = { 0, 0, 0 }; + volatile int callbackOrders[3] = { 0, 0, 0 }; sDestructorIndex = 0; // Set up the callbacks - error = clSetMemObjectDestructorCallback( memObject, mem_destructor_callback, (void*) &callbackOrders[ 0 ] ); - test_error( error, "Unable to set destructor callback" ); + error = clSetMemObjectDestructorCallback(memObject, mem_destructor_callback, + (void *)&callbackOrders[0]); + test_error(error, "Unable to set destructor callback"); - error = clSetMemObjectDestructorCallback( memObject, mem_destructor_callback, (void*) &callbackOrders[ 1 ] ); - test_error( error, "Unable to set destructor callback" ); + error = clSetMemObjectDestructorCallback(memObject, mem_destructor_callback, + (void *)&callbackOrders[1]); + test_error(error, "Unable to set destructor callback"); - error = clSetMemObjectDestructorCallback( memObject, mem_destructor_callback, (void*) &callbackOrders[ 2 ] ); - test_error( error, "Unable to set destructor callback" ); + error = clSetMemObjectDestructorCallback(memObject, mem_destructor_callback, + (void *)&callbackOrders[2]); + test_error(error, "Unable to set destructor callback"); // Now release the buffer, which SHOULD call the callbacks - error = clReleaseMemObject( memObject ); - test_error( error, "Unable to release test buffer" ); + error = clReleaseMemObject(memObject); + test_error(error, "Unable to release test buffer"); - // Note: since we manually released the mem wrapper, we need to set it to NULL to prevent a double-release + // Note: since we manually released the mem wrapper, we need to set it to + // NULL to prevent a double-release memObject = NULL; // At this point, all three callbacks should have already been called int numErrors = 0; - for( i = 0; i < 3; i++ ) + for (int i = 0; i < 3; i++) { - // Spin waiting for the release to finish. If you don't call the mem_destructor_callback, you will not - // pass the test. bugzilla 6316 - while( 0 == callbackOrders[i] ) - {} - - if( ABS( callbackOrders[ i ] ) != 3-i ) + // Spin waiting for the release to finish. If you don't call the + // mem_destructor_callback, you will not pass the test. bugzilla 6316 + log_info("\tWaiting for callback %d...\n", i); + int wait = 0; + while (0 == callbackOrders[i]) { - log_error( "\tERROR: Callback %d was called in the wrong order! (Was called order %d, should have been order %d)\n", - i+1, ABS( callbackOrders[ i ] ), i ); + usleep(100000); // 1/10th second + if (++wait >= 10 * 10) + { + log_error("\tERROR: Callback %d was not called within 10 " + "seconds! Assuming failure.\n", + i + 1); + numErrors++; + break; + } + } + + if (callbackOrders[i] != 3 - i) + { + log_error("\tERROR: Callback %d was called in the wrong order! " + "(Was called order %d, should have been order %d)\n", + i + 1, callbackOrders[i], 3 - i); numErrors++; } } - return ( numErrors > 0 ) ? -1 : 0; + return (numErrors > 0) ? TEST_FAIL : TEST_PASS; } -int test_mem_object_destructor_callback(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements) +int test_mem_object_destructor_callback(cl_device_id deviceID, + cl_context context, + cl_command_queue queue, + int num_elements) { clMemWrapper testBuffer, testImage; cl_int error; // Create a buffer and an image to test callbacks against - testBuffer = clCreateBuffer( context, CL_MEM_READ_WRITE, 1024, NULL, &error ); - test_error( error, "Unable to create testing buffer" ); + testBuffer = clCreateBuffer(context, CL_MEM_READ_WRITE, 1024, NULL, &error); + test_error(error, "Unable to create testing buffer"); - if( test_mem_object_destructor_callback_single( testBuffer ) != 0 ) + if (test_mem_object_destructor_callback_single(testBuffer) != TEST_PASS) { - log_error( "ERROR: Destructor callbacks for buffer object FAILED\n" ); - return -1; + log_error("ERROR: Destructor callbacks for buffer object FAILED\n"); + return TEST_FAIL; } - if( checkForImageSupport( deviceID ) == 0 ) + if (checkForImageSupport(deviceID) == 0) { cl_image_format imageFormat = { CL_RGBA, CL_SIGNED_INT8 }; - testImage = create_image_2d( context, CL_MEM_READ_ONLY, &imageFormat, 16, 16, 0, NULL, &error ); - test_error( error, "Unable to create testing image" ); + testImage = create_image_2d(context, CL_MEM_READ_ONLY, &imageFormat, 16, + 16, 0, NULL, &error); + test_error(error, "Unable to create testing image"); - if( test_mem_object_destructor_callback_single( testImage ) != 0 ) + if (test_mem_object_destructor_callback_single(testImage) != TEST_PASS) { - log_error( "ERROR: Destructor callbacks for image object FAILED\n" ); - return -1; + log_error("ERROR: Destructor callbacks for image object FAILED\n"); + return TEST_FAIL; } } - return 0; + return TEST_PASS; }