Go to the documentation of this file.00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00770 #include "generic.h"
00771
00772 #include <assert.h>
00773 #include <stdlib.h>
00774 #include <stdio.h>
00775 #include <stdarg.h>
00776 #include <math.h>
00777
00778 #if defined(VL_OS_WIN)
00779 #include <Windows.h>
00780 #endif
00781
00782 #if ! defined(VL_DISABLE_THREADS) && defined(VL_THREADS_POSIX)
00783 #include <pthread.h>
00784 #endif
00785
00786 #if defined(VL_OS_MACOSX) || defined(VL_OS_LINUX)
00787 #include <unistd.h>
00788 #endif
00789
00790 #if defined(_OPENMP)
00791 #include <omp.h>
00792 #endif
00793
00794
00795
00796
00797
00798
00799 typedef struct _VlThreadState
00800 {
00801
00802 int lastError ;
00803 char lastErrorMessage [VL_ERR_MSG_LEN] ;
00804
00805
00806 VlRand rand ;
00807
00808
00809 #if defined(VL_OS_WIN)
00810 LARGE_INTEGER ticFreq ;
00811 LARGE_INTEGER ticMark ;
00812 #else
00813 clock_t ticMark ;
00814 #endif
00815 } VlThreadState ;
00816
00817
00818 typedef struct _VlState
00819 {
00820
00821
00822 #if defined(VL_DISABLE_THREADS)
00823 VlThreadState * threadState ;
00824 #else
00825 #if defined(VL_THREADS_POSIX)
00826 pthread_key_t threadKey ;
00827 pthread_mutex_t mutex ;
00828 pthread_t mutexOwner ;
00829 pthread_cond_t mutexCondition ;
00830 size_t mutexCount ;
00831 #elif defined(VL_THREADS_WIN)
00832 DWORD tlsIndex ;
00833 CRITICAL_SECTION mutex ;
00834 #endif
00835 #endif
00836
00837
00838 int (*printf_func) (char const * format, ...) ;
00839 void *(*malloc_func) (size_t) ;
00840 void *(*realloc_func) (void*,size_t) ;
00841 void *(*calloc_func) (size_t, size_t) ;
00842 void (*free_func) (void*) ;
00843
00844 #if defined(VL_ARCH_IX86) || defined(VL_ARCH_X64) || defined(VL_ARCH_IA64)
00845 VlX86CpuInfo cpuInfo ;
00846 #endif
00847 vl_size numCPUs ;
00848 vl_bool simdEnabled ;
00849 vl_size numThreads ;
00850 } VlState ;
00851
00852
00853 VlState _vl_state ;
00854
00855
00856 VL_INLINE VlState * vl_get_state () ;
00857 VL_INLINE VlThreadState * vl_get_thread_specific_state () ;
00858 static void vl_lock_state (void) ;
00859 static void vl_unlock_state (void) ;
00860 static VlThreadState * vl_thread_specific_state_new (void) ;
00861 static void vl_thread_specific_state_delete (VlThreadState * self) ;
00862
00867 char const *
00868 vl_get_version_string ()
00869 {
00870 return VL_VERSION_STRING ;
00871 }
00872
00880 char *
00881 vl_configuration_to_string_copy ()
00882 {
00883 char * string = 0 ;
00884 int length = 0 ;
00885 char * staticString = vl_static_configuration_to_string_copy() ;
00886 char * cpuString =
00887 #if defined(VL_ARCH_IX86) || defined(VL_ARCH_X64) || defined(VL_ARCH_IA64)
00888 _vl_x86cpu_info_to_string_copy(&vl_get_state()->cpuInfo) ;
00889 #else
00890 "Generic CPU" ;
00891 #endif
00892 #if defined(DEBUG)
00893 int const debug = 1 ;
00894 #else
00895 int const debug = 0 ;
00896 #endif
00897
00898 while (string == 0) {
00899 if (length > 0) {
00900 string = vl_malloc(sizeof(char) * length) ;
00901 if (string == NULL) break ;
00902 }
00903 length = snprintf(string, length,
00904 "VLFeat version %s\n"
00905 " Static config: %s\n"
00906 " %" VL_FMT_SIZE " CPU(s): %s\n"
00907 #if defined(_OPENMP)
00908 " OpenMP: max threads: %d (library: %" VL_FMT_SIZE ")\n"
00909 #endif
00910 " Debug: %s\n",
00911 vl_get_version_string (),
00912 staticString,
00913 vl_get_num_cpus(), cpuString,
00914 #if defined(_OPENMP)
00915 omp_get_max_threads(), vl_get_max_threads(),
00916 #endif
00917 VL_YESNO(debug)) ;
00918 length += 1 ;
00919 }
00920
00921 if (staticString) vl_free(staticString) ;
00922 if (cpuString) vl_free(cpuString) ;
00923 return string ;
00924 }
00925
00927 static int
00928 do_nothing_printf (char const* format VL_UNUSED, ...)
00929 {
00930 return 0 ;
00931 }
00932
00945 static void
00946 vl_lock_state (void)
00947 {
00948 #if ! defined(VL_DISABLE_THREADS)
00949 #if defined(VL_THREADS_POSIX)
00950 VlState * state = vl_get_state () ;
00951 pthread_t thisThread = pthread_self () ;
00952 pthread_mutex_lock (&state->mutex) ;
00953 if (state->mutexCount >= 1 &&
00954 pthread_equal (state->mutexOwner, thisThread)) {
00955 state->mutexCount ++ ;
00956 } else {
00957 while (state->mutexCount >= 1) {
00958 pthread_cond_wait (&state->mutexCondition, &state->mutex) ;
00959 }
00960 state->mutexOwner = thisThread ;
00961 state->mutexCount = 1 ;
00962 }
00963 pthread_mutex_unlock (&state->mutex) ;
00964 #elif defined(VL_THREADS_WIN)
00965 EnterCriticalSection (&vl_get_state()->mutex) ;
00966 #endif
00967 #endif
00968 }
00969
00978 static void
00979 vl_unlock_state (void)
00980 {
00981 #if ! defined(VL_DISABLE_THREADS)
00982 #if defined(VL_THREADS_POSIX)
00983 VlState * state = vl_get_state () ;
00984 pthread_mutex_lock (&state->mutex) ;
00985 -- state->mutexCount ;
00986 if (state->mutexCount == 0) {
00987 pthread_cond_signal (&state->mutexCondition) ;
00988 }
00989 pthread_mutex_unlock (&state->mutex) ;
00990 #elif defined(VL_THREADS_WIN)
00991 LeaveCriticalSection (&vl_get_state()->mutex) ;
00992 #endif
00993 #endif
00994 }
00995
01004 VL_INLINE VlState *
01005 vl_get_state (void)
01006 {
01007 return &_vl_state ;
01008 }
01009
01016 VL_INLINE VlThreadState *
01017 vl_get_thread_specific_state (void)
01018 {
01019 #ifdef VL_DISABLE_THREADS
01020 return vl_get_state()->threadState ;
01021 #else
01022 VlState * state ;
01023 VlThreadState * threadState ;
01024
01025 vl_lock_state() ;
01026 state = vl_get_state() ;
01027
01028 #if defined(VL_THREADS_POSIX)
01029 threadState = (VlThreadState *) pthread_getspecific(state->threadKey) ;
01030 #elif defined(VL_THREADS_WIN)
01031 threadState = (VlThreadState *) TlsGetValue(state->tlsIndex) ;
01032 #endif
01033
01034 if (! threadState) {
01035 threadState = vl_thread_specific_state_new () ;
01036 }
01037
01038 #if defined(VL_THREADS_POSIX)
01039 pthread_setspecific(state->threadKey, threadState) ;
01040 #elif defined(VL_THREADS_WIN)
01041 TlsSetValue(state->tlsIndex, threadState) ;
01042 #endif
01043
01044 vl_unlock_state() ;
01045 return threadState ;
01046 #endif
01047 }
01048
01049
01054 vl_size
01055 vl_get_num_cpus (void)
01056 {
01057 return vl_get_state()->numCPUs ;
01058 }
01059
01071 void
01072 vl_set_simd_enabled (vl_bool x)
01073 {
01074 vl_get_state()->simdEnabled = x ;
01075 }
01076
01081 vl_bool
01082 vl_get_simd_enabled (void)
01083 {
01084 return vl_get_state()->simdEnabled ;
01085 }
01086
01091 vl_bool
01092 vl_cpu_has_avx (void)
01093 {
01094 #if defined(VL_ARCH_IX86) || defined(VL_ARCH_X64) || defined(VL_ARCH_IA64)
01095 return vl_get_state()->cpuInfo.hasAVX ;
01096 #else
01097 return VL_FALSE ;
01098 #endif
01099 }
01100
01105 vl_bool
01106 vl_cpu_has_sse3 (void)
01107 {
01108 #if defined(VL_ARCH_IX86) || defined(VL_ARCH_X64) || defined(VL_ARCH_IA64)
01109 return vl_get_state()->cpuInfo.hasSSE3 ;
01110 #else
01111 return VL_FALSE ;
01112 #endif
01113 }
01114
01119 vl_bool
01120 vl_cpu_has_sse2 (void)
01121 {
01122 #if defined(VL_ARCH_IX86) || defined(VL_ARCH_X64) || defined(VL_ARCH_IA64)
01123 return vl_get_state()->cpuInfo.hasSSE2 ;
01124 #else
01125 return VL_FALSE ;
01126 #endif
01127 }
01128
01129
01130
01142 vl_size
01143 vl_get_thread_limit (void)
01144 {
01145 #if defined(_OPENMP)
01146 #if _OPENMP >= 200805
01147
01148 return omp_get_thread_limit() ;
01149 #else
01150 return 0 ;
01151 #endif
01152 #else
01153 return 1 ;
01154 #endif
01155 }
01156
01174 vl_size
01175 vl_get_max_threads (void)
01176 {
01177 #if defined(_OPENMP)
01178 return vl_get_state()->numThreads ;
01179 #else
01180 return 1 ;
01181 #endif
01182 }
01183
01206 #if defined(_OPENMP)
01207 void
01208 vl_set_num_threads (vl_size numThreads)
01209 {
01210 if (numThreads == 0) {
01211 numThreads = omp_get_max_threads() ;
01212 }
01213 vl_get_state()->numThreads = numThreads ;
01214 }
01215 #else
01216 void
01217 vl_set_num_threads (vl_size numThreads VL_UNUSED) { }
01218 #endif
01219
01220
01237 int
01238 vl_set_last_error (int error, char const * errorMessage, ...)
01239 {
01240 VlThreadState * state = vl_get_thread_specific_state() ;
01241 va_list args;
01242 va_start(args, errorMessage) ;
01243 if (errorMessage) {
01244 #ifdef VL_COMPILER_LCC
01245 vsprintf(state->lastErrorMessage, errorMessage, args) ;
01246 #else
01247 vsnprintf(state->lastErrorMessage,
01248 sizeof(state->lastErrorMessage)/sizeof(char),
01249 errorMessage, args) ;
01250 #endif
01251 } else {
01252 state->lastErrorMessage[0] = 0 ;
01253 }
01254 state->lastError = error ;
01255 va_end(args) ;
01256 return error ;
01257 }
01258
01264 int
01265 vl_get_last_error (void) {
01266 return vl_get_thread_specific_state()->lastError ;
01267 }
01268
01274 char const *
01275 vl_get_last_error_message (void)
01276 {
01277 return vl_get_thread_specific_state()->lastErrorMessage ;
01278 }
01279
01280
01288 void
01289 vl_set_alloc_func (void *(*malloc_func) (size_t),
01290 void *(*realloc_func) (void*, size_t),
01291 void *(*calloc_func) (size_t, size_t),
01292 void (*free_func) (void*))
01293 {
01294 VlState * state ;
01295 vl_lock_state () ;
01296 state = vl_get_state() ;
01297 state->malloc_func = malloc_func ;
01298 state->realloc_func = realloc_func ;
01299 state->calloc_func = calloc_func ;
01300 state->free_func = free_func ;
01301 vl_unlock_state () ;
01302 }
01303
01312 void *
01313 vl_malloc (size_t n)
01314 {
01315 return (vl_get_state()->malloc_func)(n) ;
01316
01317 }
01318
01319
01329 void *
01330 vl_realloc (void* ptr, size_t n)
01331 {
01332 return (vl_get_state()->realloc_func)(ptr, n) ;
01333 }
01334
01344 void *
01345 vl_calloc (size_t n, size_t size)
01346 {
01347 return (vl_get_state()->calloc_func)(n, size) ;
01348 }
01349
01358 void
01359 vl_free (void *ptr)
01360 {
01361 (vl_get_state()->free_func)(ptr) ;
01362 }
01363
01364
01365
01371 void
01372 vl_set_printf_func (printf_func_t printf_func)
01373 {
01374 vl_get_state()->printf_func = printf_func ? printf_func : do_nothing_printf ;
01375 }
01376
01382 printf_func_t
01383 vl_get_printf_func (void) {
01384 return vl_get_state()->printf_func ;
01385 }
01386
01387
01393 double
01394 vl_get_cpu_time ()
01395 {
01396 #ifdef VL_OS_WIN
01397 VlThreadState * threadState = vl_get_thread_specific_state() ;
01398 LARGE_INTEGER mark ;
01399 QueryPerformanceCounter (&mark) ;
01400 return (double)mark.QuadPart / (double)threadState->ticFreq.QuadPart ;
01401 #else
01402 return (double)clock() / (double)CLOCKS_PER_SEC ;
01403 #endif
01404 }
01405
01412 void
01413 vl_tic (void)
01414 {
01415 VlThreadState * threadState = vl_get_thread_specific_state() ;
01416 #ifdef VL_OS_WIN
01417 QueryPerformanceCounter (&threadState->ticMark) ;
01418 #else
01419 threadState->ticMark = clock() ;
01420 #endif
01421 }
01422
01437 double
01438 vl_toc (void)
01439 {
01440 VlThreadState * threadState = vl_get_thread_specific_state() ;
01441 #ifdef VL_OS_WIN
01442 LARGE_INTEGER tocMark ;
01443 QueryPerformanceCounter(&tocMark) ;
01444 return (double) (tocMark.QuadPart - threadState->ticMark.QuadPart) /
01445 threadState->ticFreq.QuadPart ;
01446 #else
01447 return (double) (clock() - threadState->ticMark) / CLOCKS_PER_SEC ;
01448 #endif
01449 }
01450
01451
01460 VL_EXPORT VlRand *
01461 vl_get_rand (void)
01462 {
01463 return &vl_get_thread_specific_state()->rand ;
01464 }
01465
01466
01467
01468
01469
01474 static VlThreadState *
01475 vl_thread_specific_state_new (void)
01476 {
01477 VlThreadState * self ;
01478 #if defined(DEBUG)
01479 printf("VLFeat DEBUG: thread constructor begins.\n") ;
01480 #endif
01481 self = malloc(sizeof(VlThreadState)) ;
01482 self->lastError = 0 ;
01483 self->lastErrorMessage[0] = 0 ;
01484 #if defined(VL_OS_WIN)
01485 QueryPerformanceFrequency (&self->ticFreq) ;
01486 self->ticMark.QuadPart = 0 ;
01487 #else
01488 self->ticMark = 0 ;
01489 #endif
01490 vl_rand_init (&self->rand) ;
01491
01492 return self ;
01493 }
01494
01499 static void
01500 vl_thread_specific_state_delete (VlThreadState * self)
01501 {
01502 #if defined(DEBUG)
01503 printf("VLFeat DEBUG: thread destructor begins.\n") ;
01504 #endif
01505 free (self) ;
01506 }
01507
01508
01509
01510
01511
01512
01513
01514
01515 #if (defined(VL_OS_LINUX) || defined(VL_OS_MACOSX)) && defined(VL_COMPILER_GNUC)
01516 static void vl_constructor () __attribute__ ((constructor)) ;
01517 static void vl_destructor () __attribute__ ((destructor)) ;
01518 #endif
01519
01520 #if defined(VL_OS_WIN)
01521 static void vl_constructor () ;
01522 static void vl_destructor () ;
01523
01524 BOOL WINAPI DllMain(
01525 HINSTANCE hinstDLL,
01526 DWORD fdwReason,
01527 LPVOID lpReserved )
01528 {
01529 VlState * state ;
01530 VlThreadState * threadState ;
01531 switch (fdwReason) {
01532 case DLL_PROCESS_ATTACH:
01533
01534 vl_constructor () ;
01535 break ;
01536
01537 case DLL_THREAD_ATTACH:
01538
01539 break ;
01540
01541 case DLL_THREAD_DETACH:
01542
01543 #if ! defined(VL_DISABLE_THREADS) && defined(VL_THREADS_WIN)
01544 state = vl_get_state() ;
01545 threadState = (VlThreadState*) TlsGetValue(state->tlsIndex) ;
01546 if (threadState) {
01547 vl_thread_specific_state_delete (threadState) ;
01548 }
01549 #endif
01550 break;
01551
01552 case DLL_PROCESS_DETACH:
01553
01554 vl_destructor () ;
01555 break;
01556 }
01557 return TRUE ;
01558 }
01559 #endif
01560
01561
01562
01563
01564
01566 static void
01567 vl_constructor (void)
01568 {
01569 VlState * state ;
01570 #if defined(DEBUG)
01571 printf("VLFeat DEBUG: constructor begins.\n") ;
01572 #endif
01573
01574 state = vl_get_state() ;
01575
01576 #if ! defined(VL_DISABLE_THREADS)
01577 #if defined(DEBUG)
01578 printf("VLFeat DEBUG: constructing thread specific state.\n") ;
01579 #endif
01580 #if defined(VL_THREADS_POSIX)
01581 {
01582 typedef void (*destructorType)(void * );
01583 pthread_key_create (&state->threadKey,
01584 (destructorType)
01585 vl_thread_specific_state_delete) ;
01586 pthread_mutex_init (&state->mutex, NULL) ;
01587 pthread_cond_init (&state->mutexCondition, NULL) ;
01588 }
01589 #elif defined(VL_THREADS_WIN)
01590 InitializeCriticalSection (&state->mutex) ;
01591 state->tlsIndex = TlsAlloc () ;
01592 #endif
01593 #else
01594
01595
01596 #if defined(DEBUG)
01597 printf("VLFeat DEBUG: constructing the generic thread state instance (threading support disabled).\n") ;
01598 #endif
01599 vl_get_state()->threadState = vl_thread_specific_state_new() ;
01600 #endif
01601
01602 state->malloc_func = malloc ;
01603 state->realloc_func = realloc ;
01604 state->calloc_func = calloc ;
01605 state->free_func = free ;
01606 state->printf_func = printf ;
01607
01608
01609 #if defined(VL_ARCH_IX86) || defined(VL_ARCH_X64) || defined(VL_ARCH_IA64)
01610 _vl_x86cpu_info_init (&state->cpuInfo) ;
01611 #endif
01612
01613
01614 #if defined(VL_OS_WIN)
01615 {
01616 SYSTEM_INFO info;
01617 GetSystemInfo (&info) ;
01618 state->numCPUs = info.dwNumberOfProcessors ;
01619 }
01620 #elif defined(VL_OS_MACOSX) || defined(VL_OS_LINUX)
01621 state->numCPUs = sysconf(_SC_NPROCESSORS_ONLN) ;
01622 #else
01623 state->numCPUs = 1 ;
01624 #endif
01625 state->simdEnabled = VL_TRUE ;
01626
01627
01628 #if defined(_OPENMP)
01629 state->numThreads = omp_get_max_threads() ;
01630 #else
01631 state->numThreads = 1 ;
01632 #endif
01633
01634 #if defined(DEBUG)
01635 printf("VLFeat DEBUG: constructor ends.\n") ;
01636 #endif
01637 }
01638
01640 static void
01641 vl_destructor ()
01642 {
01643 VlState * state ;
01644 #if defined(DEBUG)
01645 printf("VLFeat DEBUG: destructor begins.\n") ;
01646 #endif
01647
01648 state = vl_get_state() ;
01649
01650 #if ! defined(VL_DISABLE_THREADS)
01651 #if defined(DEBUG)
01652 printf("VLFeat DEBUG: destroying a thread specific state instance.\n") ;
01653 #endif
01654 #if defined(VL_THREADS_POSIX)
01655 {
01656
01657
01658
01659
01660
01661
01662 VlThreadState * threadState =
01663 pthread_getspecific(state->threadKey) ;
01664 if (threadState) {
01665 vl_thread_specific_state_delete (threadState) ;
01666 pthread_setspecific(state->threadKey, NULL) ;
01667 }
01668 }
01669 pthread_cond_destroy (&state->mutexCondition) ;
01670 pthread_mutex_destroy (&state->mutex) ;
01671 pthread_key_delete (state->threadKey) ;
01672 #elif defined(VL_THREADS_WIN)
01673 {
01674
01675
01676
01677
01678
01679
01680 VlThreadState * threadState =
01681 TlsGetValue(state->tlsIndex) ;
01682 if (threadState) {
01683 vl_thread_specific_state_delete (threadState) ;
01684 TlsSetValue(state->tlsIndex, NULL) ;
01685 }
01686 }
01687 TlsFree (state->tlsIndex) ;
01688 DeleteCriticalSection (&state->mutex) ;
01689 #endif
01690 #else
01691 #if defined(DEBUG)
01692 printf("VLFeat DEBUG: destroying the generic thread state instance (threading support disabled).\n") ;
01693 #endif
01694 vl_thread_specific_state_delete(vl_get_state()->threadState) ;
01695 #endif
01696
01697 #if defined(DEBUG)
01698 printf("VLFeat DEBUG: destructor ends.\n") ;
01699 #endif
01700 }