1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //    http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #if defined(__APPLE__)
17     #include <OpenCL/opencl.h>
18     #include <mach/mach_time.h>
19 #else
20     #include <CL/cl.h>
21   #include <malloc.h>
22 #endif
23 #include <assert.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include "harness/kernelHelpers.h"
27 
28 ///////////////////////////////////////////////////////////////////////////////
29 // CL error checking.
30 
31 #if defined(_MSC_VER)
32 #define CL_EXIT_ERROR(cmd,...) \
33 { \
34 if ((cmd) != CL_SUCCESS) { \
35 log_error("CL ERROR: %s %u: ", __FILE__,__LINE__);\
36 log_error(## __VA_ARGS__ );\
37 log_error("\n");\
38 return -1;\
39 }\
40 }
41 #else
42 #define CL_EXIT_ERROR(cmd,format,...) \
43 { \
44 if ((cmd) != CL_SUCCESS) { \
45 log_error("CL ERROR: %s %u: ", __FILE__,__LINE__);\
46 log_error(format,## __VA_ARGS__ );\
47 log_error("\n");\
48 return -1;\
49 }\
50 }
51 #endif
52 
53 #define CL_EXIT_BUILD_ERROR(cmd,program,format,...) \
54 { \
55 if ((cmd) != CL_SUCCESS) { \
56 cl_uint num_devices_;\
57 clGetProgramInfo(program,CL_PROGRAM_NUM_DEVICES,sizeof(num_devices_),&num_devices_,NULL);\
58 cl_device_id *device_list;\
59 device_list=(cl_device_id *)malloc(num_devices_*sizeof(cl_device_id));\
60 clGetProgramInfo(program,CL_PROGRAM_DEVICES,num_devices_*sizeof(cl_device_id),device_list,NULL);\
61 for (unsigned i=0;i<num_devices_;++i) {\
62 size_t len;\
63 char buffer[2048];\
64 clGetProgramBuildInfo(program,device_list[i],CL_PROGRAM_BUILD_LOG,sizeof(buffer),buffer,&len);\
65 log_error("DEVICE %u CL BUILD ERROR: %s(%u): ",i,__FILE__,__LINE__);\
66 log_error(format,## __VA_ARGS__ );\
67 log_error("\n");\
68 }\
69 free(device_list);\
70 return -1;\
71 }\
72 }
73 
74 const char* src[] = {
75   "__kernel void simple_task(__global float* output) {\n"
76   "  output[0] += 1;\n"
77   "}\n"
78 };
79 
80 enum { MaxDevices = 8 };
81 
test_userevents(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)82 int test_userevents( cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
83 {
84 
85   cl_int err;
86 
87   cl_event u1 = clCreateUserEvent( context, &err );
88   CL_EXIT_ERROR(err,"clCreateUserEvent failed");
89 
90   // Test event properties.
91   cl_int s;
92   size_t sizeofs;
93   CL_EXIT_ERROR(clGetEventInfo(u1, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof s, &s, &sizeofs),"clGetEventInfo failed");
94   CL_EXIT_ERROR((sizeof s == sizeofs) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong size for CL_EVENT_COMMAND_EXECUTION_STATUS");
95   CL_EXIT_ERROR((s == CL_SUBMITTED) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong value for CL_EVENT_COMMAND_EXECUTION_STATUS");
96 
97   cl_command_type t;
98   size_t sizeoft;
99   CL_EXIT_ERROR(clGetEventInfo(u1, CL_EVENT_COMMAND_TYPE, sizeof t, &t, &sizeoft),"clGetEventInfo failed");
100   CL_EXIT_ERROR((sizeof t == sizeoft) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong size for CL_EVENT_COMMAND_TYPE");
101   CL_EXIT_ERROR((t == CL_COMMAND_USER) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong value for CL_EVENT_COMMAND_TYPE");
102 
103   cl_command_queue q;
104   size_t sizeofq;
105   CL_EXIT_ERROR(clGetEventInfo(u1, CL_EVENT_COMMAND_QUEUE, sizeof q, &q, &sizeofq),"clGetEventInfo failed");
106   CL_EXIT_ERROR((sizeof q == sizeofq) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong size for CL_EVENT_COMMAND_QUEUE");
107   CL_EXIT_ERROR((q == NULL) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong value for CL_EVENT_COMMAND_QUEUE");
108 
109   cl_context c;
110   size_t sizeofc;
111   CL_EXIT_ERROR(clGetEventInfo(u1, CL_EVENT_CONTEXT, sizeof c, &c, &sizeofc),"clGetEventInfo failed");
112   CL_EXIT_ERROR((sizeof c == sizeofc) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong size for CL_EVENT_CONTEXT");
113   CL_EXIT_ERROR((c == context) ? CL_SUCCESS : -1,"clGetEventInfo returned wrong value for CL_EVENT_CONTEXT");
114 
115   cl_ulong p;
116   err = clGetEventProfilingInfo(u1,CL_PROFILING_COMMAND_QUEUED,sizeof p,&p,0);
117   CL_EXIT_ERROR((err != CL_SUCCESS) ? CL_SUCCESS : -1,"clGetEventProfilingInfo returned wrong error.");
118 
119   // Test semantics.
120   cl_program program;
121   err = create_single_kernel_helper_create_program(context, &program, 1, src);
122   CL_EXIT_ERROR(err,"clCreateProgramWithSource failed");
123 
124   CL_EXIT_BUILD_ERROR(clBuildProgram(program,0,NULL,"",NULL,NULL),program,"Building program from inline src:\t%s",src[0]);
125 
126   cl_kernel k0 = clCreateKernel(program,"simple_task",&err);
127   CL_EXIT_ERROR(err,"clCreateKernel failed");
128 
129   float buffer[1];
130   cl_mem output = clCreateBuffer(context,CL_MEM_USE_HOST_PTR,sizeof buffer, buffer, &err);
131   CL_EXIT_ERROR(err,"clCreateBuffer failed.");
132 
133   CL_EXIT_ERROR(clSetKernelArg(k0,0,sizeof(output),&output),"clSetKernelArg failed");
134 
135 
136   // Successful case. //////////////////////////////////////////////////////////////////////////////////////
137   {
138     cl_event e[4];
139     cl_uint  N = sizeof e / sizeof(cl_event);
140 
141     log_info("Enqueuing tasks\n");
142     for (cl_uint i = 0; i != N; ++i)
143       CL_EXIT_ERROR(clEnqueueTask(queue,k0,1,&u1,&e[i]),"clEnqueueTaskFailed");
144 
145     log_info("Checking task status before setting user event status\n");
146     for (cl_uint i = 0; i != N; ++i) {
147       CL_EXIT_ERROR(clGetEventInfo(e[i],CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof s,&s,0),"clGetEventInfo failed");
148       CL_EXIT_ERROR((s >= CL_SUBMITTED) ? CL_SUCCESS : -1,"clGetEventInfo %u returned wrong status before user event",i);
149     }
150 
151     log_info("Setting user event status to complete\n");
152     CL_EXIT_ERROR(clSetUserEventStatus(u1,CL_COMPLETE),"clSetUserEventStatus failed");
153 
154     log_info("Waiting for tasks to finish executing\n");
155     CL_EXIT_ERROR(clWaitForEvents( 1, &e[N-1] ),"clWaitForEvent failed");
156 
157     log_info("Checking task status after setting user event status\n");
158     for (cl_uint i = 0; i != N; ++i) {
159       CL_EXIT_ERROR(clGetEventInfo(e[i],CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof s,&s,0),"clGetEventInfo failed");
160       CL_EXIT_ERROR((s != CL_QUEUED) ? CL_SUCCESS : -1,"clGetEventInfo %u returned wrong status %04x after successful user event",i,s);
161     }
162 
163     CL_EXIT_ERROR(clReleaseEvent(u1),"clReleaseEvent failed");
164 
165     for (cl_uint i = 0; i != N; ++i)
166       CL_EXIT_ERROR(clReleaseEvent(e[i]),"clReleaseEvent failed");
167 
168     log_info("Successful user event case passed.\n");
169 
170   }
171 
172   // Test unsuccessful user event case. ///////////////////////////////////////////////////////////////////
173   {
174     cl_event u2 = clCreateUserEvent( context, &err );
175     CL_EXIT_ERROR(err,"clCreateUserEvent failed");
176 
177     cl_event e[4];
178     cl_uint  N = sizeof e / sizeof(cl_event);
179 
180     log_info("Enqueuing tasks\n");
181     for (cl_uint i = 0; i != N; ++i)
182       CL_EXIT_ERROR(clEnqueueTask(queue,k0,1,&u2,&e[i]),"clEnqueueTaskFailed");
183 
184     log_info("Checking task status before setting user event status\n");
185     for (cl_uint i = 0; i != N; ++i) {
186       CL_EXIT_ERROR(clGetEventInfo(e[i],CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof s,&s,0),"clGetEventInfo failed");
187       CL_EXIT_ERROR((s == CL_QUEUED || s == CL_SUBMITTED) ? CL_SUCCESS : -1,"clGetEventInfo %u returned wrong status %d before user event",i, (int) s);
188     }
189 
190     log_info("Setting user event status to unsuccessful result\n");
191     CL_EXIT_ERROR(clSetUserEventStatus(u2,-1),"clSetUserEventStatus failed");
192 
193     log_info("Waiting for tasks to finish executing\n");
194     CL_EXIT_ERROR((clWaitForEvents( N, &e[0] )!=CL_SUCCESS) ? CL_SUCCESS : -1,"clWaitForEvent succeeded when it should have failed");
195 
196     log_info("Checking task status after setting user event status\n");
197     for (cl_uint i = 0; i != N; ++i) {
198       CL_EXIT_ERROR(clGetEventInfo(e[i],CL_EVENT_COMMAND_EXECUTION_STATUS,sizeof s,&s,0),"clGetEventInfo failed");
199       CL_EXIT_ERROR((s != CL_QUEUED) ? CL_SUCCESS : -1,"clGetEventInfo %u returned wrong status %04x after unsuccessful user event",i,s);
200     }
201 
202     CL_EXIT_ERROR(clReleaseEvent(u2),"clReleaseEvent failed");
203 
204     for (cl_uint i = 0; i != N; ++i)
205       CL_EXIT_ERROR(clReleaseEvent(e[i]),"clReleaseEvent failed");
206 
207     log_info("Unsuccessful user event case passed.\n");
208   }
209 
210   clReleaseKernel(k0);
211   clReleaseProgram(program);
212   clReleaseMemObject(output);
213 
214   return 0;
215 
216 }
217 
218