persistentstorage/sqlite3api/SQLite/mutex_w32.c
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 /*
       
     2 ** 2007 August 14
       
     3 **
       
     4 ** The author disclaims copyright to this source code.  In place of
       
     5 ** a legal notice, here is a blessing:
       
     6 **
       
     7 **    May you do good and not evil.
       
     8 **    May you find forgiveness for yourself and forgive others.
       
     9 **    May you share freely, never taking more than you give.
       
    10 **
       
    11 *************************************************************************
       
    12 ** This file contains the C functions that implement mutexes for win32
       
    13 **
       
    14 ** $Id: mutex_w32.c,v 1.11 2008/06/26 10:41:19 danielk1977 Exp $
       
    15 */
       
    16 #include "sqliteInt.h"
       
    17 
       
    18 /*
       
    19 ** The code in this file is only used if we are compiling multithreaded
       
    20 ** on a win32 system.
       
    21 */
       
    22 #ifdef SQLITE_MUTEX_W32
       
    23 
       
    24 /*
       
    25 ** Each recursive mutex is an instance of the following structure.
       
    26 */
       
    27 struct sqlite3_mutex {
       
    28   CRITICAL_SECTION mutex;    /* Mutex controlling the lock */
       
    29   int id;                    /* Mutex type */
       
    30   int nRef;                  /* Number of enterances */
       
    31   DWORD owner;               /* Thread holding this mutex */
       
    32 };
       
    33 
       
    34 /*
       
    35 ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
       
    36 ** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
       
    37 **
       
    38 ** Here is an interesting observation:  Win95, Win98, and WinME lack
       
    39 ** the LockFileEx() API.  But we can still statically link against that
       
    40 ** API as long as we don't call it win running Win95/98/ME.  A call to
       
    41 ** this routine is used to determine if the host is Win95/98/ME or
       
    42 ** WinNT/2K/XP so that we will know whether or not we can safely call
       
    43 ** the LockFileEx() API.
       
    44 */
       
    45 #if SQLITE_OS_WINCE
       
    46 # define mutexIsNT()  (1)
       
    47 #else
       
    48   static int mutexIsNT(void){
       
    49     static int osType = 0;
       
    50     if( osType==0 ){
       
    51       OSVERSIONINFO sInfo;
       
    52       sInfo.dwOSVersionInfoSize = sizeof(sInfo);
       
    53       GetVersionEx(&sInfo);
       
    54       osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
       
    55     }
       
    56     return osType==2;
       
    57   }
       
    58 #endif /* SQLITE_OS_WINCE */
       
    59 
       
    60 
       
    61 #ifdef SQLITE_DEBUG
       
    62 /*
       
    63 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
       
    64 ** intended for use only inside assert() statements.
       
    65 */
       
    66 static int winMutexHeld(sqlite3_mutex *p){
       
    67   return p->nRef!=0 && p->owner==GetCurrentThreadId();
       
    68 }
       
    69 static int winMutexNotheld(sqlite3_mutex *p){
       
    70   return p->nRef==0 || p->owner!=GetCurrentThreadId();
       
    71 }
       
    72 #endif
       
    73 
       
    74 
       
    75 /*
       
    76 ** Initialize and deinitialize the mutex subsystem.
       
    77 */
       
    78 static int winMutexInit(void){ return SQLITE_OK; }
       
    79 static int winMutexEnd(void){ return SQLITE_OK; }
       
    80 
       
    81 /*
       
    82 ** The sqlite3_mutex_alloc() routine allocates a new
       
    83 ** mutex and returns a pointer to it.  If it returns NULL
       
    84 ** that means that a mutex could not be allocated.  SQLite
       
    85 ** will unwind its stack and return an error.  The argument
       
    86 ** to sqlite3_mutex_alloc() is one of these integer constants:
       
    87 **
       
    88 ** <ul>
       
    89 ** <li>  SQLITE_MUTEX_FAST               0
       
    90 ** <li>  SQLITE_MUTEX_RECURSIVE          1
       
    91 ** <li>  SQLITE_MUTEX_STATIC_MASTER      2
       
    92 ** <li>  SQLITE_MUTEX_STATIC_MEM         3
       
    93 ** <li>  SQLITE_MUTEX_STATIC_PRNG        4
       
    94 ** </ul>
       
    95 **
       
    96 ** The first two constants cause sqlite3_mutex_alloc() to create
       
    97 ** a new mutex.  The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
       
    98 ** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
       
    99 ** The mutex implementation does not need to make a distinction
       
   100 ** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
       
   101 ** not want to.  But SQLite will only request a recursive mutex in
       
   102 ** cases where it really needs one.  If a faster non-recursive mutex
       
   103 ** implementation is available on the host platform, the mutex subsystem
       
   104 ** might return such a mutex in response to SQLITE_MUTEX_FAST.
       
   105 **
       
   106 ** The other allowed parameters to sqlite3_mutex_alloc() each return
       
   107 ** a pointer to a static preexisting mutex.  Three static mutexes are
       
   108 ** used by the current version of SQLite.  Future versions of SQLite
       
   109 ** may add additional static mutexes.  Static mutexes are for internal
       
   110 ** use by SQLite only.  Applications that use SQLite mutexes should
       
   111 ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
       
   112 ** SQLITE_MUTEX_RECURSIVE.
       
   113 **
       
   114 ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
       
   115 ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
       
   116 ** returns a different mutex on every call.  But for the static 
       
   117 ** mutex types, the same mutex is returned on every call that has
       
   118 ** the same type number.
       
   119 */
       
   120 static sqlite3_mutex *winMutexAlloc(int iType){
       
   121   sqlite3_mutex *p;
       
   122 
       
   123   switch( iType ){
       
   124     case SQLITE_MUTEX_FAST:
       
   125     case SQLITE_MUTEX_RECURSIVE: {
       
   126       p = sqlite3MallocZero( sizeof(*p) );
       
   127       if( p ){
       
   128         p->id = iType;
       
   129         InitializeCriticalSection(&p->mutex);
       
   130       }
       
   131       break;
       
   132     }
       
   133     default: {
       
   134       static sqlite3_mutex staticMutexes[6];
       
   135       static int isInit = 0;
       
   136       while( !isInit ){
       
   137         static long lock = 0;
       
   138         if( InterlockedIncrement(&lock)==1 ){
       
   139           int i;
       
   140           for(i=0; i<sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++){
       
   141             InitializeCriticalSection(&staticMutexes[i].mutex);
       
   142           }
       
   143           isInit = 1;
       
   144         }else{
       
   145           Sleep(1);
       
   146         }
       
   147       }
       
   148       assert( iType-2 >= 0 );
       
   149       assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
       
   150       p = &staticMutexes[iType-2];
       
   151       p->id = iType;
       
   152       break;
       
   153     }
       
   154   }
       
   155   return p;
       
   156 }
       
   157 
       
   158 
       
   159 /*
       
   160 ** This routine deallocates a previously
       
   161 ** allocated mutex.  SQLite is careful to deallocate every
       
   162 ** mutex that it allocates.
       
   163 */
       
   164 static void winMutexFree(sqlite3_mutex *p){
       
   165   assert( p );
       
   166   assert( p->nRef==0 );
       
   167   assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
       
   168   DeleteCriticalSection(&p->mutex);
       
   169   sqlite3_free(p);
       
   170 }
       
   171 
       
   172 /*
       
   173 ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
       
   174 ** to enter a mutex.  If another thread is already within the mutex,
       
   175 ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
       
   176 ** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
       
   177 ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
       
   178 ** be entered multiple times by the same thread.  In such cases the,
       
   179 ** mutex must be exited an equal number of times before another thread
       
   180 ** can enter.  If the same thread tries to enter any other kind of mutex
       
   181 ** more than once, the behavior is undefined.
       
   182 */
       
   183 static void winMutexEnter(sqlite3_mutex *p){
       
   184   assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
       
   185   EnterCriticalSection(&p->mutex);
       
   186   p->owner = GetCurrentThreadId(); 
       
   187   p->nRef++;
       
   188 }
       
   189 static int winMutexTry(sqlite3_mutex *p){
       
   190   int rc = SQLITE_BUSY;
       
   191   assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
       
   192   /*
       
   193   ** The sqlite3_mutex_try() routine is very rarely used, and when it
       
   194   ** is used it is merely an optimization.  So it is OK for it to always
       
   195   ** fail.  
       
   196   **
       
   197   ** The TryEnterCriticalSection() interface is only available on WinNT.
       
   198   ** And some windows compilers complain if you try to use it without
       
   199   ** first doing some #defines that prevent SQLite from building on Win98.
       
   200   ** For that reason, we will omit this optimization for now.  See
       
   201   ** ticket #2685.
       
   202   */
       
   203 #if 0
       
   204   if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
       
   205     p->owner = GetCurrentThreadId();
       
   206     p->nRef++;
       
   207     rc = SQLITE_OK;
       
   208   }
       
   209 #endif
       
   210   return rc;
       
   211 }
       
   212 
       
   213 /*
       
   214 ** The sqlite3_mutex_leave() routine exits a mutex that was
       
   215 ** previously entered by the same thread.  The behavior
       
   216 ** is undefined if the mutex is not currently entered or
       
   217 ** is not currently allocated.  SQLite will never do either.
       
   218 */
       
   219 static void winMutexLeave(sqlite3_mutex *p){
       
   220   assert( p->nRef>0 );
       
   221   assert( p->owner==GetCurrentThreadId() );
       
   222   p->nRef--;
       
   223   assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
       
   224   LeaveCriticalSection(&p->mutex);
       
   225 }
       
   226 
       
   227 sqlite3_mutex_methods *sqlite3DefaultMutex(void){
       
   228   static sqlite3_mutex_methods sMutex = {
       
   229     winMutexInit,
       
   230     winMutexEnd,
       
   231     winMutexAlloc,
       
   232     winMutexFree,
       
   233     winMutexEnter,
       
   234     winMutexTry,
       
   235     winMutexLeave,
       
   236 #ifdef SQLITE_DEBUG
       
   237     winMutexHeld,
       
   238     winMutexNotheld
       
   239 #endif
       
   240   };
       
   241 
       
   242   return &sMutex;
       
   243 }
       
   244 #endif /* SQLITE_MUTEX_W32 */