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 79typedef struct CvProcessorInfo 80{ 81 int model; 82 int count; 83 double frequency; // clocks per microsecond 84} 85CvProcessorInfo; 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*/ 106static void 107icvInitProcessorInfo( 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 273CV_INLINE const CvProcessorInfo* 274icvGetProcessorInfo() 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 299static 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 321typedef 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 338typedef struct CvPluginInfo 339{ 340 const char* basename; 341 HMODULE handle; 342 char name[100]; 343} 344CvPluginInfo; 345 346static CvPluginInfo plugins[CV_PLUGIN_MAX]; 347static CvModuleInfo cxcore_info = { 0, "cxcore", CV_VERSION, cxcore_ipp_tab }; 348 349CvModuleInfo *CvModule::first = 0, *CvModule::last = 0; 350 351CvModule::CvModule( CvModuleInfo* _info ) 352{ 353 cvRegisterModule( _info ); 354 info = last; 355} 356 357CvModule::~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 375static int 376icvUpdatePluginFuncTab( 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 489CV_IMPL int 490cvRegisterModule( 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 540CV_IMPL int 541cvUseOptimized( 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 638CvModule cxcore_module( &cxcore_info ); 639 640CV_IMPL void 641cvGetModuleInfo( 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 722typedef int64 (CV_CDECL * rdtsc_func)(void); 723 724/* helper functions for RNG initialization and accurate time measurement */ 725CV_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 765CV_IMPL double cvGetTickFrequency() 766{ 767 return icvGetProcessorInfo()->frequency; 768} 769 770 771static int icvNumThreads = 0; 772static int icvNumProcs = 0; 773 774CV_IMPL int cvGetNumThreads(void) 775{ 776 if( !icvNumProcs ) 777 cvSetNumThreads(0); 778 return icvNumThreads; 779} 780 781CV_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 806CV_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