generic.c
Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
00008 Copyright (C) 2013 Andrea Vedaldi.
00009 All rights reserved.
00010 
00011 This file is part of the VLFeat library and is made available under
00012 the terms of the BSD license (see the COPYING file).
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 /*                                         Global and thread states */
00796 /* ---------------------------------------------------------------- */
00797 
00798 /* Thread state */
00799 typedef struct _VlThreadState
00800 {
00801   /* errors */
00802   int lastError ;
00803   char lastErrorMessage [VL_ERR_MSG_LEN] ;
00804 
00805   /* random number generator */
00806   VlRand rand ;
00807 
00808   /* time */
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 /* Gobal state */
00818 typedef struct _VlState
00819 {
00820   /* The thread state uses either a mutex (POSIX)
00821     or a critical section (Win) */
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 /* VL_DISABLE_THREADS */
00836 
00837   /* Configurable functions */
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 /* Global state instance */
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   /* OpenMP version >= 3.0 */
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   //return (memalign)(32,n) ;
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 /*                    Library construction and destruction routines */
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 /*                                        DLL entry and exit points */
01509 /* ---------------------------------------------------------------- */
01510 /* A constructor and a destructor must be called to initialize or dispose of VLFeat
01511  * state when the DLL is loaded or unloaded. This is obtained
01512  * in different ways depending on the operating system.
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,  // handle to DLL module
01526     DWORD fdwReason,     // reason for calling function
01527     LPVOID lpReserved )  // reserved
01528 {
01529   VlState * state ;
01530   VlThreadState * threadState ;
01531   switch (fdwReason) {
01532     case DLL_PROCESS_ATTACH:
01533       /* Initialize once for each new process */
01534       vl_constructor () ;
01535       break ;
01536 
01537     case DLL_THREAD_ATTACH:
01538       /* Do thread-specific initialization */
01539       break ;
01540 
01541     case DLL_THREAD_DETACH:
01542       /* Do thread-specific cleanup */
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       /* Perform any necessary cleanup */
01554       vl_destructor () ;
01555       break;
01556     }
01557     return TRUE ; /* Successful DLL_PROCESS_ATTACH */
01558 }
01559 #endif /* VL_OS_WIN */
01560 
01561 /* ---------------------------------------------------------------- */
01562 /*                               Library constructor and destructor */
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 /* threading support disabled */
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   /* on x86 platforms read the CPUID register */
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   /* get the number of CPUs */
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   /* get the number of (OpenMP) threads used by the library */
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     /* Delete the thread state of this thread as the
01657        destructor is not called by pthread_key_delete or after
01658        the key is deleted. When the library
01659        is unloaded, this thread should also be the last one
01660        using the library, so this is fine.
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     /* Delete the thread state of this thread as the
01675        destructor is not called by pthread_key_delete or after
01676        the key is deleted. When the library
01677        is unloaded, this thread should also be the last one
01678        using the library, so this is fine.
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 }


libvlfeat
Author(s): Andrea Vedaldi
autogenerated on Thu Jun 6 2019 20:25:51