system.cpp 79.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
I
Ilya Lavrenov 已提交
15
// Copyright (C) 2015, Itseez Inc., all rights reserved.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "precomp.hpp"
45
#include <iostream>
46
#include <ostream>
47

48
#include <opencv2/core/utils/configuration.private.hpp>
49 50
#include <opencv2/core/utils/trace.private.hpp>

51 52
#include <opencv2/core/utils/logger.hpp>

53 54 55
#include <opencv2/core/utils/tls.hpp>
#include <opencv2/core/utils/instrumentation.hpp>

56 57 58 59 60 61 62 63 64 65 66 67
#ifndef OPENCV_WITH_THREAD_SANITIZER
  #if defined(__clang__) && defined(__has_feature)
  #if __has_feature(thread_sanitizer)
      #define OPENCV_WITH_THREAD_SANITIZER 1
      #include <atomic>  // assume C++11
  #endif
  #endif
#endif
#ifndef OPENCV_WITH_THREAD_SANITIZER
    #define OPENCV_WITH_THREAD_SANITIZER 0
#endif

68 69
namespace cv {

70 71 72 73 74 75 76 77 78 79 80 81
static void _initSystem()
{
#ifdef __ANDROID__
    // https://github.com/opencv/opencv/issues/14906
    // "ios_base::Init" object is not a part of Android's "iostream" header (in case of clang toolchain, NDK 20).
    // Ref1: https://en.cppreference.com/w/cpp/io/ios_base/Init
    //       The header <iostream> behaves as if it defines (directly or indirectly) an instance of std::ios_base::Init with static storage duration
    // Ref2: https://github.com/gcc-mirror/gcc/blob/gcc-8-branch/libstdc%2B%2B-v3/include/std/iostream#L73-L74
    static std::ios_base::Init s_iostream_initializer;
#endif
}

82 83 84 85
static Mutex* __initialization_mutex = NULL;
Mutex& getInitializationMutex()
{
    if (__initialization_mutex == NULL)
86 87
    {
        (void)_initSystem();
88
        __initialization_mutex = new Mutex();
89
    }
90 91 92 93 94
    return *__initialization_mutex;
}
// force initialization (single-threaded environment)
Mutex* __initialization_mutex_initializer = &getInitializationMutex();

A
Alexander Alekhin 已提交
95 96 97 98 99 100 101 102
static bool param_dumpErrors = utils::getConfigurationParameterBool("OPENCV_DUMP_ERRORS",
#if defined(_DEBUG) || defined(__ANDROID__) || (defined(__GNUC__) && !defined(__EXCEPTIONS))
    true
#else
    false
#endif
);

103
void* allocSingletonBuffer(size_t size) { return fastMalloc(size); }
104 105
void* allocSingletonNewBuffer(size_t size) { return malloc(size); }

106

107 108
} // namespace cv

109 110 111 112 113
#ifndef CV_ERROR_SET_TERMINATE_HANDLER  // build config option
# if defined(_WIN32)
#   define CV_ERROR_SET_TERMINATE_HANDLER 1
# endif
#endif
114
#if defined(CV_ERROR_SET_TERMINATE_HANDLER) && !CV_ERROR_SET_TERMINATE_HANDLER
115 116 117
# undef CV_ERROR_SET_TERMINATE_HANDLER
#endif

118 119 120 121 122 123
#ifdef _MSC_VER
# if _MSC_VER >= 1700
#  pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
# endif
#endif

124 125 126 127 128
#ifdef CV_ERROR_SET_TERMINATE_HANDLER
#include <exception>      // std::set_terminate
#include <cstdlib>        // std::abort
#endif

129
#if defined __ANDROID__ || defined __unix__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __HAIKU__
I
Ilya Lavrenov 已提交
130 131
#  include <unistd.h>
#  include <fcntl.h>
132 133 134
#if defined __QNXNTO__
#  include <sys/elf.h>
#else
I
Ilya Lavrenov 已提交
135
#  include <elf.h>
136
#endif
137
#if defined __ANDROID__ || defined __linux__
I
Ilya Lavrenov 已提交
138 139
#  include <linux/auxvec.h>
#endif
B
Bert 已提交
140
#endif
I
Ilya Lavrenov 已提交
141

142
#if defined __ANDROID__ && defined HAVE_CPUFEATURES
143 144 145
#  include <cpu-features.h>
#endif

146

147
#if (defined __ppc64__ || defined __PPC64__) && defined __unix__
148 149 150 151
# include "sys/auxv.h"
# ifndef AT_HWCAP2
#   define AT_HWCAP2 26
# endif
152 153 154
# ifndef PPC_FEATURE2_ARCH_2_07
#   define PPC_FEATURE2_ARCH_2_07 0x80000000
# endif
155 156
# ifndef PPC_FEATURE2_ARCH_3_00
#   define PPC_FEATURE2_ARCH_3_00 0x00800000
S
Sayed Adel 已提交
157 158 159
# endif
#endif

160
#if defined _WIN32 || defined WINCE
161 162 163 164
#ifndef _WIN32_WINNT           // This is needed for the declaration of TryEnterCriticalSection in winbase.h with Visual Studio 2005 (and older?)
  #define _WIN32_WINNT 0x0400  // http://msdn.microsoft.com/en-us/library/ms686857(VS.85).aspx
#endif
#include <windows.h>
165
#if (_WIN32_WINNT >= 0x0602)
166
  #include <synchapi.h>
167
#endif
168 169 170 171
#if ((_WIN32_WINNT >= 0x0600) && !defined(CV_DISABLE_FLS)) || defined(CV_FORCE_FLS)
  #include <fibersapi.h>
  #define CV_USE_FLS
#endif
172 173 174 175
#undef small
#undef min
#undef max
#undef abs
176
#include <tchar.h>
177

178
#ifdef WINRT
179
#include <wrl/client.h>
G
GregoryMorse 已提交
180 181 182
#ifndef __cplusplus_winrt
#include <windows.storage.h>
#pragma comment(lib, "runtimeobject.lib")
183
#endif // WINRT
184 185 186

std::wstring GetTempPathWinRT()
{
G
GregoryMorse 已提交
187
#ifdef __cplusplus_winrt
188
    return std::wstring(Windows::Storage::ApplicationData::Current->TemporaryFolder->Path->Data());
G
GregoryMorse 已提交
189 190 191 192 193 194 195 196 197 198 199
#else
    Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationDataStatics> appdataFactory;
    Microsoft::WRL::ComPtr<ABI::Windows::Storage::IApplicationData> appdataRef;
    Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFolder> storagefolderRef;
    Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageItem> storageitemRef;
    HSTRING str;
    HSTRING_HEADER hstrHead;
    std::wstring wstr;
    if (FAILED(WindowsCreateStringReference(RuntimeClass_Windows_Storage_ApplicationData,
                                            (UINT32)wcslen(RuntimeClass_Windows_Storage_ApplicationData), &hstrHead, &str)))
        return wstr;
G
GregoryMorse 已提交
200
    if (FAILED(RoGetActivationFactory(str, IID_PPV_ARGS(appdataFactory.ReleaseAndGetAddressOf()))))
G
GregoryMorse 已提交
201 202 203 204 205 206 207 208 209 210 211 212 213 214
        return wstr;
    if (FAILED(appdataFactory->get_Current(appdataRef.ReleaseAndGetAddressOf())))
        return wstr;
    if (FAILED(appdataRef->get_TemporaryFolder(storagefolderRef.ReleaseAndGetAddressOf())))
        return wstr;
    if (FAILED(storagefolderRef.As(&storageitemRef)))
        return wstr;
    str = NULL;
    if (FAILED(storageitemRef->get_Path(&str)))
        return wstr;
    wstr = WindowsGetStringRawBuffer(str, NULL);
    WindowsDeleteString(str);
    return wstr;
#endif
215 216 217 218
}

std::wstring GetTempFileNameWinRT(std::wstring prefix)
{
219 220 221
    wchar_t guidStr[40];
    GUID g;
    CoCreateGuid(&g);
222
    wchar_t* mask = L"%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x";
223 224 225 226
    swprintf(&guidStr[0], sizeof(guidStr)/sizeof(wchar_t), mask,
             g.Data1, g.Data2, g.Data3, UINT(g.Data4[0]), UINT(g.Data4[1]),
             UINT(g.Data4[2]), UINT(g.Data4[3]), UINT(g.Data4[4]),
             UINT(g.Data4[5]), UINT(g.Data4[6]), UINT(g.Data4[7]));
227

228
    return prefix.append(std::wstring(guidStr));
229 230 231
}

#endif
232 233 234 235 236
#else
#include <pthread.h>
#include <sys/time.h>
#include <time.h>

237
#if defined __MACH__ && defined __APPLE__
238 239 240 241 242 243 244 245 246 247
#include <mach/mach.h>
#include <mach/mach_time.h>
#endif

#endif

#ifdef _OPENMP
#include "omp.h"
#endif

248
#if defined __unix__ || defined __APPLE__ || defined __EMSCRIPTEN__ || defined __FreeBSD__ || defined __GLIBC__ || defined __HAIKU__
249 250
#include <unistd.h>
#include <stdio.h>
251
#include <sys/types.h>
252
#if defined __ANDROID__
A
Andrey Kamaev 已提交
253
#include <sys/sysconf.h>
254
#endif
A
Andrey Kamaev 已提交
255
#endif
256

257
#ifdef __ANDROID__
258 259 260
# include <android/log.h>
#endif

261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
#ifdef DECLARE_CV_CPUID_X86
DECLARE_CV_CPUID_X86
#endif
#ifndef CV_CPUID_X86
  #if defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
    #if _MSC_VER >= 1400  // MSVS 2005
      #include <intrin.h>  // __cpuidex()
      #define CV_CPUID_X86 __cpuidex
    #else
      #error "Required MSVS 2005+"
    #endif
  #elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
    static void cv_cpuid(int* cpuid_data, int reg_eax, int reg_ecx)
    {
        int __eax = reg_eax, __ebx = 0, __ecx = reg_ecx, __edx = 0;
// tested with available compilers (-fPIC -O2 -m32/-m64): https://godbolt.org/
#if !defined(__PIC__) \
    || defined(__x86_64__) || __GNUC__ >= 5 \
    || defined(__clang__) || defined(__INTEL_COMPILER)
        __asm__("cpuid\n\t"
                : "+a" (__eax), "=b" (__ebx), "+c" (__ecx), "=d" (__edx)
        );
#elif defined(__i386__)  // ebx may be reserved as the PIC register
        __asm__("xchg{l}\t{%%}ebx, %1\n\t"
                "cpuid\n\t"
                "xchg{l}\t{%%}ebx, %1\n\t"
                : "+a" (__eax), "=&r" (__ebx), "+c" (__ecx), "=d" (__edx)
        );
#else
#error "Configuration error"
#endif
        cpuid_data[0] = __eax; cpuid_data[1] = __ebx; cpuid_data[2] = __ecx; cpuid_data[3] = __edx;
    }
    #define CV_CPUID_X86 cv_cpuid
  #endif
#endif


299 300 301
namespace cv
{

302 303
Exception::Exception() { code = 0; line = 0; }

304
Exception::Exception(int _code, const String& _err, const String& _func, const String& _file, int _line)
305 306 307 308 309 310 311 312 313
: code(_code), err(_err), func(_func), file(_file), line(_line)
{
    formatMessage();
}

Exception::~Exception() throw() {}

/*!
 \return the error description and the context as a text string.
314
 */
315 316 317 318
const char* Exception::what() const throw() { return msg.c_str(); }

void Exception::formatMessage()
{
A
Alexander Alekhin 已提交
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
    size_t pos = err.find('\n');
    bool multiline = pos != cv::String::npos;
    if (multiline)
    {
        std::stringstream ss;
        size_t prev_pos = 0;
        while (pos != cv::String::npos)
        {
           ss << "> " << err.substr(prev_pos, pos - prev_pos) << std::endl;
           prev_pos = pos + 1;
           pos = err.find('\n', prev_pos);
        }
        ss << "> " << err.substr(prev_pos);
        if (err[err.size() - 1] != '\n')
            ss << std::endl;
        err = ss.str();
    }
    if (func.size() > 0)
    {
        if (multiline)
            msg = format("OpenCV(%s) %s:%d: error: (%d:%s) in function '%s'\n%s", CV_VERSION, file.c_str(), line, code, cvErrorStr(code), func.c_str(), err.c_str());
        else
            msg = format("OpenCV(%s) %s:%d: error: (%d:%s) %s in function '%s'\n", CV_VERSION, file.c_str(), line, code, cvErrorStr(code), err.c_str(), func.c_str());
    }
343
    else
A
Alexander Alekhin 已提交
344 345 346
    {
        msg = format("OpenCV(%s) %s:%d: error: (%d:%s) %s%s", CV_VERSION, file.c_str(), line, code, cvErrorStr(code), err.c_str(), multiline ? "" : "\n");
    }
347
}
348

349 350 351 352 353 354 355 356 357 358 359 360
static const char* g_hwFeatureNames[CV_HARDWARE_MAX_FEATURE] = { NULL };

static const char* getHWFeatureName(int id)
{
    return (id < CV_HARDWARE_MAX_FEATURE) ? g_hwFeatureNames[id] : NULL;
}
static const char* getHWFeatureNameSafe(int id)
{
    const char* name = getHWFeatureName(id);
    return name ? name : "Unknown feature";
}

M
Maksim Shabunin 已提交
361 362 363 364
struct HWFeatures
{
    enum { MAX_FEATURE = CV_HARDWARE_MAX_FEATURE };

365
    HWFeatures(bool run_initialize = false)
M
Maksim Shabunin 已提交
366
    {
367 368 369
        memset( have, 0, sizeof(have[0]) * MAX_FEATURE );
        if (run_initialize)
            initialize();
M
Maksim Shabunin 已提交
370 371
    }

372
    static void initializeNames()
M
Maksim Shabunin 已提交
373
    {
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
        for (int i = 0; i < CV_HARDWARE_MAX_FEATURE; i++)
        {
            g_hwFeatureNames[i] = 0;
        }
        g_hwFeatureNames[CPU_MMX] = "MMX";
        g_hwFeatureNames[CPU_SSE] = "SSE";
        g_hwFeatureNames[CPU_SSE2] = "SSE2";
        g_hwFeatureNames[CPU_SSE3] = "SSE3";
        g_hwFeatureNames[CPU_SSSE3] = "SSSE3";
        g_hwFeatureNames[CPU_SSE4_1] = "SSE4.1";
        g_hwFeatureNames[CPU_SSE4_2] = "SSE4.2";
        g_hwFeatureNames[CPU_POPCNT] = "POPCNT";
        g_hwFeatureNames[CPU_FP16] = "FP16";
        g_hwFeatureNames[CPU_AVX] = "AVX";
        g_hwFeatureNames[CPU_AVX2] = "AVX2";
        g_hwFeatureNames[CPU_FMA3] = "FMA3";

        g_hwFeatureNames[CPU_AVX_512F] = "AVX512F";
        g_hwFeatureNames[CPU_AVX_512BW] = "AVX512BW";
        g_hwFeatureNames[CPU_AVX_512CD] = "AVX512CD";
        g_hwFeatureNames[CPU_AVX_512DQ] = "AVX512DQ";
        g_hwFeatureNames[CPU_AVX_512ER] = "AVX512ER";
A
Alexander Alekhin 已提交
396
        g_hwFeatureNames[CPU_AVX_512IFMA] = "AVX512IFMA";
397 398 399
        g_hwFeatureNames[CPU_AVX_512PF] = "AVX512PF";
        g_hwFeatureNames[CPU_AVX_512VBMI] = "AVX512VBMI";
        g_hwFeatureNames[CPU_AVX_512VL] = "AVX512VL";
400 401 402 403 404 405
        g_hwFeatureNames[CPU_AVX_512VBMI2] = "AVX512VBMI2";
        g_hwFeatureNames[CPU_AVX_512VNNI] = "AVX512VNNI";
        g_hwFeatureNames[CPU_AVX_512BITALG] = "AVX512BITALG";
        g_hwFeatureNames[CPU_AVX_512VPOPCNTDQ] = "AVX512VPOPCNTDQ";
        g_hwFeatureNames[CPU_AVX_5124VNNIW] = "AVX5124VNNIW";
        g_hwFeatureNames[CPU_AVX_5124FMAPS] = "AVX5124FMAPS";
406 407

        g_hwFeatureNames[CPU_NEON] = "NEON";
S
Sayed Adel 已提交
408 409

        g_hwFeatureNames[CPU_VSX] = "VSX";
410
        g_hwFeatureNames[CPU_VSX3] = "VSX3";
A
Alexander Alekhin 已提交
411

412 413
        g_hwFeatureNames[CPU_MSA] = "CPU_MSA";

A
Alexander Alekhin 已提交
414
        g_hwFeatureNames[CPU_AVX512_COMMON] = "AVX512-COMMON";
A
Alexander Alekhin 已提交
415
        g_hwFeatureNames[CPU_AVX512_SKX] = "AVX512-SKX";
416 417 418
        g_hwFeatureNames[CPU_AVX512_KNL] = "AVX512-KNL";
        g_hwFeatureNames[CPU_AVX512_KNM] = "AVX512-KNM";
        g_hwFeatureNames[CPU_AVX512_CNL] = "AVX512-CNL";
A
Alexander Alekhin 已提交
419
        g_hwFeatureNames[CPU_AVX512_CLX] = "AVX512-CLX";
420
        g_hwFeatureNames[CPU_AVX512_ICL] = "AVX512-ICL";
421 422 423 424
    }

    void initialize(void)
    {
425
#ifndef NO_GETENV
426 427 428 429 430 431 432 433 434
        if (getenv("OPENCV_DUMP_CONFIG"))
        {
            fprintf(stderr, "\nOpenCV build configuration is:\n%s\n",
                cv::getBuildInformation().c_str());
        }
#endif

        initializeNames();

435
    #ifdef CV_CPUID_X86
M
Maksim Shabunin 已提交
436
        int cpuid_data[4] = { 0, 0, 0, 0 };
437
        int cpuid_data_ex[4] = { 0, 0, 0, 0 };
M
Maksim Shabunin 已提交
438

439
        CV_CPUID_X86(cpuid_data, 1, 0/*unused*/);
M
Maksim Shabunin 已提交
440

441 442
        int x86_family = (cpuid_data[0] >> 8) & 15;
        if( x86_family >= 6 )
M
Maksim Shabunin 已提交
443
        {
444 445 446 447 448 449 450 451 452 453 454
            have[CV_CPU_MMX]    = (cpuid_data[3] & (1<<23)) != 0;
            have[CV_CPU_SSE]    = (cpuid_data[3] & (1<<25)) != 0;
            have[CV_CPU_SSE2]   = (cpuid_data[3] & (1<<26)) != 0;
            have[CV_CPU_SSE3]   = (cpuid_data[2] & (1<<0)) != 0;
            have[CV_CPU_SSSE3]  = (cpuid_data[2] & (1<<9)) != 0;
            have[CV_CPU_FMA3]   = (cpuid_data[2] & (1<<12)) != 0;
            have[CV_CPU_SSE4_1] = (cpuid_data[2] & (1<<19)) != 0;
            have[CV_CPU_SSE4_2] = (cpuid_data[2] & (1<<20)) != 0;
            have[CV_CPU_POPCNT] = (cpuid_data[2] & (1<<23)) != 0;
            have[CV_CPU_AVX]    = (cpuid_data[2] & (1<<28)) != 0;
            have[CV_CPU_FP16]   = (cpuid_data[2] & (1<<29)) != 0;
M
Maksim Shabunin 已提交
455 456 457

            // make the second call to the cpuid command in order to get
            // information about extended features like AVX2
458
            CV_CPUID_X86(cpuid_data_ex, 7, 0);
459 460 461

            have[CV_CPU_AVX2]   = (cpuid_data_ex[1] & (1<<5)) != 0;

462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
            have[CV_CPU_AVX_512F]         = (cpuid_data_ex[1] & (1<<16)) != 0;
            have[CV_CPU_AVX_512DQ]        = (cpuid_data_ex[1] & (1<<17)) != 0;
            have[CV_CPU_AVX_512IFMA]      = (cpuid_data_ex[1] & (1<<21)) != 0;
            have[CV_CPU_AVX_512PF]        = (cpuid_data_ex[1] & (1<<26)) != 0;
            have[CV_CPU_AVX_512ER]        = (cpuid_data_ex[1] & (1<<27)) != 0;
            have[CV_CPU_AVX_512CD]        = (cpuid_data_ex[1] & (1<<28)) != 0;
            have[CV_CPU_AVX_512BW]        = (cpuid_data_ex[1] & (1<<30)) != 0;
            have[CV_CPU_AVX_512VL]        = (cpuid_data_ex[1] & (1<<31)) != 0;
            have[CV_CPU_AVX_512VBMI]      = (cpuid_data_ex[2] & (1<<1))  != 0;
            have[CV_CPU_AVX_512VBMI2]     = (cpuid_data_ex[2] & (1<<6))  != 0;
            have[CV_CPU_AVX_512VNNI]      = (cpuid_data_ex[2] & (1<<11)) != 0;
            have[CV_CPU_AVX_512BITALG]    = (cpuid_data_ex[2] & (1<<12)) != 0;
            have[CV_CPU_AVX_512VPOPCNTDQ] = (cpuid_data_ex[2] & (1<<14)) != 0;
            have[CV_CPU_AVX_5124VNNIW]    = (cpuid_data_ex[3] & (1<<2))  != 0;
            have[CV_CPU_AVX_5124FMAPS]    = (cpuid_data_ex[3] & (1<<3))  != 0;
477 478 479 480 481 482 483 484 485 486 487

            bool have_AVX_OS_support = true;
            bool have_AVX512_OS_support = true;
            if (!(cpuid_data[2] & (1<<27)))
                have_AVX_OS_support = false; // OS uses XSAVE_XRSTORE and CPU support AVX
            else
            {
                int xcr0 = 0;
            #ifdef _XCR_XFEATURE_ENABLED_MASK // requires immintrin.h
                xcr0 = (int)_xgetbv(_XCR_XFEATURE_ENABLED_MASK);
            #elif defined __GNUC__ && (defined __i386__ || defined __x86_64__)
488
                __asm__ ("xgetbv\n\t" : "=a" (xcr0) : "c" (0) : "%edx" );
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
            #endif
                if ((xcr0 & 0x6) != 0x6)
                    have_AVX_OS_support = false; // YMM registers
                if ((xcr0 & 0xe6) != 0xe6)
                    have_AVX512_OS_support = false; // ZMM registers
            }

            if (!have_AVX_OS_support)
            {
                have[CV_CPU_AVX] = false;
                have[CV_CPU_FP16] = false;
                have[CV_CPU_AVX2] = false;
                have[CV_CPU_FMA3] = false;
            }
            if (!have_AVX_OS_support || !have_AVX512_OS_support)
            {
                have[CV_CPU_AVX_512F] = false;
                have[CV_CPU_AVX_512BW] = false;
                have[CV_CPU_AVX_512CD] = false;
                have[CV_CPU_AVX_512DQ] = false;
                have[CV_CPU_AVX_512ER] = false;
510
                have[CV_CPU_AVX_512IFMA] = false;
511 512 513
                have[CV_CPU_AVX_512PF] = false;
                have[CV_CPU_AVX_512VBMI] = false;
                have[CV_CPU_AVX_512VL] = false;
514 515 516 517 518 519
                have[CV_CPU_AVX_512VBMI2] = false;
                have[CV_CPU_AVX_512VNNI] = false;
                have[CV_CPU_AVX_512BITALG] = false;
                have[CV_CPU_AVX_512VPOPCNTDQ] = false;
                have[CV_CPU_AVX_5124VNNIW] = false;
                have[CV_CPU_AVX_5124FMAPS] = false;
520
            }
A
Alexander Alekhin 已提交
521

522 523
            have[CV_CPU_AVX512_COMMON] = have[CV_CPU_AVX_512F] && have[CV_CPU_AVX_512CD];
            if (have[CV_CPU_AVX512_COMMON])
A
Alexander Alekhin 已提交
524
            {
525 526 527 528 529
                have[CV_CPU_AVX512_KNL] = have[CV_CPU_AVX_512ER]  && have[CV_CPU_AVX_512PF];
                have[CV_CPU_AVX512_KNM] = have[CV_CPU_AVX512_KNL] && have[CV_CPU_AVX_5124FMAPS] &&
                                          have[CV_CPU_AVX_5124VNNIW] && have[CV_CPU_AVX_512VPOPCNTDQ];
                have[CV_CPU_AVX512_SKX] = have[CV_CPU_AVX_512BW] && have[CV_CPU_AVX_512DQ] && have[CV_CPU_AVX_512VL];
                have[CV_CPU_AVX512_CNL] = have[CV_CPU_AVX512_SKX] && have[CV_CPU_AVX_512IFMA] && have[CV_CPU_AVX_512VBMI];
A
Alexander Alekhin 已提交
530 531 532 533 534
                have[CV_CPU_AVX512_CLX] = have[CV_CPU_AVX512_SKX] && have[CV_CPU_AVX_512VNNI];
                have[CV_CPU_AVX512_ICL] = have[CV_CPU_AVX512_SKX] &&
                                          have[CV_CPU_AVX_512IFMA] && have[CV_CPU_AVX_512VBMI] &&
                                          have[CV_CPU_AVX_512VNNI] &&
                                          have[CV_CPU_AVX_512VBMI2] && have[CV_CPU_AVX_512BITALG] && have[CV_CPU_AVX_512VPOPCNTDQ];
535 536 537 538 539 540 541
            }
            else
            {
                have[CV_CPU_AVX512_KNL] = false;
                have[CV_CPU_AVX512_KNM] = false;
                have[CV_CPU_AVX512_SKX] = false;
                have[CV_CPU_AVX512_CNL] = false;
A
Alexander Alekhin 已提交
542
                have[CV_CPU_AVX512_CLX] = false;
543
                have[CV_CPU_AVX512_ICL] = false;
A
Alexander Alekhin 已提交
544
            }
M
Maksim Shabunin 已提交
545
        }
546
    #endif // CV_CPUID_X86
M
Maksim Shabunin 已提交
547

M
mikael 已提交
548
    #if defined __ANDROID__ || defined __linux__ || defined __FreeBSD__
M
Maksim Shabunin 已提交
549
    #ifdef __aarch64__
550 551
        have[CV_CPU_NEON] = true;
        have[CV_CPU_FP16] = true;
552
    #elif defined __arm__ && defined __ANDROID__
553
      #if defined HAVE_CPUFEATURES
554
        CV_LOG_INFO(NULL, "calling android_getCpuFeatures() ...");
555
        uint64_t features = android_getCpuFeatures();
556
        CV_LOG_INFO(NULL, cv::format("calling android_getCpuFeatures() ... Done (%llx)", (long long)features));
557 558
        have[CV_CPU_NEON] = (features & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
        have[CV_CPU_FP16] = (features & ANDROID_CPU_ARM_FEATURE_VFP_FP16) != 0;
559
      #else
560
        CV_LOG_INFO(NULL, "cpufeatures library is not available for CPU detection");
561
        #if CV_NEON
562
        CV_LOG_INFO(NULL, "- NEON instructions is enabled via build flags");
563 564
        have[CV_CPU_NEON] = true;
        #else
565
        CV_LOG_INFO(NULL, "- NEON instructions is NOT enabled via build flags");
566 567
        #endif
        #if CV_FP16
568
        CV_LOG_INFO(NULL, "- FP16 instructions is enabled via build flags");
569 570
        have[CV_CPU_FP16] = true;
        #else
571
        CV_LOG_INFO(NULL, "- FP16 instructions is NOT enabled via build flags");
572 573
        #endif
      #endif
M
mikael 已提交
574
    #elif defined __arm__ && !defined __FreeBSD__
M
Maksim Shabunin 已提交
575 576 577 578 579 580 581 582 583 584 585
        int cpufile = open("/proc/self/auxv", O_RDONLY);

        if (cpufile >= 0)
        {
            Elf32_auxv_t auxv;
            const size_t size_auxv_t = sizeof(auxv);

            while ((size_t)read(cpufile, &auxv, size_auxv_t) == size_auxv_t)
            {
                if (auxv.a_type == AT_HWCAP)
                {
586 587
                    have[CV_CPU_NEON] = (auxv.a_un.a_val & 4096) != 0;
                    have[CV_CPU_FP16] = (auxv.a_un.a_val & 2) != 0;
M
Maksim Shabunin 已提交
588 589 590 591 592 593 594
                    break;
                }
            }

            close(cpufile);
        }
    #endif
595 596
    #elif (defined __clang__ || defined __APPLE__)
    #if (defined __ARM_NEON__ || (defined __ARM_NEON && defined __aarch64__))
597
        have[CV_CPU_NEON] = true;
598 599
    #endif
    #if (defined __ARM_FP  && (((__ARM_FP & 0x2) != 0) && defined __ARM_NEON__))
600
        have[CV_CPU_FP16] = true;
601
    #endif
M
Maksim Shabunin 已提交
602
    #endif
603 604 605
    #if defined _ARM_ && (defined(_WIN32_WCE) && _WIN32_WCE >= 0x800)
        have[CV_CPU_NEON] = true;
    #endif
606 607 608
    #ifdef __mips_msa
        have[CV_CPU_MSA] = true;
    #endif
609

610
    #if (defined __ppc64__ || defined __PPC64__) && defined __unix__
611 612 613 614 615 616 617 618 619
        unsigned int hwcap = getauxval(AT_HWCAP);
        if (hwcap & PPC_FEATURE_HAS_VSX) {
            hwcap = getauxval(AT_HWCAP2);
            if (hwcap & PPC_FEATURE2_ARCH_3_00) {
                have[CV_CPU_VSX] = have[CV_CPU_VSX3] = true;
            } else {
                have[CV_CPU_VSX] = (hwcap & PPC_FEATURE2_ARCH_2_07) != 0;
            }
        }
S
Sayed Adel 已提交
620
    #else
621 622 623 624 625 626 627
        // TODO: AIX, FreeBSD
        #if CV_VSX || defined _ARCH_PWR8 || defined __POWER9_VECTOR__
            have[CV_CPU_VSX] = true;
        #endif
        #if CV_VSX3 || defined __POWER9_VECTOR__
            have[CV_CPU_VSX3] = true;
        #endif
S
Sayed Adel 已提交
628 629
    #endif

A
Alexander Alekhin 已提交
630 631 632 633 634 635 636
        bool skip_baseline_check = false;
#ifndef NO_GETENV
        if (getenv("OPENCV_SKIP_CPU_BASELINE_CHECK"))
        {
            skip_baseline_check = true;
        }
#endif
637
        int baseline_features[] = { CV_CPU_BASELINE_FEATURES };
A
Alexander Alekhin 已提交
638 639
        if (!checkFeatures(baseline_features, sizeof(baseline_features) / sizeof(baseline_features[0]))
            && !skip_baseline_check)
640 641 642 643 644 645 646 647 648 649
        {
            fprintf(stderr, "\n"
                    "******************************************************************\n"
                    "* FATAL ERROR:                                                   *\n"
                    "* This OpenCV build doesn't support current CPU/HW configuration *\n"
                    "*                                                                *\n"
                    "* Use OPENCV_DUMP_CONFIG=1 environment variable for details      *\n"
                    "******************************************************************\n");
            fprintf(stderr, "\nRequired baseline features:\n");
            checkFeatures(baseline_features, sizeof(baseline_features) / sizeof(baseline_features[0]), true);
650
            CV_Error(cv::Error::StsAssert, "Missing support for required CPU baseline features. Check OpenCV build configuration and required CPU/HW setup.");
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
        }

        readSettings(baseline_features, sizeof(baseline_features) / sizeof(baseline_features[0]));
    }

    bool checkFeatures(const int* features, int count, bool dump = false)
    {
        bool result = true;
        for (int i = 0; i < count; i++)
        {
            int feature = features[i];
            if (feature)
            {
                if (have[feature])
                {
A
Alexander Alekhin 已提交
666
                    if (dump) fprintf(stderr, "    ID=%3d (%s) - OK\n", feature, getHWFeatureNameSafe(feature));
667 668 669 670
                }
                else
                {
                    result = false;
A
Alexander Alekhin 已提交
671
                    if (dump) fprintf(stderr, "    ID=%3d (%s) - NOT AVAILABLE\n", feature, getHWFeatureNameSafe(feature));
672 673 674 675 676 677 678 679
                }
            }
        }
        return result;
    }

    static inline bool isSymbolSeparator(char c)
    {
680
        return c == ',' || c == ';';
681 682 683 684 685 686
    }

    void readSettings(const int* baseline_features, int baseline_count)
    {
        bool dump = true;
        const char* disabled_features =
687
#ifdef NO_GETENV
688
                NULL;
689 690
#else
                getenv("OPENCV_CPU_DISABLE");
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
#endif
        if (disabled_features && disabled_features[0] != 0)
        {
            const char* start = disabled_features;
            for (;;)
            {
                while (start[0] != 0 && isSymbolSeparator(start[0]))
                {
                    start++;
                }
                if (start[0] == 0)
                    break;
                const char* end = start;
                while (end[0] != 0 && !isSymbolSeparator(end[0]))
                {
                    end++;
                }
                if (end == start)
                    continue;
                cv::String feature(start, end);
                start = end;

                CV_Assert(feature.size() > 0);

                bool found = false;
                for (int i = 0; i < CV_HARDWARE_MAX_FEATURE; i++)
                {
                    if (!g_hwFeatureNames[i]) continue;
                    size_t len = strlen(g_hwFeatureNames[i]);
                    if (len != feature.size()) continue;
                    if (feature.compare(g_hwFeatureNames[i]) == 0)
                    {
                        bool isBaseline = false;
                        for (int k = 0; k < baseline_count; k++)
                        {
                            if (baseline_features[k] == i)
                            {
                                isBaseline = true;
                                break;
                            }
                        }
                        if (isBaseline)
                        {
734 735 736
                            if (dump) fprintf(stderr, "OPENCV: Trying to disable baseline CPU feature: '%s'."
                                                      "This has very limited effect, because code optimizations for this feature are executed unconditionally "
                                                      "in the most cases.\n", getHWFeatureNameSafe(i));
737 738 739
                        }
                        if (!have[i])
                        {
740 741
                            if (dump) fprintf(stderr, "OPENCV: Trying to disable unavailable CPU feature on the current platform: '%s'.\n",
                                getHWFeatureNameSafe(i));
742 743 744 745 746 747 748 749 750 751 752 753 754
                        }
                        have[i] = false;

                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    if (dump) fprintf(stderr, "OPENCV: Trying to disable unknown CPU feature: '%s'.\n", feature.c_str());
                }
            }
        }
M
Maksim Shabunin 已提交
755 756 757 758 759
    }

    bool have[MAX_FEATURE+1];
};

760
static HWFeatures  featuresEnabled(true), featuresDisabled = HWFeatures(false);
M
Maksim Shabunin 已提交
761 762
static HWFeatures* currentFeatures = &featuresEnabled;

763 764 765
bool checkHardwareSupport(int feature)
{
    CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
M
Maksim Shabunin 已提交
766
    return currentFeatures->have[feature];
767 768
}

769 770 771 772 773
String getHardwareFeatureName(int feature)
{
    const char* name = getHWFeatureName(feature);
    return name ? String(name) : String();
}
M
Maksim Shabunin 已提交
774

775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
std::string getCPUFeaturesLine()
{
    const int features[] = { CV_CPU_BASELINE_FEATURES, CV_CPU_DISPATCH_FEATURES };
    const int sz = sizeof(features) / sizeof(features[0]);
    std::string result;
    std::string prefix;
    for (int i = 1; i < sz; ++i)
    {
        if (features[i] == 0)
        {
            prefix = "*";
            continue;
        }
        if (i != 1) result.append(" ");
        result.append(prefix);
        result.append(getHWFeatureNameSafe(features[i]));
        if (!checkHardwareSupport(features[i])) result.append("?");
    }
    return result;
}

M
Maksim Shabunin 已提交
796 797
volatile bool useOptimizedFlag = true;

798 799
void setUseOptimized( bool flag )
{
M
Maksim Shabunin 已提交
800 801
    useOptimizedFlag = flag;
    currentFeatures = flag ? &featuresEnabled : &featuresDisabled;
802 803

    ipp::setUseIPP(flag);
804
#ifdef HAVE_OPENCL
805
    ocl::setUseOpenCL(flag);
806
#endif
807 808 809
#ifdef HAVE_TEGRA_OPTIMIZATION
    ::tegra::setUseTegra(flag);
#endif
810 811
}

812
bool useOptimized(void)
813
{
M
Maksim Shabunin 已提交
814
    return useOptimizedFlag;
815
}
816 817

int64 getTickCount(void)
818
{
819
#if defined _WIN32 || defined WINCE
820 821 822
    LARGE_INTEGER counter;
    QueryPerformanceCounter( &counter );
    return (int64)counter.QuadPart;
823 824 825
#elif defined __MACH__ && defined __APPLE__
    return (int64)mach_absolute_time();
#elif defined __unix__
826 827 828
    struct timespec tp;
    clock_gettime(CLOCK_MONOTONIC, &tp);
    return (int64)tp.tv_sec*1000000000 + tp.tv_nsec;
829
#else
830
    struct timeval tv;
831
    gettimeofday(&tv, NULL);
832 833 834 835
    return (int64)tv.tv_sec*1000000 + tv.tv_usec;
#endif
}

836
double getTickFrequency(void)
837
{
838
#if defined _WIN32 || defined WINCE
839 840 841
    LARGE_INTEGER freq;
    QueryPerformanceFrequency(&freq);
    return (double)freq.QuadPart;
842
#elif defined __MACH__ && defined __APPLE__
843 844 845 846 847 848 849
    static double freq = 0;
    if( freq == 0 )
    {
        mach_timebase_info_data_t sTimebaseInfo;
        mach_timebase_info(&sTimebaseInfo);
        freq = sTimebaseInfo.denom*1e9/sTimebaseInfo.numer;
    }
850
    return freq;
851 852
#elif defined __unix__
    return 1e9;
853 854 855 856 857
#else
    return 1e6;
#endif
}

858
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__ || defined __ppc__)
859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
#if defined(__i386__)

int64 getCPUTickCount(void)
{
    int64 x;
    __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
    return x;
}
#elif defined(__x86_64__)

int64 getCPUTickCount(void)
{
    unsigned hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return (int64)lo | ((int64)hi << 32);
}

#elif defined(__ppc__)

int64 getCPUTickCount(void)
{
    unsigned upper, lower, tmp;
    __asm__ volatile(
                     "0:                  \n"
                     "\tmftbu   %0           \n"
                     "\tmftb    %1           \n"
                     "\tmftbu   %2           \n"
                     "\tcmpw    %2,%0        \n"
                     "\tbne     0b         \n"
                     : "=r"(upper),"=r"(lower),"=r"(tmp)
                     );
    return lower | ((int64)upper << 32);
}

#else

#error "RDTSC not defined"

#endif

899
#elif defined _MSC_VER && defined _WIN32 && defined _M_IX86
900 901 902 903 904 905 906 907 908

int64 getCPUTickCount(void)
{
    __asm _emit 0x0f;
    __asm _emit 0x31;
}

#else

V
vbystricky 已提交
909 910 911 912 913 914
//#ifdef HAVE_IPP
//int64 getCPUTickCount(void)
//{
//    return ippGetCpuClocks();
//}
//#else
915
int64 getCPUTickCount(void)
916 917 918
{
    return getTickCount();
}
V
vbystricky 已提交
919
//#endif
920 921 922

#endif

923
const String& getBuildInformation()
924
{
925
    static String build_info =
926 927 928 929 930
#include "version_string.inc"
    ;
    return build_info;
}

931 932 933 934 935 936 937 938
String getVersionString() { return String(CV_VERSION); }

int getVersionMajor() { return CV_VERSION_MAJOR; }

int getVersionMinor() { return CV_VERSION_MINOR; }

int getVersionRevision() { return CV_VERSION_REVISION; }

939
String format( const char* fmt, ... )
940
{
I
Ilya Lavrenov 已提交
941
    AutoBuffer<char, 1024> buf;
942

I
Ilya Lavrenov 已提交
943
    for ( ; ; )
944
    {
I
Ilya Lavrenov 已提交
945
        va_list va;
946
        va_start(va, fmt);
A
Alexander Alekhin 已提交
947
        int bsize = static_cast<int>(buf.size());
948
        int len = cv_vsnprintf(buf.data(), bsize, fmt, va);
949 950
        va_end(va);

951 952
        CV_Assert(len >= 0 && "Check format string for errors");
        if (len >= bsize)
I
Ilya Lavrenov 已提交
953
        {
954
            buf.resize(len + 1);
I
Ilya Lavrenov 已提交
955 956
            continue;
        }
A
Alexander Alekhin 已提交
957
        buf[bsize - 1] = 0;
958
        return String(buf.data(), len);
I
Ilya Lavrenov 已提交
959
    }
960 961
}

962
String tempfile( const char* suffix )
963
{
964
    String fname;
965
#ifndef NO_GETENV
G
GregoryMorse 已提交
966
    const char *temp_dir = getenv("OPENCV_TEMP_PATH");
967
#endif
968

969
#if defined _WIN32
970
#ifdef WINRT
971
    RoInitialize(RO_INIT_MULTITHREADED);
972
    std::wstring temp_dir = GetTempPathWinRT();
973

974
    std::wstring temp_file = GetTempFileNameWinRT(L"ocv");
975
    if (temp_file.empty())
G
GregoryMorse 已提交
976
        return String();
977

978
    temp_file = temp_dir.append(std::wstring(L"\\")).append(temp_file);
979 980
    DeleteFileW(temp_file.c_str());

981 982 983
    char aname[MAX_PATH];
    size_t copied = wcstombs(aname, temp_file.c_str(), MAX_PATH);
    CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
G
GregoryMorse 已提交
984
    fname = String(aname);
985
    RoUninitialize();
986 987 988 989 990 991 992 993 994 995 996 997 998 999
#elif defined(_WIN32_WCE)
    const auto kMaxPathSize = MAX_PATH+1;
    wchar_t temp_dir[kMaxPathSize] = {0};
    wchar_t temp_file[kMaxPathSize] = {0};

    ::GetTempPathW(kMaxPathSize, temp_dir);

    if(0 != ::GetTempFileNameW(temp_dir, L"ocv", 0, temp_file)) {
        DeleteFileW(temp_file);
        char aname[MAX_PATH];
        size_t copied = wcstombs(aname, temp_file, MAX_PATH);
        CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
        fname = String(aname);
    }
1000
#else
1001 1002
    char temp_dir2[MAX_PATH] = { 0 };
    char temp_file[MAX_PATH] = { 0 };
1003

1004 1005 1006 1007 1008
    if (temp_dir == 0 || temp_dir[0] == 0)
    {
        ::GetTempPathA(sizeof(temp_dir2), temp_dir2);
        temp_dir = temp_dir2;
    }
1009
    if(0 == ::GetTempFileNameA(temp_dir, "ocv", 0, temp_file))
1010
        return String();
1011

R
Roy Reapor 已提交
1012 1013
    DeleteFileA(temp_file);

1014
    fname = temp_file;
1015
#endif
1016
# else
1017
#  ifdef __ANDROID__
1018 1019 1020 1021 1022 1023
    //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX";
    char defaultTemplate[] = "/data/local/tmp/__opencv_temp.XXXXXX";
#  else
    char defaultTemplate[] = "/tmp/__opencv_temp.XXXXXX";
#  endif

1024
    if (temp_dir == 0 || temp_dir[0] == 0)
1025 1026 1027 1028 1029 1030
        fname = defaultTemplate;
    else
    {
        fname = temp_dir;
        char ech = fname[fname.size() - 1];
        if(ech != '/' && ech != '\\')
1031 1032
            fname = fname + "/";
        fname = fname + "__opencv_temp.XXXXXX";
1033 1034 1035
    }

    const int fd = mkstemp((char*)fname.c_str());
1036
    if (fd == -1) return String();
1037

1038 1039
    close(fd);
    remove(fname.c_str());
1040
# endif
1041

1042
    if (suffix)
1043 1044
    {
        if (suffix[0] != '.')
1045
            return fname + "." + suffix;
1046
        else
1047
            return fname + suffix;
1048 1049
    }
    return fname;
1050 1051
}

1052
static ErrorCallback customErrorCallback = 0;
1053 1054 1055 1056 1057 1058 1059 1060
static void* customErrorCallbackData = 0;
static bool breakOnError = false;

bool setBreakOnError(bool value)
{
    bool prevVal = breakOnError;
    breakOnError = value;
    return prevVal;
1061
}
1062

1063
int cv_snprintf(char* buf, int len, const char* fmt, ...)
A
Alexander Alekhin 已提交
1064 1065 1066
{
    va_list va;
    va_start(va, fmt);
1067
    int res = cv_vsnprintf(buf, len, fmt, va);
A
Alexander Alekhin 已提交
1068
    va_end(va);
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
    return res;
}

int cv_vsnprintf(char* buf, int len, const char* fmt, va_list args)
{
#if defined _MSC_VER
    if (len <= 0) return len == 0 ? 1024 : -1;
    int res = _vsnprintf_s(buf, len, _TRUNCATE, fmt, args);
    // ensure null terminating on VS
    if (res >= 0 && res < len)
    {
        buf[res] = 0;
        return res;
    }
    else
    {
        buf[len - 1] = 0; // truncate happened
        return res >= len ? res : (len * 2);
    }
A
Alexander Alekhin 已提交
1088
#else
1089
    return vsnprintf(buf, len, fmt, args);
A
Alexander Alekhin 已提交
1090 1091 1092
#endif
}

1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126
static void dumpException(const Exception& exc)
{
    const char* errorStr = cvErrorStr(exc.code);
    char buf[1 << 12];

    cv_snprintf(buf, sizeof(buf),
        "OpenCV(%s) Error: %s (%s) in %s, file %s, line %d",
        CV_VERSION,
        errorStr, exc.err.c_str(), exc.func.size() > 0 ?
        exc.func.c_str() : "unknown function", exc.file.c_str(), exc.line);
#ifdef __ANDROID__
    __android_log_print(ANDROID_LOG_ERROR, "cv::error()", "%s", buf);
#else
    fflush(stdout); fflush(stderr);
    fprintf(stderr, "%s\n", buf);
    fflush(stderr);
#endif
}

#ifdef CV_ERROR_SET_TERMINATE_HANDLER
static bool cv_terminate_handler_installed = false;
static std::terminate_handler cv_old_terminate_handler;
static cv::Exception cv_terminate_handler_exception;
static bool param_setupTerminateHandler = utils::getConfigurationParameterBool("OPENCV_SETUP_TERMINATE_HANDLER", true);
static void cv_terminate_handler() {
    std::cerr << "OpenCV: terminate handler is called! The last OpenCV error is:\n";
    dumpException(cv_terminate_handler_exception);
    if (false /*cv_old_terminate_handler*/)  // buggy behavior is observed with doubled "abort/retry/ignore" windows
        cv_old_terminate_handler();
    abort();
}

#endif

1127 1128
void error( const Exception& exc )
{
1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141
#ifdef CV_ERROR_SET_TERMINATE_HANDLER
    {
        cv::AutoLock lock(getInitializationMutex());
        if (!cv_terminate_handler_installed)
        {
            if (param_setupTerminateHandler)
                cv_old_terminate_handler = std::set_terminate(cv_terminate_handler);
            cv_terminate_handler_installed = true;
        }
        cv_terminate_handler_exception = exc;
    }
#endif

1142
    if (customErrorCallback != 0)
1143 1144
        customErrorCallback(exc.code, exc.func.c_str(), exc.err.c_str(),
                            exc.file.c_str(), exc.line, customErrorCallbackData);
A
Alexander Alekhin 已提交
1145
    else if (param_dumpErrors)
1146
    {
1147
        dumpException(exc);
1148
    }
1149

1150 1151 1152 1153 1154
    if(breakOnError)
    {
        static volatile int* p = 0;
        *p = 0;
    }
1155

A
Alexander Alekhin 已提交
1156
    throw exc;
1157
}
1158

1159 1160 1161 1162 1163
void error(int _code, const String& _err, const char* _func, const char* _file, int _line)
{
    error(cv::Exception(_code, _err, _func, _file, _line));
}

A
Alexander Alekhin 已提交
1164

1165 1166
ErrorCallback
redirectError( ErrorCallback errCallback, void* userdata, void** prevUserdata)
1167 1168 1169
{
    if( prevUserdata )
        *prevUserdata = customErrorCallbackData;
1170

1171
    ErrorCallback prevCallback = customErrorCallback;
1172 1173

    customErrorCallback     = errCallback;
1174
    customErrorCallbackData = userdata;
1175

1176 1177
    return prevCallback;
}
1178

1179 1180 1181 1182 1183
}

CV_IMPL int cvCheckHardwareSupport(int feature)
{
    CV_DbgAssert( 0 <= feature && feature <= CV_HARDWARE_MAX_FEATURE );
M
Maksim Shabunin 已提交
1184
    return cv::currentFeatures->have[feature];
1185 1186 1187 1188
}

CV_IMPL int cvUseOptimized( int flag )
{
M
Maksim Shabunin 已提交
1189
    int prevMode = cv::useOptimizedFlag;
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
    cv::setUseOptimized( flag != 0 );
    return prevMode;
}

CV_IMPL int64  cvGetTickCount(void)
{
    return cv::getTickCount();
}

CV_IMPL double cvGetTickFrequency(void)
{
    return cv::getTickFrequency()*1e-6;
}

CV_IMPL CvErrorCallback
cvRedirectError( CvErrorCallback errCallback, void* userdata, void** prevUserdata)
{
    return cv::redirectError(errCallback, userdata, prevUserdata);
}

CV_IMPL int cvNulDevReport( int, const char*, const char*,
                            const char*, int, void* )
{
    return 0;
}

CV_IMPL int cvStdErrReport( int, const char*, const char*,
                            const char*, int, void* )
{
    return 0;
}

CV_IMPL int cvGuiBoxReport( int, const char*, const char*,
                            const char*, int, void* )
{
    return 0;
}

CV_IMPL int cvGetErrInfo( const char**, const char**, const char**, int* )
{
    return 0;
}


CV_IMPL const char* cvErrorStr( int status )
{
    static char buf[256];

    switch (status)
    {
1240 1241 1242 1243 1244 1245 1246 1247 1248 1249
    case CV_StsOk :                  return "No Error";
    case CV_StsBackTrace :           return "Backtrace";
    case CV_StsError :               return "Unspecified error";
    case CV_StsInternal :            return "Internal error";
    case CV_StsNoMem :               return "Insufficient memory";
    case CV_StsBadArg :              return "Bad argument";
    case CV_StsNoConv :              return "Iterations do not converge";
    case CV_StsAutoTrace :           return "Autotrace call";
    case CV_StsBadSize :             return "Incorrect size of input array";
    case CV_StsNullPtr :             return "Null pointer";
1250
    case CV_StsDivByZero :           return "Division by zero occurred";
1251
    case CV_BadStep :                return "Image step is wrong";
1252 1253
    case CV_StsInplaceNotSupported : return "Inplace operation is not supported";
    case CV_StsObjectNotFound :      return "Requested object was not found";
1254 1255 1256
    case CV_BadDepth :               return "Input image depth is not supported by function";
    case CV_StsUnmatchedFormats :    return "Formats of input arguments do not match";
    case CV_StsUnmatchedSizes :      return "Sizes of input arguments do not match";
1257
    case CV_StsOutOfRange :          return "One of the arguments\' values is out of range";
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267
    case CV_StsUnsupportedFormat :   return "Unsupported format or combination of formats";
    case CV_BadCOI :                 return "Input COI is not supported";
    case CV_BadNumChannels :         return "Bad number of channels";
    case CV_StsBadFlag :             return "Bad flag (parameter or structure field)";
    case CV_StsBadPoint :            return "Bad parameter of type CvPoint";
    case CV_StsBadMask :             return "Bad type of mask argument";
    case CV_StsParseError :          return "Parsing error";
    case CV_StsNotImplemented :      return "The function/feature is not implemented";
    case CV_StsBadMemBlock :         return "Memory block has been corrupted";
    case CV_StsAssert :              return "Assertion failed";
V
Vladislav Vinogradov 已提交
1268
    case CV_GpuNotSupported :        return "No CUDA support";
1269 1270 1271
    case CV_GpuApiCallError :        return "Gpu API call";
    case CV_OpenGlNotSupported :     return "No OpenGL support";
    case CV_OpenGlApiCallError :     return "OpenGL API call";
1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287
    };

    sprintf(buf, "Unknown %s code %d", status >= 0 ? "status":"error", status);
    return buf;
}

CV_IMPL int cvGetErrMode(void)
{
    return 0;
}

CV_IMPL int cvSetErrMode(int)
{
    return 0;
}

1288
CV_IMPL int cvGetErrStatus(void)
1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310
{
    return 0;
}

CV_IMPL void cvSetErrStatus(int)
{
}


CV_IMPL void cvError( int code, const char* func_name,
                      const char* err_msg,
                      const char* file_name, int line )
{
    cv::error(cv::Exception(code, err_msg, func_name, file_name, line));
}

/* function, which converts int to int */
CV_IMPL int
cvErrorFromIppStatus( int status )
{
    switch (status)
    {
1311 1312 1313 1314 1315 1316 1317 1318
    case CV_BADSIZE_ERR:               return CV_StsBadSize;
    case CV_BADMEMBLOCK_ERR:           return CV_StsBadMemBlock;
    case CV_NULLPTR_ERR:               return CV_StsNullPtr;
    case CV_DIV_BY_ZERO_ERR:           return CV_StsDivByZero;
    case CV_BADSTEP_ERR:               return CV_BadStep;
    case CV_OUTOFMEM_ERR:              return CV_StsNoMem;
    case CV_BADARG_ERR:                return CV_StsBadArg;
    case CV_NOTDEFINED_ERR:            return CV_StsError;
1319
    case CV_INPLACE_NOT_SUPPORTED_ERR: return CV_StsInplaceNotSupported;
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
    case CV_NOTFOUND_ERR:              return CV_StsObjectNotFound;
    case CV_BADCONVERGENCE_ERR:        return CV_StsNoConv;
    case CV_BADDEPTH_ERR:              return CV_BadDepth;
    case CV_UNMATCHED_FORMATS_ERR:     return CV_StsUnmatchedFormats;
    case CV_UNSUPPORTED_COI_ERR:       return CV_BadCOI;
    case CV_UNSUPPORTED_CHANNELS_ERR:  return CV_BadNumChannels;
    case CV_BADFLAG_ERR:               return CV_StsBadFlag;
    case CV_BADRANGE_ERR:              return CV_StsBadArg;
    case CV_BADCOEF_ERR:               return CV_StsBadArg;
    case CV_BADFACTOR_ERR:             return CV_StsBadArg;
    case CV_BADPOINT_ERR:              return CV_StsBadPoint;

    default:
      return CV_StsError;
1334 1335 1336
    }
}

1337 1338 1339
namespace cv {
bool __termination = false;
}
1340

1341 1342 1343
namespace cv
{

1344
#if defined _WIN32 || defined WINCE
1345 1346 1347

struct Mutex::Impl
{
1348 1349 1350 1351 1352 1353 1354 1355 1356
    Impl()
    {
#if (_WIN32_WINNT >= 0x0600)
        ::InitializeCriticalSectionEx(&cs, 1000, 0);
#else
        ::InitializeCriticalSection(&cs);
#endif
        refcount = 1;
    }
1357
    ~Impl() { DeleteCriticalSection(&cs); }
1358

1359 1360 1361
    void lock() { EnterCriticalSection(&cs); }
    bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
    void unlock() { LeaveCriticalSection(&cs); }
1362

1363 1364 1365
    CRITICAL_SECTION cs;
    int refcount;
};
1366

1367 1368 1369 1370
#else

struct Mutex::Impl
{
I
Ilya Lavrenov 已提交
1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381
    Impl()
    {
        pthread_mutexattr_t attr;
        pthread_mutexattr_init(&attr);
        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&mt, &attr);
        pthread_mutexattr_destroy(&attr);

        refcount = 1;
    }
    ~Impl() { pthread_mutex_destroy(&mt); }
1382

I
Ilya Lavrenov 已提交
1383 1384 1385
    void lock() { pthread_mutex_lock(&mt); }
    bool trylock() { return pthread_mutex_trylock(&mt) == 0; }
    void unlock() { pthread_mutex_unlock(&mt); }
1386

I
Ilya Lavrenov 已提交
1387
    pthread_mutex_t mt;
1388 1389 1390 1391 1392 1393 1394 1395 1396
    int refcount;
};

#endif

Mutex::Mutex()
{
    impl = new Mutex::Impl;
}
1397

1398 1399 1400 1401 1402 1403
Mutex::~Mutex()
{
    if( CV_XADD(&impl->refcount, -1) == 1 )
        delete impl;
    impl = 0;
}
1404

1405 1406 1407 1408 1409 1410 1411 1412
Mutex::Mutex(const Mutex& m)
{
    impl = m.impl;
    CV_XADD(&impl->refcount, 1);
}

Mutex& Mutex::operator = (const Mutex& m)
{
1413 1414 1415 1416 1417 1418 1419
    if (this != &m)
    {
        CV_XADD(&m.impl->refcount, 1);
        if( CV_XADD(&impl->refcount, -1) == 1 )
            delete impl;
        impl = m.impl;
    }
1420 1421
    return *this;
}
1422

1423 1424
void Mutex::lock() { impl->lock(); }
void Mutex::unlock() { impl->unlock(); }
1425
bool Mutex::trylock() { return impl->trylock(); }
1426

A
Alexander Alekhin 已提交
1427 1428 1429

//////////////////////////////// thread-local storage ////////////////////////////////

1430 1431
namespace details {

1432
#ifdef _WIN32
P
Pavel Vlasov 已提交
1433 1434 1435 1436 1437 1438 1439 1440 1441
#ifdef _MSC_VER
#pragma warning(disable:4505) // unreferenced local function has been removed
#endif
#ifndef TLS_OUT_OF_INDEXES
#define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
#endif
#endif

// TLS platform abstraction layer
1442
class TlsAbstraction
A
Alexander Alekhin 已提交
1443 1444
{
public:
P
Pavel Vlasov 已提交
1445
    TlsAbstraction();
1446
    ~TlsAbstraction()
1447
    {
1448 1449 1450 1451 1452
        // TlsAbstraction singleton should not be released
        // There is no reliable way to avoid problems caused by static initialization order fiasco
        // NB: Do NOT use logging here
        fprintf(stderr, "OpenCV FATAL: TlsAbstraction::~TlsAbstraction() call is not expected\n");
        fflush(stderr);
1453
    }
A
Alexander Alekhin 已提交
1454

1455 1456 1457 1458 1459
    void* getData() const;
    void setData(void *pData);

    void releaseSystemResources();

P
Pavel Vlasov 已提交
1460
private:
1461

1462
#ifdef _WIN32
P
Pavel Vlasov 已提交
1463 1464
#ifndef WINRT
    DWORD tlsKey;
1465
    bool disposed;
A
Alexander Alekhin 已提交
1466
#endif
1467
#else // _WIN32
P
Pavel Vlasov 已提交
1468
    pthread_key_t  tlsKey;
1469 1470 1471 1472 1473
#if OPENCV_WITH_THREAD_SANITIZER
    std::atomic<bool> disposed;
#else
    bool disposed;
#endif
P
Pavel Vlasov 已提交
1474 1475
#endif
};
A
Alexander Alekhin 已提交
1476

1477
class TlsAbstractionReleaseGuard
1478
{
1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
    TlsAbstraction& tls_;
public:
    TlsAbstractionReleaseGuard(TlsAbstraction& tls) : tls_(tls)
    {
        /* nothing */
    }
    ~TlsAbstractionReleaseGuard()
    {
        tls_.releaseSystemResources();
    }
};

// TODO use reference
1492 1493 1494
static TlsAbstraction* getTlsAbstraction()
{
#ifdef CV_CXX11
1495 1496
    static TlsAbstraction *g_tls = new TlsAbstraction();  // memory leak is intended here to avoid disposing of TLS container
    static TlsAbstractionReleaseGuard g_tlsReleaseGuard(*g_tls);
1497
#else
1498 1499
    static TlsAbstraction* volatile g_tls = NULL;
    if (g_tls == NULL)
1500 1501
    {
        cv::AutoLock lock(cv::getInitializationMutex());
1502 1503 1504 1505 1506
        if (g_tls == NULL)
        {
            g_tls = new TlsAbstraction();
            static TlsAbstractionReleaseGuard g_tlsReleaseGuard(*g_tls);
        }
1507 1508
    }
#endif
1509
    return g_tls;
1510 1511 1512
}


1513
#ifdef _WIN32
1514
#ifdef WINRT
P
Pavel Vlasov 已提交
1515 1516
static __declspec( thread ) void* tlsData = NULL; // using C++11 thread attribute for local thread data
TlsAbstraction::TlsAbstraction() {}
1517 1518 1519 1520 1521
void TlsAbstraction::releaseSystemResources()
{
    cv::__termination = true;  // DllMain is missing in static builds
}
void* TlsAbstraction::getData() const
P
Pavel Vlasov 已提交
1522 1523 1524
{
    return tlsData;
}
1525
void TlsAbstraction::setData(void *pData)
P
Pavel Vlasov 已提交
1526 1527 1528 1529
{
    tlsData = pData;
}
#else //WINRT
1530 1531 1532
#ifdef CV_USE_FLS
static void NTAPI opencv_fls_destructor(void* pData);
#endif // CV_USE_FLS
P
Pavel Vlasov 已提交
1533
TlsAbstraction::TlsAbstraction()
1534
    : disposed(false)
P
Pavel Vlasov 已提交
1535
{
1536
#ifndef CV_USE_FLS
P
Pavel Vlasov 已提交
1537
    tlsKey = TlsAlloc();
1538 1539 1540
#else // CV_USE_FLS
    tlsKey = FlsAlloc(opencv_fls_destructor);
#endif // CV_USE_FLS
P
Pavel Vlasov 已提交
1541 1542
    CV_Assert(tlsKey != TLS_OUT_OF_INDEXES);
}
1543
void TlsAbstraction::releaseSystemResources()
P
Pavel Vlasov 已提交
1544
{
1545 1546
    cv::__termination = true;  // DllMain is missing in static builds
    disposed = true;
1547
#ifndef CV_USE_FLS
P
Pavel Vlasov 已提交
1548
    TlsFree(tlsKey);
1549 1550 1551
#else // CV_USE_FLS
    FlsFree(tlsKey);
#endif // CV_USE_FLS
1552
    tlsKey = TLS_OUT_OF_INDEXES;
P
Pavel Vlasov 已提交
1553
}
1554
void* TlsAbstraction::getData() const
P
Pavel Vlasov 已提交
1555
{
1556 1557
    if (disposed)
        return NULL;
1558
#ifndef CV_USE_FLS
P
Pavel Vlasov 已提交
1559
    return TlsGetValue(tlsKey);
1560 1561 1562
#else // CV_USE_FLS
    return FlsGetValue(tlsKey);
#endif // CV_USE_FLS
P
Pavel Vlasov 已提交
1563
}
1564
void TlsAbstraction::setData(void *pData)
P
Pavel Vlasov 已提交
1565
{
1566 1567
    if (disposed)
        return;  // no-op
1568
#ifndef CV_USE_FLS
P
Pavel Vlasov 已提交
1569
    CV_Assert(TlsSetValue(tlsKey, pData) == TRUE);
1570 1571 1572
#else // CV_USE_FLS
    CV_Assert(FlsSetValue(tlsKey, pData) == TRUE);
#endif // CV_USE_FLS
P
Pavel Vlasov 已提交
1573
}
1574
#endif // WINRT
1575
#else // _WIN32
1576
static void opencv_tls_destructor(void* pData);
P
Pavel Vlasov 已提交
1577
TlsAbstraction::TlsAbstraction()
1578
    : disposed(false)
P
Pavel Vlasov 已提交
1579
{
1580
    CV_Assert(pthread_key_create(&tlsKey, opencv_tls_destructor) == 0);
P
Pavel Vlasov 已提交
1581
}
1582
void TlsAbstraction::releaseSystemResources()
P
Pavel Vlasov 已提交
1583
{
1584 1585
    cv::__termination = true;  // DllMain is missing in static builds
    disposed = true;
1586 1587 1588 1589 1590 1591
    if (pthread_key_delete(tlsKey) != 0)
    {
        // Don't use logging here
        fprintf(stderr, "OpenCV ERROR: TlsAbstraction::~TlsAbstraction(): pthread_key_delete() call failed\n");
        fflush(stderr);
    }
P
Pavel Vlasov 已提交
1592
}
1593
void* TlsAbstraction::getData() const
P
Pavel Vlasov 已提交
1594
{
1595 1596
    if (disposed)
        return NULL;
P
Pavel Vlasov 已提交
1597 1598
    return pthread_getspecific(tlsKey);
}
1599
void TlsAbstraction::setData(void *pData)
P
Pavel Vlasov 已提交
1600
{
1601 1602
    if (disposed)
        return;  // no-op
P
Pavel Vlasov 已提交
1603 1604 1605
    CV_Assert(pthread_setspecific(tlsKey, pData) == 0);
}
#endif
A
Alexander Alekhin 已提交
1606

P
Pavel Vlasov 已提交
1607 1608 1609 1610
// Per-thread data structure
struct ThreadData
{
    ThreadData()
A
Alexander Alekhin 已提交
1611
    {
P
Pavel Vlasov 已提交
1612 1613
        idx = 0;
        slots.reserve(32);
A
Alexander Alekhin 已提交
1614 1615
    }

P
Pavel Vlasov 已提交
1616 1617 1618
    std::vector<void*> slots; // Data array for a thread
    size_t idx;               // Thread index in TLS storage. This is not OS thread ID!
};
A
Alexander Alekhin 已提交
1619

1620 1621 1622

static bool g_isTlsStorageInitialized = false;

P
Pavel Vlasov 已提交
1623 1624 1625 1626
// Main TLS storage class
class TlsStorage
{
public:
1627 1628
    TlsStorage() :
        tlsSlotsSize(0)
A
Alexander Alekhin 已提交
1629
    {
1630
        (void)getTlsAbstraction();  // ensure singeton initialization (for correct order of atexit calls)
P
Pavel Vlasov 已提交
1631
        tlsSlots.reserve(32);
P
Pavel Vlasov 已提交
1632
        threads.reserve(32);
1633
        g_isTlsStorageInitialized = true;
A
Alexander Alekhin 已提交
1634
    }
P
Pavel Vlasov 已提交
1635
    ~TlsStorage()
A
Alexander Alekhin 已提交
1636
    {
1637 1638
        // TlsStorage object should not be released
        // There is no reliable way to avoid problems caused by static initialization order fiasco
1639 1640 1641
        // Don't use logging here
        fprintf(stderr, "OpenCV FATAL: TlsStorage::~TlsStorage() call is not expected\n");
        fflush(stderr);
A
Alexander Alekhin 已提交
1642 1643
    }

1644
    void releaseThread(void* tlsValue = NULL)
A
Alexander Alekhin 已提交
1645
    {
1646 1647
        TlsAbstraction* tls = getTlsAbstraction();
        if (NULL == tls)
B
Brian Wignall 已提交
1648
            return;  // TLS singleton is not available (terminated)
1649
        ThreadData *pTD = tlsValue == NULL ? (ThreadData*)tls->getData() : (ThreadData*)tlsValue;
1650 1651
        if (pTD == NULL)
            return;  // no OpenCV TLS data for this thread
P
Pavel Vlasov 已提交
1652
        AutoLock guard(mtxGlobalAccess);
1653
        for (size_t i = 0; i < threads.size(); i++)
1654
        {
1655
            if (pTD == threads[i])
P
Pavel Vlasov 已提交
1656
            {
1657 1658
                threads[i] = NULL;
                if (tlsValue == NULL)
1659
                    tls->setData(0);
1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670
                std::vector<void*>& thread_slots = pTD->slots;
                for (size_t slotIdx = 0; slotIdx < thread_slots.size(); slotIdx++)
                {
                    void* pData = thread_slots[slotIdx];
                    thread_slots[slotIdx] = NULL;
                    if (!pData)
                        continue;
                    TLSDataContainer* container = tlsSlots[slotIdx].container;
                    if (container)
                        container->deleteDataInstance(pData);
                    else
1671 1672 1673 1674
                    {
                        fprintf(stderr, "OpenCV ERROR: TLS: container for slotIdx=%d is NULL. Can't release thread data\n", (int)slotIdx);
                        fflush(stderr);
                    }
1675 1676 1677
                }
                delete pTD;
                return;
P
Pavel Vlasov 已提交
1678
            }
1679
        }
1680
        fprintf(stderr, "OpenCV WARNING: TLS: Can't release thread TLS data (unknown pointer or data race): %p\n", (void*)pTD); fflush(stderr);
A
Alexander Alekhin 已提交
1681 1682
    }

P
Pavel Vlasov 已提交
1683
    // Reserve TLS storage index
1684
    size_t reserveSlot(TLSDataContainer* container)
A
Alexander Alekhin 已提交
1685
    {
P
Pavel Vlasov 已提交
1686
        AutoLock guard(mtxGlobalAccess);
1687
        CV_Assert(tlsSlotsSize == tlsSlots.size());
P
Pavel Vlasov 已提交
1688 1689

        // Find unused slots
1690
        for(size_t slot = 0; slot < tlsSlotsSize; slot++)
P
Pavel Vlasov 已提交
1691
        {
1692
            if (tlsSlots[slot].container == NULL)
P
Pavel Vlasov 已提交
1693
            {
1694
                tlsSlots[slot].container = container;
P
Pavel Vlasov 已提交
1695 1696 1697 1698 1699
                return slot;
            }
        }

        // Create new slot
1700
        tlsSlots.push_back(TlsSlotInfo(container)); tlsSlotsSize++;
1701
        return tlsSlotsSize - 1;
A
Alexander Alekhin 已提交
1702 1703
    }

1704
    // Release TLS storage index and pass associated data to caller
1705
    void releaseSlot(size_t slotIdx, std::vector<void*> &dataVec, bool keepSlot = false)
A
Alexander Alekhin 已提交
1706
    {
P
Pavel Vlasov 已提交
1707
        AutoLock guard(mtxGlobalAccess);
1708 1709
        CV_Assert(tlsSlotsSize == tlsSlots.size());
        CV_Assert(tlsSlotsSize > slotIdx);
A
Alexander Alekhin 已提交
1710

P
Pavel Vlasov 已提交
1711
        for(size_t i = 0; i < threads.size(); i++)
A
Alexander Alekhin 已提交
1712
        {
1713
            if(threads[i])
P
Pavel Vlasov 已提交
1714
            {
1715 1716 1717 1718
                std::vector<void*>& thread_slots = threads[i]->slots;
                if (thread_slots.size() > slotIdx && thread_slots[slotIdx])
                {
                    dataVec.push_back(thread_slots[slotIdx]);
1719
                    thread_slots[slotIdx] = NULL;
1720
                }
P
Pavel Vlasov 已提交
1721
            }
A
Alexander Alekhin 已提交
1722
        }
P
Pavel Vlasov 已提交
1723

1724
        if (!keepSlot)
1725 1726 1727
        {
            tlsSlots[slotIdx].container = NULL;  // mark slot as free (see reserveSlot() implementation)
        }
A
Alexander Alekhin 已提交
1728 1729
    }

P
Pavel Vlasov 已提交
1730 1731
    // Get data by TLS storage index
    void* getData(size_t slotIdx) const
A
Alexander Alekhin 已提交
1732
    {
1733
#ifndef CV_THREAD_SANITIZER
1734
        CV_Assert(tlsSlotsSize > slotIdx);
1735
#endif
A
Alexander Alekhin 已提交
1736

1737 1738
        TlsAbstraction* tls = getTlsAbstraction();
        if (NULL == tls)
B
Brian Wignall 已提交
1739
            return NULL;  // TLS singleton is not available (terminated)
1740 1741

        ThreadData* threadData = (ThreadData*)tls->getData();
P
Pavel Vlasov 已提交
1742 1743 1744 1745
        if(threadData && threadData->slots.size() > slotIdx)
            return threadData->slots[slotIdx];

        return NULL;
A
Alexander Alekhin 已提交
1746 1747
    }

P
Pavel Vlasov 已提交
1748 1749 1750 1751
    // Gather data from threads by TLS storage index
    void gather(size_t slotIdx, std::vector<void*> &dataVec)
    {
        AutoLock guard(mtxGlobalAccess);
1752 1753
        CV_Assert(tlsSlotsSize == tlsSlots.size());
        CV_Assert(tlsSlotsSize > slotIdx);
P
Pavel Vlasov 已提交
1754 1755 1756

        for(size_t i = 0; i < threads.size(); i++)
        {
1757 1758 1759 1760 1761 1762
            if(threads[i])
            {
                std::vector<void*>& thread_slots = threads[i]->slots;
                if (thread_slots.size() > slotIdx && thread_slots[slotIdx])
                    dataVec.push_back(thread_slots[slotIdx]);
            }
P
Pavel Vlasov 已提交
1763 1764 1765
        }
    }

P
Pavel Vlasov 已提交
1766 1767
    // Set data to storage index
    void setData(size_t slotIdx, void* pData)
A
Alexander Alekhin 已提交
1768
    {
1769
#ifndef CV_THREAD_SANITIZER
1770
        CV_Assert(tlsSlotsSize > slotIdx);
1771
#endif
P
Pavel Vlasov 已提交
1772

1773 1774
        TlsAbstraction* tls = getTlsAbstraction();
        if (NULL == tls)
B
Brian Wignall 已提交
1775
            return;  // TLS singleton is not available (terminated)
1776 1777

        ThreadData* threadData = (ThreadData*)tls->getData();
P
Pavel Vlasov 已提交
1778
        if(!threadData)
A
Alexander Alekhin 已提交
1779
        {
P
Pavel Vlasov 已提交
1780
            threadData = new ThreadData;
1781
            tls->setData((void*)threadData);
P
Pavel Vlasov 已提交
1782 1783
            {
                AutoLock guard(mtxGlobalAccess);
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803

                bool found = false;
                // Find unused slots
                for(size_t slot = 0; slot < threads.size(); slot++)
                {
                    if (threads[slot] == NULL)
                    {
                        threadData->idx = (int)slot;
                        threads[slot] = threadData;
                        found = true;
                        break;
                    }
                }

                if (!found)
                {
                    // Create new slot
                    threadData->idx = threads.size();
                    threads.push_back(threadData);
                }
P
Pavel Vlasov 已提交
1804
            }
A
Alexander Alekhin 已提交
1805
        }
P
Pavel Vlasov 已提交
1806 1807

        if(slotIdx >= threadData->slots.size())
P
Pavel Vlasov 已提交
1808
        {
1809 1810
            AutoLock guard(mtxGlobalAccess); // keep synchronization with gather() calls
            threadData->slots.resize(slotIdx + 1, NULL);
P
Pavel Vlasov 已提交
1811
        }
P
Pavel Vlasov 已提交
1812
        threadData->slots[slotIdx] = pData;
A
Alexander Alekhin 已提交
1813
    }
P
Pavel Vlasov 已提交
1814 1815 1816

private:
    Mutex  mtxGlobalAccess;           // Shared objects operation guard
1817
    size_t tlsSlotsSize;              // equal to tlsSlots.size() in synchronized sections
1818 1819 1820 1821 1822 1823 1824 1825
                                      // without synchronization this counter doesn't decrease - it is used for slotIdx sanity checks

    struct TlsSlotInfo
    {
        TlsSlotInfo(TLSDataContainer* _container) : container(_container) {}
        TLSDataContainer* container;  // attached container (to dispose data of terminated threads)
    };
    std::vector<struct TlsSlotInfo> tlsSlots;  // TLS keys state
P
Pavel Vlasov 已提交
1826
    std::vector<ThreadData*> threads; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup
A
Alexander Alekhin 已提交
1827
};
1828

P
Pavel Vlasov 已提交
1829 1830
// Create global TLS storage object
static TlsStorage &getTlsStorage()
1831
{
P
Pavel Vlasov 已提交
1832
    CV_SINGLETON_LAZY_INIT_REF(TlsStorage, new TlsStorage())
1833
}
A
Alexander Alekhin 已提交
1834

1835 1836 1837
#ifndef _WIN32  // pthread key destructor
static void opencv_tls_destructor(void* pData)
{
1838 1839
    if (!g_isTlsStorageInitialized)
        return;  // nothing to release, so prefer to avoid creation of new global structures
1840 1841
    getTlsStorage().releaseThread(pData);
}
1842 1843 1844 1845
#else // _WIN32
#ifdef CV_USE_FLS
static void WINAPI opencv_fls_destructor(void* pData)
{
1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862
    // Empiric detection of ExitProcess call
    DWORD code = STILL_ACTIVE/*259*/;
    BOOL res = GetExitCodeProcess(GetCurrentProcess(), &code);
    if (res && code != STILL_ACTIVE)
    {
        // Looks like we are in ExitProcess() call
        // This is FLS specific only because their callback is called before DllMain.
        // TLS doesn't have similar problem, DllMain() is called first which mark __termination properly.
        // Note: this workaround conflicts with ExitProcess() steps order described in documentation, however it works:
        // 3. ... called with DLL_PROCESS_DETACH
        // 7. The termination status of the process changes from STILL_ACTIVE to the exit value of the process.
        // (ref: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-exitprocess)
        cv::__termination = true;
    }

    if (!g_isTlsStorageInitialized)
        return;  // nothing to release, so prefer to avoid creation of new global structures
1863 1864 1865 1866
    getTlsStorage().releaseThread(pData);
}
#endif // CV_USE_FLS
#endif // _WIN32
1867

1868
static TlsStorage* const g_force_initialization_of_TlsStorage
1869 1870 1871
#if defined __GNUC__
    __attribute__((unused))
#endif
1872
    = &getTlsStorage();
1873

1874 1875 1876
} // namespace details
using namespace details;

1877 1878 1879 1880 1881 1882 1883
void releaseTlsStorageThread()
{
    if (!g_isTlsStorageInitialized)
        return;  // nothing to release, so prefer to avoid creation of new global structures
    getTlsStorage().releaseThread();
}

A
Alexander Alekhin 已提交
1884 1885
TLSDataContainer::TLSDataContainer()
{
1886
    key_ = (int)getTlsStorage().reserveSlot(this); // Reserve key from TLS storage
1887 1888
}

A
Alexander Alekhin 已提交
1889 1890
TLSDataContainer::~TLSDataContainer()
{
P
Pavel Vlasov 已提交
1891
    CV_Assert(key_ == -1); // Key must be released in child object
A
Alexander Alekhin 已提交
1892 1893
}

P
Pavel Vlasov 已提交
1894 1895 1896 1897 1898
void TLSDataContainer::gatherData(std::vector<void*> &data) const
{
    getTlsStorage().gather(key_, data);
}

1899 1900 1901 1902 1903
void TLSDataContainer::detachData(std::vector<void*> &data)
{
    getTlsStorage().releaseSlot(key_, data, true);
}

P
Pavel Vlasov 已提交
1904
void TLSDataContainer::release()
A
Alexander Alekhin 已提交
1905
{
1906 1907 1908 1909
    if (key_ == -1)
        return;  // already released
    std::vector<void*> data; data.reserve(32);
    getTlsStorage().releaseSlot(key_, data, false); // Release key and get stored data for proper destruction
1910 1911 1912 1913 1914 1915 1916
    key_ = -1;
    for(size_t i = 0; i < data.size(); i++)  // Delete all associated data
        deleteDataInstance(data[i]);
}

void TLSDataContainer::cleanup()
{
1917
    std::vector<void*> data; data.reserve(32);
1918
    getTlsStorage().releaseSlot(key_, data, true); // Extract stored data with removal from TLS tables
1919
    for(size_t i = 0; i < data.size(); i++)  // Delete all associated data
P
Pavel Vlasov 已提交
1920
        deleteDataInstance(data[i]);
A
Alexander Alekhin 已提交
1921 1922
}

P
Pavel Vlasov 已提交
1923
void* TLSDataContainer::getData() const
A
Alexander Alekhin 已提交
1924
{
1925
    CV_Assert(key_ != -1 && "Can't fetch data from terminated TLS container.");
P
Pavel Vlasov 已提交
1926 1927
    void* pData = getTlsStorage().getData(key_); // Check if data was already allocated
    if(!pData)
A
Alexander Alekhin 已提交
1928
    {
P
Pavel Vlasov 已提交
1929 1930 1931
        // Create new data instance and save it to TLS storage
        pData = createDataInstance();
        getTlsStorage().setData(key_, pData);
A
Alexander Alekhin 已提交
1932
    }
P
Pavel Vlasov 已提交
1933
    return pData;
A
Alexander Alekhin 已提交
1934 1935
}

1936
static TLSData<CoreTLSData>& getCoreTlsDataTLS()
1937
{
1938
    CV_SINGLETON_LAZY_INIT_REF(TLSData<CoreTLSData>, new TLSData<CoreTLSData>())
1939 1940
}

1941 1942 1943 1944 1945
CoreTLSData& getCoreTlsData()
{
    return getCoreTlsDataTLS().getRef();
}

1946
#if defined CVAPI_EXPORTS && defined _WIN32 && !defined WINCE
P
Pavel Vlasov 已提交
1947 1948 1949 1950
#ifdef WINRT
    #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
#endif

1951 1952 1953
extern "C"
BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved);

P
Pavel Vlasov 已提交
1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966
extern "C"
BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID lpReserved)
{
    if (fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH)
    {
        if (lpReserved != NULL) // called after ExitProcess() call
        {
            cv::__termination = true;
        }
        else
        {
            // Not allowed to free resources if lpReserved is non-null
            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583.aspx
1967
            releaseTlsStorageThread();
P
Pavel Vlasov 已提交
1968 1969 1970 1971 1972
        }
    }
    return TRUE;
}
#endif
1973

1974 1975

namespace {
1976 1977 1978 1979 1980 1981 1982 1983 1984

#ifdef OPENCV_WITH_ITT
bool overrideThreadName()
{
    static bool param = utils::getConfigurationParameterBool("OPENCV_TRACE_ITT_SET_THREAD_NAME", false);
    return param;
}
#endif

1985 1986 1987 1988 1989 1990 1991 1992
static int g_threadNum = 0;
class ThreadID {
public:
    const int id;
    ThreadID() :
        id(CV_XADD(&g_threadNum, 1))
    {
#ifdef OPENCV_WITH_ITT
1993 1994
        if (overrideThreadName())
            __itt_thread_set_name(cv::format("OpenCVThread-%03d", id).c_str());
1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
#endif
    }
};

static TLSData<ThreadID>& getThreadIDTLS()
{
    CV_SINGLETON_LAZY_INIT_REF(TLSData<ThreadID>, new TLSData<ThreadID>());
}

} // namespace
int utils::getThreadID() { return getThreadIDTLS().get()->id; }

2007 2008

class ParseError
2009
{
2010 2011
    std::string bad_value;
public:
2012
    ParseError(const std::string &bad_value_) :bad_value(bad_value_) {}
2013
    std::string toString(const std::string &param) const
2014
    {
2015 2016 2017
        std::ostringstream out;
        out << "Invalid value for parameter " << param << ": " << bad_value;
        return out.str();
2018
    }
2019 2020 2021 2022 2023 2024 2025 2026
};

template <typename T>
T parseOption(const std::string &);

template<>
inline bool parseOption(const std::string & value)
{
2027 2028 2029 2030 2031 2032 2033 2034
    if (value == "1" || value == "True" || value == "true" || value == "TRUE")
    {
        return true;
    }
    if (value == "0" || value == "False" || value == "false" || value == "FALSE")
    {
        return false;
    }
2035
    throw ParseError(value);
2036 2037
}

2038 2039
template<>
inline size_t parseOption(const std::string &value)
2040 2041 2042 2043 2044 2045 2046 2047 2048
{
    size_t pos = 0;
    for (; pos < value.size(); pos++)
    {
        if (!isdigit(value[pos]))
            break;
    }
    cv::String valueStr = value.substr(0, pos);
    cv::String suffixStr = value.substr(pos, value.length() - pos);
2049 2050 2051 2052 2053
#ifdef CV_CXX11
    size_t v = (size_t)std::stoull(valueStr);
#else
    size_t v = (size_t)atol(valueStr.c_str());
#endif
2054 2055 2056 2057 2058 2059
    if (suffixStr.length() == 0)
        return v;
    else if (suffixStr == "MB" || suffixStr == "Mb" || suffixStr == "mb")
        return v * 1024 * 1024;
    else if (suffixStr == "KB" || suffixStr == "Kb" || suffixStr == "kb")
        return v * 1024;
2060
    throw ParseError(value);
2061 2062
}

2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090
template<>
inline cv::String parseOption(const std::string &value)
{
    return value;
}

template<>
inline utils::Paths parseOption(const std::string &value)
{
    utils::Paths result;
#ifdef _WIN32
    const char sep = ';';
#else
    const char sep = ':';
#endif
    size_t start_pos = 0;
    while (start_pos != std::string::npos)
    {
        const size_t pos = value.find(sep, start_pos);
        const std::string one_piece(value, start_pos, pos == std::string::npos ? pos : pos - start_pos);
        if (!one_piece.empty())
            result.push_back(one_piece);
        start_pos = pos == std::string::npos ? pos : pos + 1;
    }
    return result;
}

static inline const char * envRead(const char * name)
2091 2092
{
#ifdef NO_GETENV
2093 2094
    CV_UNUSED(name);
    return NULL;
2095
#else
2096
    return getenv(name);
2097
#endif
2098 2099 2100 2101 2102 2103
}

template<typename T>
inline T read(const std::string & k, const T & defaultValue)
{
    try
2104
    {
2105 2106 2107
        const char * res = envRead(k.c_str());
        if (res)
            return parseOption<T>(std::string(res));
2108
    }
2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133
    catch (const ParseError &err)
    {
        CV_Error(cv::Error::StsBadArg, err.toString(k));
    }
    return defaultValue;
}

bool utils::getConfigurationParameterBool(const char* name, bool defaultValue)
{
    return read<bool>(name, defaultValue);
}

size_t utils::getConfigurationParameterSizeT(const char* name, size_t defaultValue)
{
    return read<size_t>(name, defaultValue);
}

cv::String utils::getConfigurationParameterString(const char* name, const char* defaultValue)
{
    return read<cv::String>(name, defaultValue);
}

utils::Paths utils::getConfigurationParameterPaths(const char* name, const utils::Paths &defaultValue)
{
    return read<utils::Paths>(name, defaultValue);
2134 2135 2136
}


2137
#ifdef CV_COLLECT_IMPL_DATA
P
Pavel Vlasov 已提交
2138 2139
ImplCollector& getImplData()
{
2140
    CV_SINGLETON_LAZY_INIT_REF(ImplCollector, new ImplCollector())
P
Pavel Vlasov 已提交
2141 2142
}

2143 2144
void setImpl(int flags)
{
P
Pavel Vlasov 已提交
2145 2146 2147 2148 2149
    cv::AutoLock lock(getImplData().mutex);

    getImplData().implFlags = flags;
    getImplData().implCode.clear();
    getImplData().implFun.clear();
2150 2151 2152 2153
}

void addImpl(int flag, const char* func)
{
P
Pavel Vlasov 已提交
2154 2155 2156
    cv::AutoLock lock(getImplData().mutex);

    getImplData().implFlags |= flag;
2157 2158
    if(func) // use lazy collection if name was not specified
    {
P
Pavel Vlasov 已提交
2159 2160
        size_t index = getImplData().implCode.size();
        if(!index || (getImplData().implCode[index-1] != flag || getImplData().implFun[index-1].compare(func))) // avoid duplicates
2161
        {
P
Pavel Vlasov 已提交
2162 2163
            getImplData().implCode.push_back(flag);
            getImplData().implFun.push_back(func);
2164 2165 2166 2167 2168 2169
        }
    }
}

int getImpl(std::vector<int> &impl, std::vector<String> &funName)
{
P
Pavel Vlasov 已提交
2170 2171 2172 2173 2174
    cv::AutoLock lock(getImplData().mutex);

    impl    = getImplData().implCode;
    funName = getImplData().implFun;
    return getImplData().implFlags; // return actual flags for lazy collection
2175 2176 2177 2178
}

bool useCollection()
{
P
Pavel Vlasov 已提交
2179
    return getImplData().useCollection;
2180 2181 2182 2183
}

void setUseCollection(bool flag)
{
P
Pavel Vlasov 已提交
2184 2185 2186
    cv::AutoLock lock(getImplData().mutex);

    getImplData().useCollection = flag;
2187 2188 2189
}
#endif

2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226
namespace instr
{
bool useInstrumentation()
{
#ifdef ENABLE_INSTRUMENTATION
    return getInstrumentStruct().useInstr;
#else
    return false;
#endif
}

void setUseInstrumentation(bool flag)
{
#ifdef ENABLE_INSTRUMENTATION
    getInstrumentStruct().useInstr = flag;
#else
    CV_UNUSED(flag);
#endif
}

InstrNode* getTrace()
{
#ifdef ENABLE_INSTRUMENTATION
    return &getInstrumentStruct().rootNode;
#else
    return NULL;
#endif
}

void resetTrace()
{
#ifdef ENABLE_INSTRUMENTATION
    getInstrumentStruct().rootNode.removeChilds();
    getInstrumentTLSStruct().pCurrentNode = &getInstrumentStruct().rootNode;
#endif
}

2227
void setFlags(FLAGS modeFlags)
2228 2229
{
#ifdef ENABLE_INSTRUMENTATION
2230
    getInstrumentStruct().flags = modeFlags;
2231 2232 2233 2234
#else
    CV_UNUSED(modeFlags);
#endif
}
2235
FLAGS getFlags()
2236 2237
{
#ifdef ENABLE_INSTRUMENTATION
2238
    return (FLAGS)getInstrumentStruct().flags;
2239
#else
2240
    return (FLAGS)0;
2241 2242 2243
#endif
}

2244
NodeData::NodeData(const char* funName, const char* fileName, int lineNum, void* retAddress, bool alwaysExpand, cv::instr::TYPE instrType, cv::instr::IMPL implType)
2245
{
2246
    m_funName       = funName ? cv::String(funName) : cv::String();  // std::string doesn't accept NULL
2247 2248 2249 2250 2251 2252
    m_instrType     = instrType;
    m_implType      = implType;
    m_fileName      = fileName;
    m_lineNum       = lineNum;
    m_retAddress    = retAddress;
    m_alwaysExpand  = alwaysExpand;
2253

2254 2255
    m_threads    = 1;
    m_counter    = 0;
2256 2257
    m_ticksTotal = 0;

2258
    m_funError  = false;
2259 2260 2261 2262 2263 2264 2265
}
NodeData::NodeData(NodeData &ref)
{
    *this = ref;
}
NodeData& NodeData::operator=(const NodeData &right)
{
2266 2267 2268 2269 2270 2271 2272 2273 2274
    this->m_funName      = right.m_funName;
    this->m_instrType    = right.m_instrType;
    this->m_implType     = right.m_implType;
    this->m_fileName     = right.m_fileName;
    this->m_lineNum      = right.m_lineNum;
    this->m_retAddress   = right.m_retAddress;
    this->m_alwaysExpand = right.m_alwaysExpand;

    this->m_threads     = right.m_threads;
2275 2276
    this->m_counter     = right.m_counter;
    this->m_ticksTotal  = right.m_ticksTotal;
2277

2278
    this->m_funError    = right.m_funError;
2279

2280 2281 2282 2283 2284 2285 2286 2287
    return *this;
}
NodeData::~NodeData()
{
}
bool operator==(const NodeData& left, const NodeData& right)
{
    if(left.m_lineNum == right.m_lineNum && left.m_funName == right.m_funName && left.m_fileName == right.m_fileName)
2288 2289 2290 2291
    {
        if(left.m_retAddress == right.m_retAddress || !(cv::instr::getFlags()&cv::instr::FLAGS_EXPAND_SAME_NAMES || left.m_alwaysExpand))
            return true;
    }
2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311
    return false;
}

#ifdef ENABLE_INSTRUMENTATION
InstrStruct& getInstrumentStruct()
{
    static InstrStruct instr;
    return instr;
}

InstrTLSStruct& getInstrumentTLSStruct()
{
    return *getInstrumentStruct().tlsStruct.get();
}

InstrNode* getCurrentNode()
{
    return getInstrumentTLSStruct().pCurrentNode;
}

2312
IntrumentationRegion::IntrumentationRegion(const char* funName, const char* fileName, int lineNum, void *retAddress, bool alwaysExpand, TYPE instrType, IMPL implType)
2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328
{
    m_disabled    = false;
    m_regionTicks = 0;

    InstrStruct *pStruct = &getInstrumentStruct();
    if(pStruct->useInstr)
    {
        InstrTLSStruct *pTLS = &getInstrumentTLSStruct();

        // Disable in case of failure
        if(!pTLS->pCurrentNode)
        {
            m_disabled = true;
            return;
        }

2329 2330 2331 2332
        int depth = pTLS->pCurrentNode->getDepth();
        if(pStruct->maxDepth && pStruct->maxDepth <= depth)
        {
            m_disabled = true;
2333
            return;
2334
        }
2335

2336
        NodeData payload(funName, fileName, lineNum, retAddress, alwaysExpand, instrType, implType);
2337 2338
        Node<NodeData>* pChild = NULL;

2339
        if(pStruct->flags&FLAGS_MAPPING)
2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354
        {
            // Critical section
            cv::AutoLock guard(pStruct->mutexCreate); // Guard from concurrent child creation
            pChild = pTLS->pCurrentNode->findChild(payload);
            if(!pChild)
            {
                pChild = new Node<NodeData>(payload);
                pTLS->pCurrentNode->addChild(pChild);
            }
        }
        else
        {
            pChild = pTLS->pCurrentNode->findChild(payload);
            if(!pChild)
            {
2355
                m_disabled = true;
2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372
                return;
            }
        }
        pTLS->pCurrentNode = pChild;

        m_regionTicks = getTickCount();
    }
}

IntrumentationRegion::~IntrumentationRegion()
{
    InstrStruct *pStruct = &getInstrumentStruct();
    if(pStruct->useInstr)
    {
        if(!m_disabled)
        {
            InstrTLSStruct *pTLS = &getInstrumentTLSStruct();
2373 2374 2375 2376

            if (pTLS->pCurrentNode->m_payload.m_implType == cv::instr::IMPL_OPENCL &&
                (pTLS->pCurrentNode->m_payload.m_instrType == cv::instr::TYPE_FUN ||
                    pTLS->pCurrentNode->m_payload.m_instrType == cv::instr::TYPE_WRAPPER))
2377
            {
2378
                cv::ocl::finish(); // TODO Support "async" OpenCL instrumentation
2379 2380
            }

2381 2382 2383 2384 2385 2386
            uint64 ticks = (getTickCount() - m_regionTicks);
            {
                cv::AutoLock guard(pStruct->mutexCount); // Concurrent ticks accumulation
                pTLS->pCurrentNode->m_payload.m_counter++;
                pTLS->pCurrentNode->m_payload.m_ticksTotal += ticks;
                pTLS->pCurrentNode->m_payload.m_tls.get()->m_ticksTotal += ticks;
2387
            }
2388 2389

            pTLS->pCurrentNode = pTLS->pCurrentNode->m_pParent;
2390 2391 2392 2393 2394 2395
        }
    }
}
#endif
}

I
Ilya Lavrenov 已提交
2396 2397 2398
namespace ipp
{

2399
#ifdef HAVE_IPP
P
Pavel Vlasov 已提交
2400
struct IPPInitSingleton
2401 2402
{
public:
P
Pavel Vlasov 已提交
2403
    IPPInitSingleton()
2404
    {
P
Pavel Vlasov 已提交
2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423
        useIPP         = true;
        useIPP_NE      = false;
        ippStatus      = 0;
        funcname       = NULL;
        filename       = NULL;
        linen          = 0;
        cpuFeatures    = 0;
        ippFeatures    = 0;
        ippTopFeatures = 0;
        pIppLibInfo    = NULL;

        ippStatus = ippGetCpuFeatures(&cpuFeatures, NULL);
        if(ippStatus < 0)
        {
            std::cerr << "ERROR: IPP cannot detect CPU features, IPP was disabled " << std::endl;
            useIPP = false;
            return;
        }
        ippFeatures = cpuFeatures;
2424 2425 2426 2427 2428

        const char* pIppEnv = getenv("OPENCV_IPP");
        cv::String env = pIppEnv;
        if(env.size())
        {
M
maver1 已提交
2429 2430 2431 2432 2433 2434
#if IPP_VERSION_X100 >= 201900
            const Ipp64u minorFeatures = ippCPUID_MOVBE|ippCPUID_AES|ippCPUID_CLMUL|ippCPUID_ABR|ippCPUID_RDRAND|ippCPUID_F16C|
                ippCPUID_ADCOX|ippCPUID_RDSEED|ippCPUID_PREFETCHW|ippCPUID_SHA|ippCPUID_MPX|ippCPUID_AVX512CD|ippCPUID_AVX512ER|
                ippCPUID_AVX512PF|ippCPUID_AVX512BW|ippCPUID_AVX512DQ|ippCPUID_AVX512VL|ippCPUID_AVX512VBMI|ippCPUID_AVX512_4FMADDPS|
                ippCPUID_AVX512_4VNNIW|ippCPUID_AVX512IFMA;
#elif IPP_VERSION_X100 >= 201703
2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445
            const Ipp64u minorFeatures = ippCPUID_MOVBE|ippCPUID_AES|ippCPUID_CLMUL|ippCPUID_ABR|ippCPUID_RDRAND|ippCPUID_F16C|
                ippCPUID_ADCOX|ippCPUID_RDSEED|ippCPUID_PREFETCHW|ippCPUID_SHA|ippCPUID_MPX|ippCPUID_AVX512CD|ippCPUID_AVX512ER|
                ippCPUID_AVX512PF|ippCPUID_AVX512BW|ippCPUID_AVX512DQ|ippCPUID_AVX512VL|ippCPUID_AVX512VBMI;
#elif IPP_VERSION_X100 >= 201700
            const Ipp64u minorFeatures = ippCPUID_MOVBE|ippCPUID_AES|ippCPUID_CLMUL|ippCPUID_ABR|ippCPUID_RDRAND|ippCPUID_F16C|
                ippCPUID_ADCOX|ippCPUID_RDSEED|ippCPUID_PREFETCHW|ippCPUID_SHA|ippCPUID_AVX512CD|ippCPUID_AVX512ER|
                ippCPUID_AVX512PF|ippCPUID_AVX512BW|ippCPUID_AVX512DQ|ippCPUID_AVX512VL|ippCPUID_AVX512VBMI;
#else
            const Ipp64u minorFeatures = 0;
#endif

P
Pavel Vlasov 已提交
2446 2447 2448 2449 2450 2451 2452
            env = env.toLowerCase();
            if(env.substr(0, 2) == "ne")
            {
                useIPP_NE = true;
                env = env.substr(3, env.size());
            }

2453 2454 2455 2456 2457 2458
            if(env == "disabled")
            {
                std::cerr << "WARNING: IPP was disabled by OPENCV_IPP environment variable" << std::endl;
                useIPP = false;
            }
            else if(env == "sse42")
2459
                ippFeatures = minorFeatures|ippCPUID_SSE2|ippCPUID_SSE3|ippCPUID_SSSE3|ippCPUID_SSE41|ippCPUID_SSE42;
2460
            else if(env == "avx2")
2461 2462
                ippFeatures = minorFeatures|ippCPUID_SSE2|ippCPUID_SSE3|ippCPUID_SSSE3|ippCPUID_SSE41|ippCPUID_SSE42|ippCPUID_AVX|ippCPUID_AVX2;
#if IPP_VERSION_X100 >= 201700
P
Pavel Vlasov 已提交
2463 2464
#if defined (_M_AMD64) || defined (__x86_64__)
            else if(env == "avx512")
2465 2466
                ippFeatures = minorFeatures|ippCPUID_SSE2|ippCPUID_SSE3|ippCPUID_SSSE3|ippCPUID_SSE41|ippCPUID_SSE42|ippCPUID_AVX|ippCPUID_AVX2|ippCPUID_AVX512F;
#endif
2467 2468
#endif
            else
P
Pavel Vlasov 已提交
2469 2470
                std::cerr << "ERROR: Improper value of OPENCV_IPP: " << env.c_str() << ". Correct values are: disabled, sse42, avx2, avx512 (Intel64 only)" << std::endl;

2471 2472
            // Trim unsupported features
            ippFeatures &= cpuFeatures;
P
Pavel Vlasov 已提交
2473 2474 2475 2476
        }

        // Disable AVX1 since we don't track regressions for it. SSE42 will be used instead
        if(cpuFeatures&ippCPUID_AVX && !(cpuFeatures&ippCPUID_AVX2))
2477
            ippFeatures &= ~((Ipp64u)ippCPUID_AVX);
P
Pavel Vlasov 已提交
2478 2479 2480

        // IPP integrations in OpenCV support only SSE4.2, AVX2 and AVX-512 optimizations.
        if(!(
2481
#if IPP_VERSION_X100 >= 201700
P
Pavel Vlasov 已提交
2482
            cpuFeatures&ippCPUID_AVX512F ||
2483
#endif
P
Pavel Vlasov 已提交
2484 2485 2486 2487 2488 2489
            cpuFeatures&ippCPUID_AVX2 ||
            cpuFeatures&ippCPUID_SSE42
            ))
        {
            useIPP = false;
            return;
2490 2491
        }

2492 2493 2494 2495
        if(ippFeatures == cpuFeatures)
            IPP_INITIALIZER(0)
        else
            IPP_INITIALIZER(ippFeatures)
2496
        ippFeatures = ippGetEnabledCpuFeatures();
P
Pavel Vlasov 已提交
2497 2498

        // Detect top level optimizations to make comparison easier for optimizations dependent conditions
2499
#if IPP_VERSION_X100 >= 201700
P
Pavel Vlasov 已提交
2500 2501 2502 2503 2504 2505 2506 2507 2508
        if(ippFeatures&ippCPUID_AVX512F)
        {
            if((ippFeatures&ippCPUID_AVX512_SKX) == ippCPUID_AVX512_SKX)
                ippTopFeatures = ippCPUID_AVX512_SKX;
            else if((ippFeatures&ippCPUID_AVX512_KNL) == ippCPUID_AVX512_KNL)
                ippTopFeatures = ippCPUID_AVX512_KNL;
            else
                ippTopFeatures = ippCPUID_AVX512F; // Unknown AVX512 configuration
        }
2509 2510 2511
        else
#endif
        if(ippFeatures&ippCPUID_AVX2)
P
Pavel Vlasov 已提交
2512 2513 2514 2515 2516
            ippTopFeatures = ippCPUID_AVX2;
        else if(ippFeatures&ippCPUID_SSE42)
            ippTopFeatures = ippCPUID_SSE42;

        pIppLibInfo = ippiGetLibVersion();
2517 2518 2519 2520 2521 2522 2523

        // workaround: https://github.com/opencv/opencv/issues/12959
        std::string ippName(pIppLibInfo->Name ? pIppLibInfo->Name : "");
        if (ippName.find("SSE4.2") != std::string::npos)
        {
            ippTopFeatures = ippCPUID_SSE42;
        }
2524 2525
    }

P
Pavel Vlasov 已提交
2526 2527 2528
public:
    bool        useIPP;
    bool        useIPP_NE;
2529

P
Pavel Vlasov 已提交
2530
    int         ippStatus;  // 0 - all is ok, -1 - IPP functions failed
2531 2532 2533
    const char *funcname;
    const char *filename;
    int         linen;
2534
    Ipp64u      ippFeatures;
P
Pavel Vlasov 已提交
2535 2536 2537
    Ipp64u      cpuFeatures;
    Ipp64u      ippTopFeatures;
    const IppLibraryVersion *pIppLibInfo;
2538 2539
};

P
Pavel Vlasov 已提交
2540
static IPPInitSingleton& getIPPSingleton()
2541
{
P
Pavel Vlasov 已提交
2542
    CV_SINGLETON_LAZY_INIT_REF(IPPInitSingleton, new IPPInitSingleton())
2543
}
2544
#endif
2545

2546 2547 2548
#if OPENCV_ABI_COMPATIBILITY > 300
unsigned long long getIppFeatures()
#else
2549
int getIppFeatures()
2550
#endif
2551 2552
{
#ifdef HAVE_IPP
2553
#if OPENCV_ABI_COMPATIBILITY > 300
P
Pavel Vlasov 已提交
2554
    return getIPPSingleton().ippFeatures;
2555 2556 2557
#else
    return (int)getIPPSingleton().ippFeatures;
#endif
2558 2559 2560 2561
#else
    return 0;
#endif
}
I
Ilya Lavrenov 已提交
2562

2563
#ifdef HAVE_IPP
P
Pavel Vlasov 已提交
2564 2565 2566 2567
unsigned long long getIppTopFeatures()
{
    return getIPPSingleton().ippTopFeatures;
}
2568
#endif
P
Pavel Vlasov 已提交
2569

I
Ilya Lavrenov 已提交
2570
void setIppStatus(int status, const char * const _funcname, const char * const _filename, int _line)
I
Ilya Lavrenov 已提交
2571
{
2572
#ifdef HAVE_IPP
P
Pavel Vlasov 已提交
2573 2574 2575 2576
    getIPPSingleton().ippStatus = status;
    getIPPSingleton().funcname = _funcname;
    getIPPSingleton().filename = _filename;
    getIPPSingleton().linen = _line;
2577 2578 2579
#else
    CV_UNUSED(status); CV_UNUSED(_funcname); CV_UNUSED(_filename); CV_UNUSED(_line);
#endif
I
Ilya Lavrenov 已提交
2580 2581 2582 2583
}

int getIppStatus()
{
2584
#ifdef HAVE_IPP
P
Pavel Vlasov 已提交
2585
    return getIPPSingleton().ippStatus;
2586 2587 2588
#else
    return 0;
#endif
I
Ilya Lavrenov 已提交
2589 2590 2591 2592
}

String getIppErrorLocation()
{
2593
#ifdef HAVE_IPP
P
Pavel Vlasov 已提交
2594
    return format("%s:%d %s", getIPPSingleton().filename ? getIPPSingleton().filename : "", getIPPSingleton().linen, getIPPSingleton().funcname ? getIPPSingleton().funcname : "");
2595 2596 2597
#else
    return String();
#endif
I
Ilya Lavrenov 已提交
2598 2599
}

P
Pavel Vlasov 已提交
2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612
String getIppVersion()
{
#ifdef HAVE_IPP
    const IppLibraryVersion *pInfo = getIPPSingleton().pIppLibInfo;
    if(pInfo)
        return format("%s %s %s", pInfo->Name, pInfo->Version, pInfo->BuildDate);
    else
        return String("error");
#else
    return String("disabled");
#endif
}

2613 2614 2615
bool useIPP()
{
#ifdef HAVE_IPP
2616 2617
    CoreTLSData& data = getCoreTlsData();
    if (data.useIPP < 0)
2618
    {
2619
        data.useIPP = getIPPSingleton().useIPP;
2620
    }
2621
    return (data.useIPP > 0);
2622 2623 2624 2625 2626 2627 2628
#else
    return false;
#endif
}

void setUseIPP(bool flag)
{
2629
    CoreTLSData& data = getCoreTlsData();
2630
#ifdef HAVE_IPP
2631
    data.useIPP = (getIPPSingleton().useIPP)?flag:false;
2632
#else
H
Hamdi Sahloul 已提交
2633
    CV_UNUSED(flag);
2634
    data.useIPP = false;
2635 2636 2637
#endif
}

M
maver1 已提交
2638
bool useIPP_NotExact()
P
Pavel Vlasov 已提交
2639 2640
{
#ifdef HAVE_IPP
2641 2642
    CoreTLSData& data = getCoreTlsData();
    if (data.useIPP_NE < 0)
P
Pavel Vlasov 已提交
2643
    {
2644
        data.useIPP_NE = getIPPSingleton().useIPP_NE;
P
Pavel Vlasov 已提交
2645
    }
2646
    return (data.useIPP_NE > 0);
P
Pavel Vlasov 已提交
2647 2648 2649 2650 2651
#else
    return false;
#endif
}

M
maver1 已提交
2652
void setUseIPP_NotExact(bool flag)
P
Pavel Vlasov 已提交
2653
{
2654
    CoreTLSData& data = getCoreTlsData();
P
Pavel Vlasov 已提交
2655
#ifdef HAVE_IPP
2656
    data.useIPP_NE = flag;
P
Pavel Vlasov 已提交
2657
#else
H
Hamdi Sahloul 已提交
2658
    CV_UNUSED(flag);
2659
    data.useIPP_NE = false;
P
Pavel Vlasov 已提交
2660 2661 2662
#endif
}

M
maver1 已提交
2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674
#if OPENCV_ABI_COMPATIBILITY < 400
bool useIPP_NE()
{
    return useIPP_NotExact();
}

void setUseIPP_NE(bool flag)
{
    setUseIPP_NotExact(flag);
}
#endif

I
Ilya Lavrenov 已提交
2675 2676
} // namespace ipp

2677 2678
} // namespace cv

2679 2680 2681 2682 2683 2684
#ifdef HAVE_TEGRA_OPTIMIZATION

namespace tegra {

bool useTegra()
{
2685
    cv::CoreTLSData* data = cv::getCoreTlsData();
2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700

    if (data->useTegra < 0)
    {
        const char* pTegraEnv = getenv("OPENCV_TEGRA");
        if (pTegraEnv && (cv::String(pTegraEnv) == "disabled"))
            data->useTegra = false;
        else
            data->useTegra = true;
    }

    return (data->useTegra > 0);
}

void setUseTegra(bool flag)
{
2701
    cv::CoreTLSData* data = cv::getCoreTlsData();
2702 2703 2704 2705 2706 2707 2708
    data->useTegra = flag;
}

} // namespace tegra

#endif

2709
/* End of file. */