ocl: memory corruption check
authorAlexander Alekhin <alexander.alekhin@itseez.com>
Sat, 26 Oct 2013 11:03:23 +0000 (15:03 +0400)
committerAlexander Alekhin <alexander.alekhin@itseez.com>
Mon, 28 Oct 2013 15:33:00 +0000 (19:33 +0400)
modules/ocl/src/cl_operations.cpp

index cd948fc..7f09b1e 100644 (file)
@@ -109,6 +109,31 @@ cl_mem openCLCreateBuffer(Context *ctx, size_t flag , size_t size)
     return buffer;
 }
 
+//#define CHECK_MEMORY_CORRUPTION
+#ifdef CHECK_MEMORY_CORRUPTION
+//#define CHECK_MEMORY_CORRUPTION_PRINT_ERROR
+#define CHECK_MEMORY_CORRUPTION_RAISE_ERROR
+static const int __memory_corruption_check_bytes = 1024*1024;
+static const int __memory_corruption_check_pattern = 0x14326547; // change pattern for sizeof(int)==8
+struct CheckBuffers
+{
+    cl_mem mainBuffer;
+    size_t size;
+    size_t widthInBytes, height;
+    CheckBuffers()
+        : mainBuffer(NULL), size(0), widthInBytes(0), height(0)
+    {
+        // nothing
+    }
+    CheckBuffers(cl_mem _mainBuffer, size_t _size, size_t _widthInBytes, size_t _height)
+        : mainBuffer(_mainBuffer), size(_size), widthInBytes(_widthInBytes), height(_height)
+    {
+        // notihng
+    }
+};
+static std::map<cl_mem, CheckBuffers> __check_buffers;
+#endif
+
 void openCLMallocPitch(Context *ctx, void **dev_ptr, size_t *pitch,
                        size_t widthInBytes, size_t height)
 {
@@ -119,9 +144,34 @@ void openCLMallocPitchEx(Context *ctx, void **dev_ptr, size_t *pitch,
                        size_t widthInBytes, size_t height, DevMemRW rw_type, DevMemType mem_type)
 {
     cl_int status;
+    size_t size = widthInBytes * height;
+#ifndef CHECK_MEMORY_CORRUPTION
     *dev_ptr = clCreateBuffer(getClContext(ctx), gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type],
-                              widthInBytes * height, 0, &status);
+                              size, 0, &status);
     openCLVerifyCall(status);
+#else
+    size_t allocSize = size + __memory_corruption_check_bytes * 2;
+    cl_mem mainBuffer = clCreateBuffer(getClContext(ctx), gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type],
+            allocSize, 0, &status);
+    openCLVerifyCall(status);
+    cl_buffer_region r = {__memory_corruption_check_bytes, size};
+    *dev_ptr =  clCreateSubBuffer(mainBuffer,
+            gDevMemRWValueMap[rw_type]|gDevMemTypeValueMap[mem_type],
+            CL_BUFFER_CREATE_TYPE_REGION, &r,
+            &status);
+    openCLVerifyCall(status);
+    std::vector<int> tmp(__memory_corruption_check_bytes / sizeof(int),
+            __memory_corruption_check_pattern);
+    CV_Assert(tmp.size() * sizeof(int) == __memory_corruption_check_bytes);
+    openCLVerifyCall(clEnqueueWriteBuffer(getClCommandQueue(ctx),
+            mainBuffer, CL_TRUE, 0, __memory_corruption_check_bytes, &tmp[0],
+            0, NULL, NULL));
+    openCLVerifyCall(clEnqueueWriteBuffer(getClCommandQueue(ctx),
+            mainBuffer, CL_TRUE, __memory_corruption_check_bytes + size, __memory_corruption_check_bytes, &tmp[0],
+            0, NULL, NULL));
+    CheckBuffers data(mainBuffer, size, widthInBytes, height);
+    __check_buffers.insert(std::pair<cl_mem, CheckBuffers>((cl_mem)*dev_ptr, data));
+#endif
     *pitch = widthInBytes;
 }
 
@@ -174,7 +224,59 @@ void openCLCopyBuffer2D(Context *ctx, void *dst, size_t dpitch, int dst_offset,
 
 void openCLFree(void *devPtr)
 {
+#ifdef CHECK_MEMORY_CORRUPTION
+    bool failBefore = false, failAfter = false;
+    CheckBuffers data;
+    std::map<cl_mem, CheckBuffers>::iterator i = __check_buffers.find((cl_mem)devPtr);
+    if (i != __check_buffers.end())
+    {
+        data = i->second;
+        Context* ctx = Context::getContext();
+        std::vector<uchar> checkBefore(__memory_corruption_check_bytes);
+        std::vector<uchar> checkAfter(__memory_corruption_check_bytes);
+        openCLVerifyCall(clEnqueueReadBuffer(getClCommandQueue(ctx),
+                data.mainBuffer, CL_TRUE, 0, __memory_corruption_check_bytes, &checkBefore[0],
+                0, NULL, NULL));
+        openCLVerifyCall(clEnqueueReadBuffer(getClCommandQueue(ctx),
+                data.mainBuffer, CL_TRUE, __memory_corruption_check_bytes + data.size, __memory_corruption_check_bytes, &checkAfter[0],
+                0, NULL, NULL));
+
+        std::vector<int> tmp(__memory_corruption_check_bytes / sizeof(int),
+                __memory_corruption_check_pattern);
+
+        if (memcmp(&checkBefore[0], &tmp[0], __memory_corruption_check_bytes) != 0)
+        {
+            failBefore = true;
+        }
+        if (memcmp(&checkAfter[0], &tmp[0], __memory_corruption_check_bytes) != 0)
+        {
+            failAfter = true;
+        }
+        openCLSafeCall(clReleaseMemObject(data.mainBuffer));
+        __check_buffers.erase(i);
+    }
+#endif
     openCLSafeCall(clReleaseMemObject((cl_mem)devPtr));
+#ifdef CHECK_MEMORY_CORRUPTION
+    if (failBefore)
+    {
+#ifdef CHECK_MEMORY_CORRUPTION_PRINT_ERROR
+        std::cerr << "ERROR: Memory corruption detected: before buffer: " << cv::format("widthInBytes=%d height=%d", (int)data.widthInBytes, (int)data.height) << std::endl;
+#endif
+#ifdef CHECK_MEMORY_CORRUPTION_RAISE_ERROR
+        CV_Error(CV_StsInternal, "Memory corruption detected: before buffer");
+#endif
+    }
+    if (failAfter)
+    {
+#ifdef CHECK_MEMORY_CORRUPTION_PRINT_ERROR
+        std::cerr << "ERROR: Memory corruption detected: after buffer: " << cv::format("widthInBytes=%d height=%d", (int)data.widthInBytes, (int)data.height) << std::endl;
+#endif
+#ifdef CHECK_MEMORY_CORRUPTION_RAISE_ERROR
+        CV_Error(CV_StsInternal, "Memory corruption detected: after buffer");
+#endif
+    }
+#endif
 }
 
 cl_kernel openCLGetKernelFromSource(const Context *ctx, const cv::ocl::ProgramEntry* source, string kernelName)