Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 
     42 
     43 /****************************************************************************************/
     44 /*                         Dynamic detection and loading of IPP modules                 */
     45 /****************************************************************************************/
     46 
     47 #include "_cxcore.h"
     48 
     49 #if defined _MSC_VER && _MSC_VER >= 1200
     50 #pragma warning( disable: 4115 )        /* type definition in () */
     51 #endif
     52 
     53 #if defined _MSC_VER && defined WIN64 && !defined EM64T
     54 #pragma optimize( "", off )
     55 #endif
     56 
     57 #if defined WIN32 || defined WIN64
     58 #include <windows.h>
     59 #else
     60 #include <dlfcn.h>
     61 #include <sys/time.h>
     62 #endif
     63 
     64 #include <string.h>
     65 #include <stdio.h>
     66 #include <ctype.h>
     67 
     68 #define CV_PROC_GENERIC             0
     69 #define CV_PROC_SHIFT               10
     70 #define CV_PROC_ARCH_MASK           ((1 << CV_PROC_SHIFT) - 1)
     71 #define CV_PROC_IA32_GENERIC        1
     72 #define CV_PROC_IA32_WITH_MMX       (CV_PROC_IA32_GENERIC|(2 << CV_PROC_SHIFT))
     73 #define CV_PROC_IA32_WITH_SSE       (CV_PROC_IA32_GENERIC|(3 << CV_PROC_SHIFT))
     74 #define CV_PROC_IA32_WITH_SSE2      (CV_PROC_IA32_GENERIC|(4 << CV_PROC_SHIFT))
     75 #define CV_PROC_IA64                2
     76 #define CV_PROC_EM64T               3
     77 #define CV_GET_PROC_ARCH(model)     ((model) & CV_PROC_ARCH_MASK)
     78 
     79 typedef struct CvProcessorInfo
     80 {
     81     int model;
     82     int count;
     83     double frequency; // clocks per microsecond
     84 }
     85 CvProcessorInfo;
     86 
     87 #undef MASM_INLINE_ASSEMBLY
     88 
     89 #if defined WIN32 && !defined  WIN64
     90 
     91 #if defined _MSC_VER
     92 #define MASM_INLINE_ASSEMBLY 1
     93 #elif defined __BORLANDC__
     94 
     95 #if __BORLANDC__ >= 0x560
     96 #define MASM_INLINE_ASSEMBLY 1
     97 #endif
     98 
     99 #endif
    100 
    101 #endif
    102 
    103 /*
    104    determine processor type
    105 */
    106 static void
    107 icvInitProcessorInfo( CvProcessorInfo* cpu_info )
    108 {
    109     memset( cpu_info, 0, sizeof(*cpu_info) );
    110     cpu_info->model = CV_PROC_GENERIC;
    111 
    112 #if defined WIN32 || defined WIN64
    113 
    114 #ifndef PROCESSOR_ARCHITECTURE_AMD64
    115 #define PROCESSOR_ARCHITECTURE_AMD64 9
    116 #endif
    117 
    118 #ifndef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
    119 #define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10
    120 #endif
    121 
    122     SYSTEM_INFO sys;
    123     LARGE_INTEGER freq;
    124 
    125     GetSystemInfo( &sys );
    126 
    127     if( sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL &&
    128         sys.dwProcessorType == PROCESSOR_INTEL_PENTIUM && sys.wProcessorLevel >= 6 )
    129     {
    130         int version = 0, features = 0, family = 0;
    131         int id = 0;
    132         HKEY key = 0;
    133 
    134         cpu_info->count = (int)sys.dwNumberOfProcessors;
    135         unsigned long val = 0, sz = sizeof(val);
    136 
    137         if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\SYSTEM\\CentralProcessor\\0\\",
    138             0, KEY_QUERY_VALUE, &key ) >= 0 )
    139         {
    140             if( RegQueryValueEx( key, "~MHz", 0, 0, (uchar*)&val, &sz ) >= 0 )
    141                 cpu_info->frequency = (double)val;
    142             RegCloseKey( key );
    143         }
    144 
    145 #ifdef MASM_INLINE_ASSEMBLY
    146         __asm
    147         {
    148             /* use CPUID to determine the features supported */
    149             pushfd
    150             mov   eax, 1
    151             push  ebx
    152             push  esi
    153             push  edi
    154 #ifdef __BORLANDC__
    155             db 0fh
    156             db 0a2h
    157 #else
    158             _emit 0x0f
    159             _emit 0xa2
    160 #endif
    161             pop   edi
    162             pop   esi
    163             pop   ebx
    164             mov   version, eax
    165             mov   features, edx
    166             popfd
    167         }
    168 #elif defined WIN32 && __GNUC__ > 2
    169         asm volatile
    170         (
    171             "movl $1,%%eax\n\t"
    172             ".byte 0x0f; .byte 0xa2\n\t"
    173             "movl %%eax, %0\n\t"
    174             "movl %%edx, %1\n\t"
    175             : "=r"(version), "=r" (features)
    176             :
    177             : "%ebx", "%esi", "%edi"
    178         );
    179 #else
    180         {
    181             static const char cpuid_code[] =
    182                 "\x53\x56\x57\xb8\x01\x00\x00\x00\x0f\xa2\x5f\x5e\x5b\xc3";
    183             typedef int64 (CV_CDECL * func_ptr)(void);
    184             func_ptr cpuid = (func_ptr)(void*)cpuid_code;
    185             int64 cpuid_val = cpuid();
    186             version = (int)cpuid_val;
    187             features = (int)(cpuid_val >> 32);
    188         }
    189 #endif
    190 
    191         #define ICV_CPUID_M6     ((1<<15)|(1<<23))  /* cmov + MMX */
    192         #define ICV_CPUID_A6     ((1<<25)|ICV_CPUID_M6) /* <all above> + SSE */
    193         #define ICV_CPUID_W7     ((1<<26)|ICV_CPUID_A6) /* <all above> + SSE2 */
    194 
    195         family = (version >> 8) & 15;
    196         if( family >= 6 && (features & ICV_CPUID_M6) != 0 ) /* Pentium II or higher */
    197             id = features & ICV_CPUID_W7;
    198 
    199         cpu_info->model = id == ICV_CPUID_W7 ? CV_PROC_IA32_WITH_SSE2 :
    200                           id == ICV_CPUID_A6 ? CV_PROC_IA32_WITH_SSE :
    201                           id == ICV_CPUID_M6 ? CV_PROC_IA32_WITH_MMX :
    202                           CV_PROC_IA32_GENERIC;
    203     }
    204     else
    205     {
    206 #if defined EM64T
    207         if( sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 )
    208             cpu_info->model = CV_PROC_EM64T;
    209 #elif defined WIN64
    210         if( sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 )
    211             cpu_info->model = CV_PROC_IA64;
    212 #endif
    213         if( QueryPerformanceFrequency( &freq ) )
    214             cpu_info->frequency = (double)freq.QuadPart;
    215     }
    216 #else
    217     cpu_info->frequency = 1;
    218 
    219 #ifdef __x86_64__
    220     cpu_info->model = CV_PROC_EM64T;
    221 #elif defined __ia64__
    222     cpu_info->model = CV_PROC_IA64;
    223 #elif !defined __i386__
    224     cpu_info->model = CV_PROC_GENERIC;
    225 #else
    226     cpu_info->model = CV_PROC_IA32_GENERIC;
    227 
    228     // reading /proc/cpuinfo file (proc file system must be supported)
    229     FILE *file = fopen( "/proc/cpuinfo", "r" );
    230 
    231     if( file )
    232     {
    233         char buffer[1024];
    234         int max_size = sizeof(buffer)-1;
    235 
    236         for(;;)
    237         {
    238             const char* ptr = fgets( buffer, max_size, file );
    239             if( !ptr )
    240                 break;
    241             if( strncmp( buffer, "flags", 5 ) == 0 )
    242             {
    243                 if( strstr( buffer, "mmx" ) && strstr( buffer, "cmov" ))
    244                 {
    245                     cpu_info->model = CV_PROC_IA32_WITH_MMX;
    246                     if( strstr( buffer, "xmm" ) || strstr( buffer, "sse" ))
    247                     {
    248                         cpu_info->model = CV_PROC_IA32_WITH_SSE;
    249                         if( strstr( buffer, "emm" ))
    250                             cpu_info->model = CV_PROC_IA32_WITH_SSE2;
    251                     }
    252                 }
    253             }
    254             else if( strncmp( buffer, "cpu MHz", 7 ) == 0 )
    255             {
    256                 char* pos = strchr( buffer, ':' );
    257                 if( pos )
    258                     cpu_info->frequency = strtod( pos + 1, &pos );
    259             }
    260         }
    261 
    262         fclose( file );
    263         if( CV_GET_PROC_ARCH(cpu_info->model) != CV_PROC_IA32_GENERIC )
    264             cpu_info->frequency = 1;
    265         else
    266             assert( cpu_info->frequency > 1 );
    267     }
    268 #endif
    269 #endif
    270 }
    271 
    272 
    273 CV_INLINE const CvProcessorInfo*
    274 icvGetProcessorInfo()
    275 {
    276     static CvProcessorInfo cpu_info;
    277     static int init_cpu_info = 0;
    278     if( !init_cpu_info )
    279     {
    280         icvInitProcessorInfo( &cpu_info );
    281         init_cpu_info = 1;
    282     }
    283     return &cpu_info;
    284 }
    285 
    286 
    287 /****************************************************************************************/
    288 /*                               Make functions descriptions                            */
    289 /****************************************************************************************/
    290 
    291 #undef IPCVAPI_EX
    292 #define IPCVAPI_EX(type,func_name,names,modules,arg) \
    293     { (void**)&func_name##_p, (void*)(size_t)-1, names, modules, 0 },
    294 
    295 #undef IPCVAPI_C_EX
    296 #define IPCVAPI_C_EX(type,func_name,names,modules,arg) \
    297     { (void**)&func_name##_p, (void*)(size_t)-1, names, modules, 0 },
    298 
    299 static CvPluginFuncInfo cxcore_ipp_tab[] =
    300 {
    301 #undef _CXCORE_IPP_H_
    302 #include "_cxipp.h"
    303 #undef _CXCORE_IPP_H_
    304     {0, 0, 0, 0, 0}
    305 };
    306 
    307 
    308 /*
    309    determine processor type, load appropriate dll and
    310    initialize all function pointers
    311 */
    312 #if defined WIN32 || defined WIN64
    313 #define DLL_PREFIX ""
    314 #define DLL_SUFFIX ".dll"
    315 #else
    316 #define DLL_PREFIX "lib"
    317 #define DLL_SUFFIX ".so"
    318 #define LoadLibrary(name) dlopen(name, RTLD_LAZY)
    319 #define FreeLibrary(name) dlclose(name)
    320 #define GetProcAddress dlsym
    321 typedef void* HMODULE;
    322 #endif
    323 
    324 #if 0 /*def _DEBUG*/
    325 #define DLL_DEBUG_FLAG "d"
    326 #else
    327 #define DLL_DEBUG_FLAG ""
    328 #endif
    329 
    330 #define VERBOSE_LOADING 0
    331 
    332 #if VERBOSE_LOADING
    333 #define ICV_PRINTF(args)  printf args; fflush(stdout)
    334 #else
    335 #define ICV_PRINTF(args)
    336 #endif
    337 
    338 typedef struct CvPluginInfo
    339 {
    340     const char* basename;
    341     HMODULE handle;
    342     char name[100];
    343 }
    344 CvPluginInfo;
    345 
    346 static CvPluginInfo plugins[CV_PLUGIN_MAX];
    347 static CvModuleInfo cxcore_info = { 0, "cxcore", CV_VERSION, cxcore_ipp_tab };
    348 
    349 CvModuleInfo *CvModule::first = 0, *CvModule::last = 0;
    350 
    351 CvModule::CvModule( CvModuleInfo* _info )
    352 {
    353     cvRegisterModule( _info );
    354     info = last;
    355 }
    356 
    357 CvModule::~CvModule()
    358 {
    359     if( info )
    360     {
    361         CvModuleInfo* p = first;
    362         for( ; p != 0 && p->next != info; p = p->next )
    363             ;
    364         if( p )
    365             p->next = info->next;
    366         if( first == info )
    367             first = info->next;
    368         if( last == info )
    369             last = p;
    370         cvFree( &info );
    371         info = 0;
    372     }
    373 }
    374 
    375 static int
    376 icvUpdatePluginFuncTab( CvPluginFuncInfo* func_tab )
    377 {
    378     int i, loaded_functions = 0;
    379 
    380     // 1. reset pointers
    381     for( i = 0; func_tab[i].func_addr != 0; i++ )
    382     {
    383         if( func_tab[i].default_func_addr == (void*)(size_t)-1 )
    384             func_tab[i].default_func_addr = *func_tab[i].func_addr;
    385         else
    386             *func_tab[i].func_addr = func_tab[i].default_func_addr;
    387         func_tab[i].loaded_from = 0;
    388     }
    389 
    390     // ippopencv substitutes all the other IPP modules
    391     if( plugins[CV_PLUGIN_OPTCV].handle != 0 )
    392     {
    393         for( i = 2; i < CV_PLUGIN_MKL; i++ )
    394         {
    395             assert( plugins[i].handle == 0 );
    396             plugins[i].handle = plugins[CV_PLUGIN_OPTCV].handle;
    397         }
    398     }
    399 
    400     // 2. try to find corresponding functions in ipp* and reassign pointers to them
    401     for( i = 0; func_tab[i].func_addr != 0; i++ )
    402     {
    403     #if defined _MSC_VER && _MSC_VER >= 1200
    404         #pragma warning( disable: 4054 4055 ) /* converting pointers to code<->data */
    405     #endif
    406         char name[100];
    407         int j = 0, idx = 0;
    408 
    409         assert( func_tab[i].loaded_from == 0 );
    410 
    411         if( func_tab[i].search_modules )
    412         {
    413             uchar* addr = 0;
    414             const char* name_ptr = func_tab[i].func_names;
    415 
    416             for( ; j < 10 && name_ptr; j++ )
    417             {
    418                 const char* name_start = name_ptr;
    419                 const char* name_end;
    420                 while( !isalpha(name_start[0]) && name_start[0] != '\0' )
    421                     name_start++;
    422                 if( !name_start[0] )
    423                     name_start = 0;
    424                 name_end = name_start ? strchr( name_start, ',' ) : 0;
    425                 idx = (func_tab[i].search_modules / (1<<j*4)) % CV_PLUGIN_MAX;
    426 
    427                 if( plugins[idx].handle != 0 && name_start )
    428                 {
    429                     if( name_end != 0 )
    430                     {
    431                         strncpy( name, name_start, name_end - name_start );
    432                         name[name_end - name_start] = '\0';
    433                     }
    434                     else
    435                         strcpy( name, name_start );
    436 
    437                     addr = (uchar*)GetProcAddress( plugins[idx].handle, name );
    438                     if( addr )
    439                         break;
    440                 }
    441                 name_ptr = name_end;
    442             }
    443 
    444             if( addr )
    445             {
    446             /*#ifdef WIN32
    447                 while( *addr == 0xE9 )
    448                     addr += 5 + *((int*)(addr + 1));
    449             #endif*/
    450                 *func_tab[i].func_addr = addr;
    451                 func_tab[i].loaded_from = idx; // store index of the module
    452                                                    // that contain the loaded function
    453                 loaded_functions++;
    454                 ICV_PRINTF(("%s: \t%s\n", name, plugins[idx].name ));
    455             }
    456 
    457             #if defined _MSC_VER && _MSC_VER >= 1200
    458                 #pragma warning( default: 4054 4055 )
    459             #endif
    460         }
    461     }
    462 
    463 #if VERBOSE_LOADING
    464     {
    465     int not_loaded = 0;
    466     ICV_PRINTF(("\nTotal loaded: %d\n\n", loaded_functions ));
    467     printf( "***************************************************\nNot loaded ...\n\n" );
    468     for( i = 0; func_tab[i].func_addr != 0; i++ )
    469         if( !func_tab[i].loaded_from )
    470         {
    471             ICV_PRINTF(( "%s\n", func_tab[i].func_names ));
    472             not_loaded++;
    473         }
    474 
    475     ICV_PRINTF(("\nTotal: %d\n", not_loaded ));
    476     }
    477 #endif
    478 
    479     if( plugins[CV_PLUGIN_OPTCV].handle != 0 )
    480     {
    481         for( i = 2; i < CV_PLUGIN_MKL; i++ )
    482             plugins[i].handle = 0;
    483     }
    484 
    485     return loaded_functions;
    486 }
    487 
    488 
    489 CV_IMPL int
    490 cvRegisterModule( const CvModuleInfo* module )
    491 {
    492     CvModuleInfo* module_copy = 0;
    493 
    494     CV_FUNCNAME( "cvRegisterModule" );
    495 
    496     __BEGIN__;
    497 
    498     size_t name_len, version_len;
    499 
    500     CV_ASSERT( module != 0 && module->name != 0 && module->version != 0 );
    501 
    502     name_len = strlen(module->name);
    503     version_len = strlen(module->version);
    504 
    505     CV_CALL( module_copy = (CvModuleInfo*)cvAlloc( sizeof(*module_copy) +
    506                                         name_len + 1 + version_len + 1 ));
    507 
    508     *module_copy = *module;
    509     module_copy->name = (char*)(module_copy + 1);
    510     module_copy->version = (char*)(module_copy + 1) + name_len + 1;
    511 
    512     memcpy( (void*)module_copy->name, module->name, name_len + 1 );
    513     memcpy( (void*)module_copy->version, module->version, version_len + 1 );
    514     module_copy->next = 0;
    515 
    516     if( CvModule::first == 0 )
    517         CvModule::first = module_copy;
    518     else
    519         CvModule::last->next = module_copy;
    520     CvModule::last = module_copy;
    521 
    522     if( CvModule::first == CvModule::last )
    523     {
    524         CV_CALL( cvUseOptimized(1));
    525     }
    526     else
    527     {
    528         CV_CALL( icvUpdatePluginFuncTab( module_copy->func_tab ));
    529     }
    530 
    531     __END__;
    532 
    533     if( cvGetErrStatus() < 0 && module_copy )
    534         cvFree( &module_copy );
    535 
    536     return module_copy ? 0 : -1;
    537 }
    538 
    539 
    540 CV_IMPL int
    541 cvUseOptimized( int load_flag )
    542 {
    543     int i, loaded_modules = 0, loaded_functions = 0;
    544     CvModuleInfo* module;
    545     const CvProcessorInfo* cpu_info = icvGetProcessorInfo();
    546     int arch = CV_GET_PROC_ARCH(cpu_info->model);
    547 
    548     // TODO: implement some more elegant way
    549     // to find the latest and the greatest IPP/MKL libraries
    550     static const char* opencv_sfx[] = { "100", "099", "097", 0 };
    551     static const char* ipp_sfx_ia32[] = { "-6.1", "-6.0", "-5.3", "-5.2", "-5.1", "", 0 };
    552     static const char* ipp_sfx_ia64[] = { "64-6.1", "64-6.0", "64-5.3", "64-5.2", "64-5.1", "64", 0 };
    553     static const char* ipp_sfx_em64t[] = { "em64t-6.1", "em64t-6.0", "em64t-5.3", "em64t-5.2", "em64t-5.1", "em64t", 0 };
    554     static const char* mkl_sfx_ia32[] = { "p4", "p3", "def", 0 };
    555     static const char* mkl_sfx_ia64[] = { "i2p", "itp", 0 };
    556     static const char* mkl_sfx_em64t[] = { "def", 0 };
    557     const char** ipp_suffix = arch == CV_PROC_IA64 ? ipp_sfx_ia64 :
    558                               arch == CV_PROC_EM64T ? ipp_sfx_em64t : ipp_sfx_ia32;
    559     const char** mkl_suffix = arch == CV_PROC_IA64 ? mkl_sfx_ia64 :
    560                               arch == CV_PROC_EM64T ? mkl_sfx_em64t : mkl_sfx_ia32;
    561 
    562     for( i = 0; i < CV_PLUGIN_MAX; i++ )
    563         plugins[i].basename = 0;
    564     plugins[CV_PLUGIN_NONE].basename = 0;
    565     plugins[CV_PLUGIN_NONE].name[0] = '\0';
    566     plugins[CV_PLUGIN_OPTCV].basename = "ippopencv";
    567     plugins[CV_PLUGIN_IPPCV].basename = "ippcv";
    568     plugins[CV_PLUGIN_IPPI].basename = "ippi";
    569     plugins[CV_PLUGIN_IPPS].basename = "ipps";
    570     plugins[CV_PLUGIN_IPPVM].basename = "ippvm";
    571     plugins[CV_PLUGIN_IPPCC].basename = "ippcc";
    572     plugins[CV_PLUGIN_MKL].basename = "mkl_";
    573 
    574     // try to load optimized dlls
    575     for( i = 1; i < CV_PLUGIN_MAX; i++ )
    576     {
    577         // unload previously loaded optimized modules
    578         if( plugins[i].handle )
    579         {
    580             FreeLibrary( plugins[i].handle );
    581             plugins[i].handle = 0;
    582         }
    583 
    584         // do not load regular IPP modules if the custom merged IPP module is already found.
    585         if( i < CV_PLUGIN_MKL && load_flag && plugins[CV_PLUGIN_OPTCV].handle != 0 )
    586             continue;
    587 
    588         if( load_flag && plugins[i].basename &&
    589             (arch == CV_PROC_IA32_GENERIC || arch == CV_PROC_IA64 || arch == CV_PROC_EM64T) )
    590         {
    591             const char** suffix = i == CV_PLUGIN_OPTCV ? opencv_sfx :
    592                             i < CV_PLUGIN_MKL ? ipp_suffix : mkl_suffix;
    593             if( suffix == mkl_sfx_ia32 )
    594             {
    595                 if( !(cpu_info->model & CV_PROC_IA32_WITH_SSE2) )
    596                     suffix++;
    597                 if( !(cpu_info->model & CV_PROC_IA32_WITH_SSE) )
    598                     suffix++;
    599             }
    600 
    601             for( ; *suffix != 0; suffix++ )
    602             {
    603                 sprintf( plugins[i].name, DLL_PREFIX "%s%s" DLL_DEBUG_FLAG DLL_SUFFIX,
    604                     plugins[i].basename, *suffix );
    605 
    606                 ICV_PRINTF(("loading %s...\n", plugins[i].name ));
    607                 plugins[i].handle = LoadLibrary( plugins[i].name );
    608                 if( plugins[i].handle != 0 )
    609                 {
    610                     ICV_PRINTF(("%s loaded\n", plugins[i].name ));
    611                     loaded_modules++;
    612                     break;
    613                 }
    614                 #ifndef WIN32
    615                 // temporary workaround for MacOSX
    616                 sprintf( plugins[i].name, DLL_PREFIX "%s%s" DLL_DEBUG_FLAG ".dylib",
    617                     plugins[i].basename, *suffix );
    618 
    619                 ICV_PRINTF(("loading %s...\n", plugins[i].name ));
    620                 plugins[i].handle = LoadLibrary( plugins[i].name );
    621                 if( plugins[i].handle != 0 )
    622                 {
    623                     ICV_PRINTF(("%s loaded\n", plugins[i].name ));
    624                     loaded_modules++;
    625                     break;
    626                 }
    627                 #endif
    628             }
    629         }
    630     }
    631 
    632     for( module = CvModule::first; module != 0; module = module->next )
    633         loaded_functions += icvUpdatePluginFuncTab( module->func_tab );
    634 
    635     return loaded_functions;
    636 }
    637 
    638 CvModule cxcore_module( &cxcore_info );
    639 
    640 CV_IMPL void
    641 cvGetModuleInfo( const char* name, const char **version, const char **plugin_list )
    642 {
    643     static char joint_verinfo[1024] = "";
    644     static char plugin_list_buf[1024] = "";
    645 
    646     CV_FUNCNAME( "cvGetLibraryInfo" );
    647 
    648     if( version )
    649         *version = 0;
    650 
    651     if( plugin_list )
    652         *plugin_list = 0;
    653 
    654     __BEGIN__;
    655 
    656     CvModuleInfo* module;
    657 
    658     if( version )
    659     {
    660         if( name )
    661         {
    662             size_t i, name_len = strlen(name);
    663 
    664             for( module = CvModule::first; module != 0; module = module->next )
    665             {
    666                 if( strlen(module->name) == name_len )
    667                 {
    668                     for( i = 0; i < name_len; i++ )
    669                     {
    670                         int c0 = toupper(module->name[i]), c1 = toupper(name[i]);
    671                         if( c0 != c1 )
    672                             break;
    673                     }
    674                     if( i == name_len )
    675                         break;
    676                 }
    677             }
    678             if( !module )
    679                 CV_ERROR( CV_StsObjectNotFound, "The module is not found" );
    680 
    681             *version = module->version;
    682         }
    683         else
    684         {
    685             char* ptr = joint_verinfo;
    686 
    687             for( module = CvModule::first; module != 0; module = module->next )
    688             {
    689                 sprintf( ptr, "%s: %s%s", module->name, module->version, module->next ? ", " : "" );
    690                 ptr += strlen(ptr);
    691             }
    692 
    693             *version = joint_verinfo;
    694         }
    695     }
    696 
    697     if( plugin_list )
    698     {
    699         char* ptr = plugin_list_buf;
    700         int i;
    701 
    702         for( i = 0; i < CV_PLUGIN_MAX; i++ )
    703             if( plugins[i].handle != 0 )
    704             {
    705                 sprintf( ptr, "%s, ", plugins[i].name );
    706                 ptr += strlen(ptr);
    707             }
    708 
    709         if( ptr > plugin_list_buf )
    710         {
    711             ptr[-2] = '\0';
    712             *plugin_list = plugin_list_buf;
    713         }
    714         else
    715             *plugin_list = "";
    716     }
    717 
    718     __END__;
    719 }
    720 
    721 
    722 typedef int64 (CV_CDECL * rdtsc_func)(void);
    723 
    724 /* helper functions for RNG initialization and accurate time measurement */
    725 CV_IMPL  int64  cvGetTickCount( void )
    726 {
    727     const CvProcessorInfo* cpu_info = icvGetProcessorInfo();
    728 
    729     if( cpu_info->frequency > 1 &&
    730         CV_GET_PROC_ARCH(cpu_info->model) == CV_PROC_IA32_GENERIC )
    731     {
    732 #ifdef MASM_INLINE_ASSEMBLY
    733     #ifdef __BORLANDC__
    734         __asm db 0fh
    735         __asm db 31h
    736     #else
    737         __asm _emit 0x0f;
    738         __asm _emit 0x31;
    739     #endif
    740 #elif (defined __GNUC__ || defined CV_ICC) && defined __i386__
    741         int64 t;
    742         asm volatile (".byte 0xf; .byte 0x31" /* "rdtsc" */ : "=A" (t));
    743         return t;
    744 #else
    745         static const char code[] = "\x0f\x31\xc3";
    746         rdtsc_func func = (rdtsc_func)(void*)code;
    747         return func();
    748 #endif
    749     }
    750     else
    751     {
    752 #if defined WIN32 || defined WIN64
    753         LARGE_INTEGER counter;
    754         QueryPerformanceCounter( &counter );
    755         return (int64)counter.QuadPart;
    756 #else
    757         struct timeval tv;
    758         struct timezone tz;
    759         gettimeofday( &tv, &tz );
    760         return (int64)tv.tv_sec*1000000 + tv.tv_usec;
    761 #endif
    762     }
    763 }
    764 
    765 CV_IMPL  double  cvGetTickFrequency()
    766 {
    767     return icvGetProcessorInfo()->frequency;
    768 }
    769 
    770 
    771 static int icvNumThreads = 0;
    772 static int icvNumProcs = 0;
    773 
    774 CV_IMPL int cvGetNumThreads(void)
    775 {
    776     if( !icvNumProcs )
    777         cvSetNumThreads(0);
    778     return icvNumThreads;
    779 }
    780 
    781 CV_IMPL void cvSetNumThreads( int threads )
    782 {
    783     if( !icvNumProcs )
    784     {
    785 #ifdef _OPENMP
    786         icvNumProcs = omp_get_num_procs();
    787         icvNumProcs = MIN( icvNumProcs, CV_MAX_THREADS );
    788 #else
    789         icvNumProcs = 1;
    790 #endif
    791     }
    792 
    793 #ifdef _OPENMP
    794     if( threads <= 0 )
    795         threads = icvNumProcs;
    796     //else
    797     //    threads = MIN( threads, icvNumProcs );
    798 
    799     icvNumThreads = threads;
    800 #else
    801     icvNumThreads = 1;
    802 #endif
    803 }
    804 
    805 
    806 CV_IMPL int cvGetThreadNum(void)
    807 {
    808 #ifdef _OPENMP
    809     return omp_get_thread_num();
    810 #else
    811     return 0;
    812 #endif
    813 }
    814 
    815 
    816 /* End of file. */
    817