halide/Halide — pull request #283 by white-pony (2014-05-02 23:40:02+00:00)
Title: Incorrect release function for the OpenCL target

I found that following code crashes, when I am running it with HL_JIT_TARGET=opencl (I have Mac OS X 10.7.5):

```c++
for(int ix = 0; ix < 2; ix++)
{
Halide::Image input(1024, 1024);

Halide::Var x("x"), y("y");
Halide::Func foo("foo");

foo(x, y) = input(x, y);

foo.gpu_tile(x, y, 16, 16);

Halide::Image output(input.width(), input.height());

foo.realize(output);
}
```

Crash happens on a second iteration of the loop. I did a small investigation and it seems that the problem is with halide_release function. More specifically, here:

```c++
cl_uint refs = 0;
clGetContextInfo(*cl_ctx, CL_CONTEXT_REFERENCE_COUNT, sizeof(refs), &refs, NULL);

// Unload context (ref counted).
CHECK_CALL( clReleaseCommandQueue(*cl_q), "clReleaseCommandQueue" );
#ifdef DEBUG
halide_printf(user_context, "clReleaseContext %p\n", *cl_ctx);
#endif
CHECK_CALL( clReleaseContext(*cl_ctx), "clReleaseContext" );

// See TODO above...
if (--refs == 0) {
*cl_ctx = NULL;
*cl_q = NULL;
}
```
I printed a number of references to the context and queue. In my particular case, I got 4 and 1 correspondingly. I traced all references to the context and found that: one reference is from clCreateContext, one from the clCreateCommandQueue and two from unreleased buffers (clCreateBuffers). As a result, queue will zero references after release, but will not have NULL assigned, because context still has references and this will cause problems on the next iteration.

I am not sure, what is a best solution, but I separated creation and release of the context and command queue and it fixes a problem.