diff --git a/CMakeLists.txt b/CMakeLists.txt index a31f4639f1..6e69e3ac17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -487,6 +487,7 @@ OCV_OPTION(CV_DISABLE_OPTIMIZATION "Disable explicit optimized code (dispatch OCV_OPTION(CV_TRACE "Enable OpenCV code trace" ON) OCV_OPTION(OPENCV_GENERATE_SETUPVARS "Generate setup_vars* scripts" ON IF (NOT ANDROID AND NOT APPLE_FRAMEWORK) ) OCV_OPTION(ENABLE_CONFIG_VERIFICATION "Fail build if actual configuration doesn't match requested (WITH_XXX != HAVE_XXX)" OFF) +OCV_OPTION(OPENCV_ENABLE_MEMALIGN "Enable posix_memalign or memalign usage" ON) OCV_OPTION(ENABLE_PYLINT "Add target with Pylint checks" (BUILD_DOCS OR BUILD_EXAMPLES) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) ) OCV_OPTION(ENABLE_FLAKE8 "Add target with Python flake8 checker" (BUILD_DOCS OR BUILD_EXAMPLES) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) ) @@ -635,10 +636,15 @@ if(UNIX) set(HAVE_PTHREAD 1) endif() - CHECK_SYMBOL_EXISTS(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN) - CHECK_INCLUDE_FILE(malloc.h HAVE_MALLOC_H) - if(HAVE_MALLOC_H) - CHECK_SYMBOL_EXISTS(memalign malloc.h HAVE_MEMALIGN) + if(OPENCV_ENABLE_MEMALIGN) + CHECK_SYMBOL_EXISTS(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN) + CHECK_INCLUDE_FILE(malloc.h HAVE_MALLOC_H) + if(HAVE_MALLOC_H) + CHECK_SYMBOL_EXISTS(memalign malloc.h HAVE_MEMALIGN) + endif() + # TODO: + # - _aligned_malloc() on Win32 + # - std::aligned_alloc() C++17 / C11 endif() endif() diff --git a/modules/core/src/alloc.cpp b/modules/core/src/alloc.cpp index 38d1fdc3f9..8384f6dd53 100644 --- a/modules/core/src/alloc.cpp +++ b/modules/core/src/alloc.cpp @@ -46,6 +46,7 @@ #undef CV_LOG_STRIP_LEVEL #define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1 #include +#include #define CV__ALLOCATOR_STATS_LOG(...) CV_LOG_VERBOSE(NULL, 0, "alloc.cpp: " << __VA_ARGS__) #include "opencv2/core/utils/allocator_stats.impl.hpp" @@ -81,6 +82,38 @@ cv::utils::AllocatorStatisticsInterface& getAllocatorStatistics() return allocator_stats; } +#if defined HAVE_POSIX_MEMALIGN || defined HAVE_MEMALIGN +static bool readMemoryAlignmentParameter() +{ + bool value = true; +#if defined(__GLIBC__) && defined(__linux__) \ + && !defined(CV_STATIC_ANALYSIS) \ + && !defined(OPENCV_ENABLE_MEMORY_SANITIZER) \ + && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) /* oss-fuzz */ \ + && !defined(_WIN32) /* MinGW? */ + { + // https://github.com/opencv/opencv/issues/15526 + value = false; + } +#endif + value = cv::utils::getConfigurationParameterBool("OPENCV_ENABLE_MEMALIGN", value); // should not call fastMalloc() internally + // TODO add checks for valgrind, ASAN if value == false + return value; +} +static inline +bool isAlignedAllocationEnabled() +{ + static bool initialized = false; + static bool useMemalign = true; + if (!initialized) + { + initialized = true; // trick to avoid stuck in acquire (works only if allocations are scope based) + useMemalign = readMemoryAlignmentParameter(); + } + return useMemalign; +} +#endif + #ifdef OPENCV_ALLOC_ENABLE_STATISTICS static inline void* fastMalloc_(size_t size) @@ -89,25 +122,30 @@ void* fastMalloc(size_t size) #endif { #ifdef HAVE_POSIX_MEMALIGN - void* ptr = NULL; - if(posix_memalign(&ptr, CV_MALLOC_ALIGN, size)) - ptr = NULL; - if(!ptr) - return OutOfMemoryError(size); - return ptr; + if (isAlignedAllocationEnabled()) + { + void* ptr = NULL; + if(posix_memalign(&ptr, CV_MALLOC_ALIGN, size)) + ptr = NULL; + if(!ptr) + return OutOfMemoryError(size); + return ptr; + } #elif defined HAVE_MEMALIGN - void* ptr = memalign(CV_MALLOC_ALIGN, size); - if(!ptr) - return OutOfMemoryError(size); - return ptr; -#else + if (isAlignedAllocationEnabled()) + { + void* ptr = memalign(CV_MALLOC_ALIGN, size); + if(!ptr) + return OutOfMemoryError(size); + return ptr; + } +#endif uchar* udata = (uchar*)malloc(size + sizeof(void*) + CV_MALLOC_ALIGN); if(!udata) return OutOfMemoryError(size); uchar** adata = alignPtr((uchar**)udata + 1, CV_MALLOC_ALIGN); adata[-1] = udata; return adata; -#endif } #ifdef OPENCV_ALLOC_ENABLE_STATISTICS @@ -118,8 +156,12 @@ void fastFree(void* ptr) #endif { #if defined HAVE_POSIX_MEMALIGN || defined HAVE_MEMALIGN - free(ptr); -#else + if (isAlignedAllocationEnabled()) + { + free(ptr); + return; + } +#endif if(ptr) { uchar* udata = ((uchar**)ptr)[-1]; @@ -127,7 +169,6 @@ void fastFree(void* ptr) ((uchar*)ptr - udata) <= (ptrdiff_t)(sizeof(void*)+CV_MALLOC_ALIGN)); free(udata); } -#endif } #ifdef OPENCV_ALLOC_ENABLE_STATISTICS