It seems that according to the specification there’s a race condition between the clEnqueue* functions and clSetEventCallback. In other words, it seems that the implementation is allowed to start execution of enqueued commands at any point. So this means that if client is to register callbacks in the event object received from the call to clEnqueue there’s a race condition between the actual execution and the event registration.
The way I see this is that the race condition exists because a) queue can start processing at any time
b) event callbacks are edge-triggered as opposed to level-triggered.
The registered callback function will be called when the execution status of command associated with event changes to an execution status equal to or past the status specified by command_exec_status
The way I read this is that the callbacks will be fired on state change. Thus if state has already changed before a callback is registered the callback won’t fire.
So how is the client code supposed to use the callbacks safely?
There is no race condition. The spec states that for clSetEventCallback, the registered
callback function will be called when the execution status of command associated with event
changes to an execution status equal to or past the status specified by command_exec_status.
Let’s assume that the kernel you enqueued actually did get submitted to the device and finished execution and then the call to clSetEventCallBack was made on the host. The registered callbacks will still get called.
Are you sure of this? Since the state has already changed to CL_COMPLETE. Equal or past means that if callback is registered for CL_RUNNING for example it will get called when the state changes to CL_RUNNING (or past, i.e CL_COMPLETE/error).