Move the sources to trunk
[opencv] / cxcore / src / cxswitcher.cpp
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. */