add windows native aligned malloc + unit test case
authorDale Phurrough <dale@hidale.com>
Wed, 23 Dec 2020 13:59:28 +0000 (14:59 +0100)
committerDale Phurrough <dale@hidale.com>
Wed, 23 Dec 2020 13:59:28 +0000 (14:59 +0100)
* implements https://github.com/opencv/opencv/issues/19147
* CAUTION: this PR will only functions safely in the
  4+ branches that already include PR 19029
* CAUTION: this PR requires thread-safe startup of the alloc.cpp
  translation unit as implemented in PR 19029

CMakeLists.txt
modules/core/CMakeLists.txt
modules/core/src/alloc.cpp
modules/core/test/test_misc.cpp

index 90b4a26..bf805a6 100644 (file)
@@ -664,9 +664,18 @@ if(UNIX)
       CHECK_SYMBOL_EXISTS(memalign malloc.h HAVE_MEMALIGN)
     endif()
     # TODO:
-    # - _aligned_malloc() on Win32
     # - std::aligned_alloc() C++17 / C11
   endif()
+elseif(WIN32)
+  include(CheckIncludeFile)
+  include(CheckSymbolExists)
+
+  if(OPENCV_ENABLE_MEMALIGN)
+    CHECK_INCLUDE_FILE(malloc.h HAVE_MALLOC_H)
+    if(HAVE_MALLOC_H)
+      CHECK_SYMBOL_EXISTS(_aligned_malloc malloc.h HAVE_WIN32_ALIGNED_MALLOC)
+    endif()
+  endif()
 endif()
 
 include(cmake/OpenCVPCHSupport.cmake)
index 73e7f1d..cde2bb8 100644 (file)
@@ -80,6 +80,9 @@ endif()
 if(HAVE_MEMALIGN)
   ocv_append_source_file_compile_definitions(${CMAKE_CURRENT_SOURCE_DIR}/src/alloc.cpp "HAVE_MEMALIGN=1")
 endif()
+if(HAVE_WIN32_ALIGNED_MALLOC)
+  ocv_append_source_file_compile_definitions(${CMAKE_CURRENT_SOURCE_DIR}/src/alloc.cpp "HAVE_WIN32_ALIGNED_MALLOC=1")
+endif()
 if(HAVE_VA_INTEL_OLD_HEADER)
   ocv_append_source_file_compile_definitions("${CMAKE_CURRENT_LIST_DIR}/src/va_intel.cpp" "HAVE_VA_INTEL_OLD_HEADER")
 endif()
index 4b58fb6..a0def9d 100644 (file)
@@ -82,7 +82,7 @@ cv::utils::AllocatorStatisticsInterface& getAllocatorStatistics()
     return allocator_stats;
 }
 
-#if defined HAVE_POSIX_MEMALIGN || defined HAVE_MEMALIGN
+#if defined HAVE_POSIX_MEMALIGN || defined HAVE_MEMALIGN || defined HAVE_WIN32_ALIGNED_MALLOC
 static bool readMemoryAlignmentParameter()
 {
     bool value = true;
@@ -148,6 +148,14 @@ void* fastMalloc(size_t size)
             return OutOfMemoryError(size);
         return ptr;
     }
+#elif defined HAVE_WIN32_ALIGNED_MALLOC
+    if (isAlignedAllocationEnabled())
+    {
+        void* ptr = _aligned_malloc(size, CV_MALLOC_ALIGN);
+        if(!ptr)
+            return OutOfMemoryError(size);
+        return ptr;
+    }
 #endif
     uchar* udata = (uchar*)malloc(size + sizeof(void*) + CV_MALLOC_ALIGN);
     if(!udata)
@@ -170,6 +178,12 @@ void fastFree(void* ptr)
         free(ptr);
         return;
     }
+#elif defined HAVE_WIN32_ALIGNED_MALLOC
+    if (isAlignedAllocationEnabled())
+    {
+        _aligned_free(ptr);
+        return;
+    }
 #endif
     if(ptr)
     {
index 3934ceb..1d82ec5 100644 (file)
@@ -2,6 +2,7 @@
 // It is subject to the license terms in the LICENSE file found in the top-level directory
 // of this distribution and at http://opencv.org/license.html.
 #include "test_precomp.hpp"
+#include <cmath>
 
 namespace opencv_test { namespace {
 
@@ -783,5 +784,18 @@ TEST(Core_Check, testSize_1)
     }
 }
 
+TEST(Core_Allocation, alignedAllocation)
+{
+    // iterate from size=1 to approximate byte size of 8K 32bpp image buffer
+    for (int i = 0; i < 200; i++) {
+        const size_t size = static_cast<size_t>(std::pow(1.091, (double)i));
+        void * const buf = cv::fastMalloc(size);
+        ASSERT_NE((uintptr_t)0, (uintptr_t)buf)
+            << "failed to allocate memory";
+        ASSERT_EQ((uintptr_t)0, (uintptr_t)buf % CV_MALLOC_ALIGN)
+            << "memory not aligned to " << CV_MALLOC_ALIGN;
+        cv::fastFree(buf);
+    }
+}
 
 }} // namespace