/ Changes On Branch winMutex
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch winMutex Excluding Merge-Ins

This is equivalent to a diff from 8b651d4d to 08c9a4ea

2014-07-29
19:54
Enhancements and updates to the Win32 mutex subsystem. (check-in: ca9868cd user: mistachkin tags: trunk)
18:03
Merge updates from trunk. (Closed-Leaf check-in: 08c9a4ea user: mistachkin tags: winMutex)
14:16
Merge the R-Tree fix and the new SQLITE_TESTCTRL_ISINIT test control from trunk. (check-in: b2f7eb3c user: drh tags: threads)
14:09
Add the SQLITE_TESTCTRL_ISINIT file control. (check-in: 8b651d4d user: drh tags: trunk)
11:54
Have calls to the xFilter() method of rtree virtual tables ensure that cursor is initialized before proceeding. Fix for [d2889096e7bdeac]. (check-in: 8cc41b0b user: dan tags: trunk)
05:49
Enhancements and updates to the Win32 mutex subsystem. (check-in: 18984c32 user: mistachkin tags: winMutex)

Changes to src/main.c.

  1052   1052     }
  1053   1053   }
  1054   1054   
  1055   1055   /*
  1056   1056   ** Return a static string containing the name corresponding to the error code
  1057   1057   ** specified in the argument.
  1058   1058   */
  1059         -#if defined(SQLITE_TEST)
         1059  +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  1060   1060   const char *sqlite3ErrName(int rc){
  1061   1061     const char *zName = 0;
  1062   1062     int i, origRc = rc;
  1063   1063     for(i=0; i<2 && zName==0; i++, rc &= 0xff){
  1064   1064       switch( rc ){
  1065   1065         case SQLITE_OK:                 zName = "SQLITE_OK";                break;
  1066   1066         case SQLITE_ERROR:              zName = "SQLITE_ERROR";             break;

Changes to src/mutex_w32.c.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** This file contains the C functions that implement mutexes for win32
           12  +** This file contains the C functions that implement mutexes for Win32.
    13     13   */
    14     14   #include "sqliteInt.h"
    15     15   
    16     16   #if SQLITE_OS_WIN
           17  +/*
           18  +** Include code that is common to all os_*.c files
           19  +*/
           20  +#include "os_common.h"
           21  +
    17     22   /*
    18     23   ** Include the header file for the Windows VFS.
    19     24   */
    20     25   #include "os_win.h"
    21     26   #endif
    22     27   
    23     28   /*
    24     29   ** The code in this file is only used if we are compiling multithreaded
    25         -** on a win32 system.
           30  +** on a Win32 system.
    26     31   */
    27     32   #ifdef SQLITE_MUTEX_W32
    28     33   
    29     34   /*
    30     35   ** Each recursive mutex is an instance of the following structure.
    31     36   */
    32     37   struct sqlite3_mutex {
    33     38     CRITICAL_SECTION mutex;    /* Mutex controlling the lock */
    34     39     int id;                    /* Mutex type */
    35     40   #ifdef SQLITE_DEBUG
    36     41     volatile int nRef;         /* Number of enterances */
    37     42     volatile DWORD owner;      /* Thread holding this mutex */
    38         -  int trace;                 /* True to trace changes */
           43  +  volatile int trace;        /* True to trace changes */
    39     44   #endif
    40     45   };
    41         -#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
    42         -#ifdef SQLITE_DEBUG
    43         -#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
    44         -#else
    45         -#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
    46         -#endif
    47     46   
    48     47   /*
    49         -** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
    50         -** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
    51         -**
    52         -** Here is an interesting observation:  Win95, Win98, and WinME lack
    53         -** the LockFileEx() API.  But we can still statically link against that
    54         -** API as long as we don't call it win running Win95/98/ME.  A call to
    55         -** this routine is used to determine if the host is Win95/98/ME or
    56         -** WinNT/2K/XP so that we will know whether or not we can safely call
    57         -** the LockFileEx() API.
    58         -**
    59         -** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
    60         -** which is only available if your application was compiled with 
    61         -** _WIN32_WINNT defined to a value >= 0x0400.  Currently, the only
    62         -** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef 
    63         -** this out as well.
           48  +** These are the initializer values used when declaring a "static" mutex
           49  +** on Win32.  It should be noted that all mutexes require initialization
           50  +** on the Win32 platform.
    64     51   */
    65         -#if 0
    66         -#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
    67         -# define mutexIsNT()  (1)
           52  +#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
           53  +
           54  +#ifdef SQLITE_DEBUG
           55  +#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \
           56  +                                    0L, (DWORD)0, 0 }
    68     57   #else
    69         -  static int mutexIsNT(void){
    70         -    static int osType = 0;
    71         -    if( osType==0 ){
    72         -      OSVERSIONINFO sInfo;
    73         -      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
    74         -      GetVersionEx(&sInfo);
    75         -      osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
    76         -    }
    77         -    return osType==2;
    78         -  }
    79         -#endif /* SQLITE_OS_WINCE || SQLITE_OS_WINRT */
           58  +#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
    80     59   #endif
    81     60   
    82     61   #ifdef SQLITE_DEBUG
    83     62   /*
    84     63   ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
    85     64   ** intended for use only inside assert() statements.
    86     65   */
    87     66   static int winMutexHeld(sqlite3_mutex *p){
    88     67     return p->nRef!=0 && p->owner==GetCurrentThreadId();
    89     68   }
           69  +
    90     70   static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
    91     71     return p->nRef==0 || p->owner!=tid;
    92     72   }
           73  +
    93     74   static int winMutexNotheld(sqlite3_mutex *p){
    94         -  DWORD tid = GetCurrentThreadId(); 
           75  +  DWORD tid = GetCurrentThreadId();
    95     76     return winMutexNotheld2(p, tid);
    96     77   }
    97     78   #endif
    98         -
    99     79   
   100     80   /*
   101     81   ** Initialize and deinitialize the mutex subsystem.
   102     82   */
   103     83   static sqlite3_mutex winMutex_staticMutexes[6] = {
   104     84     SQLITE3_MUTEX_INITIALIZER,
   105     85     SQLITE3_MUTEX_INITIALIZER,
   106     86     SQLITE3_MUTEX_INITIALIZER,
   107     87     SQLITE3_MUTEX_INITIALIZER,
   108     88     SQLITE3_MUTEX_INITIALIZER,
   109     89     SQLITE3_MUTEX_INITIALIZER
   110     90   };
           91  +
   111     92   static int winMutex_isInit = 0;
   112         -/* As winMutexInit() and winMutexEnd() are called as part
   113         -** of the sqlite3_initialize and sqlite3_shutdown()
   114         -** processing, the "interlocked" magic is probably not
   115         -** strictly necessary.
           93  +
           94  +/* As winMutexInit() and winMutexEnd() are called as part of the
           95  +** sqlite3_initialize() and sqlite3_shutdown() processing, the
           96  +** "interlocked" magic used in this section may not strictly
           97  +** necessary.
   116     98   */
   117     99   static LONG winMutex_lock = 0;
   118    100   
          101  +int sqlite3_win32_is_nt(void); /* os_win.c */
   119    102   void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
   120    103   
   121         -static int winMutexInit(void){ 
          104  +static int winMutexInit(void){
   122    105     /* The first to increment to 1 does actual initialization */
   123    106     if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
   124    107       int i;
   125    108       for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
   126    109   #if SQLITE_OS_WINRT
   127    110         InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0);
   128    111   #else
   129    112         InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
   130    113   #endif
   131    114       }
   132    115       winMutex_isInit = 1;
   133    116     }else{
   134         -    /* Someone else is in the process of initing the static mutexes */
          117  +    /* Another thread is (in the process of) initializing the static
          118  +    ** mutexes */
   135    119       while( !winMutex_isInit ){
   136    120         sqlite3_win32_sleep(1);
   137    121       }
   138    122     }
   139         -  return SQLITE_OK; 
          123  +  return SQLITE_OK;
   140    124   }
   141    125   
   142         -static int winMutexEnd(void){ 
   143         -  /* The first to decrement to 0 does actual shutdown 
          126  +static int winMutexEnd(void){
          127  +  /* The first to decrement to 0 does actual shutdown
   144    128     ** (which should be the last to shutdown.) */
   145    129     if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
   146    130       if( winMutex_isInit==1 ){
   147    131         int i;
   148    132         for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
   149    133           DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
   150    134         }
   151    135         winMutex_isInit = 0;
   152    136       }
   153    137     }
   154         -  return SQLITE_OK; 
          138  +  return SQLITE_OK;
   155    139   }
   156    140   
   157    141   /*
   158    142   ** The sqlite3_mutex_alloc() routine allocates a new
   159    143   ** mutex and returns a pointer to it.  If it returns NULL
   160    144   ** that means that a mutex could not be allocated.  SQLite
   161    145   ** will unwind its stack and return an error.  The argument
................................................................................
   188    172   ** may add additional static mutexes.  Static mutexes are for internal
   189    173   ** use by SQLite only.  Applications that use SQLite mutexes should
   190    174   ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
   191    175   ** SQLITE_MUTEX_RECURSIVE.
   192    176   **
   193    177   ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
   194    178   ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
   195         -** returns a different mutex on every call.  But for the static 
          179  +** returns a different mutex on every call.  But for the static
   196    180   ** mutex types, the same mutex is returned on every call that has
   197    181   ** the same type number.
   198    182   */
   199    183   static sqlite3_mutex *winMutexAlloc(int iType){
   200    184     sqlite3_mutex *p;
   201    185   
   202    186     switch( iType ){
   203    187       case SQLITE_MUTEX_FAST:
   204    188       case SQLITE_MUTEX_RECURSIVE: {
   205    189         p = sqlite3MallocZero( sizeof(*p) );
   206         -      if( p ){  
          190  +      if( p ){
   207    191   #ifdef SQLITE_DEBUG
   208    192           p->id = iType;
          193  +#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC
          194  +        p->trace = 1;
          195  +#endif
   209    196   #endif
   210    197   #if SQLITE_OS_WINRT
   211    198           InitializeCriticalSectionEx(&p->mutex, 0, 0);
   212    199   #else
   213    200           InitializeCriticalSection(&p->mutex);
   214    201   #endif
   215    202         }
   216    203         break;
   217    204       }
   218    205       default: {
   219         -      assert( winMutex_isInit==1 );
   220    206         assert( iType-2 >= 0 );
   221    207         assert( iType-2 < ArraySize(winMutex_staticMutexes) );
          208  +      assert( winMutex_isInit==1 );
   222    209         p = &winMutex_staticMutexes[iType-2];
   223    210   #ifdef SQLITE_DEBUG
   224    211         p->id = iType;
          212  +#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
          213  +      p->trace = 1;
          214  +#endif
   225    215   #endif
   226    216         break;
   227    217       }
   228    218     }
   229    219     return p;
   230    220   }
   231    221   
................................................................................
   233    223   /*
   234    224   ** This routine deallocates a previously
   235    225   ** allocated mutex.  SQLite is careful to deallocate every
   236    226   ** mutex that it allocates.
   237    227   */
   238    228   static void winMutexFree(sqlite3_mutex *p){
   239    229     assert( p );
          230  +#ifdef SQLITE_DEBUG
   240    231     assert( p->nRef==0 && p->owner==0 );
   241    232     assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
          233  +#endif
   242    234     DeleteCriticalSection(&p->mutex);
   243    235     sqlite3_free(p);
   244    236   }
   245    237   
   246    238   /*
   247    239   ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
   248    240   ** to enter a mutex.  If another thread is already within the mutex,
................................................................................
   251    243   ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
   252    244   ** be entered multiple times by the same thread.  In such cases the,
   253    245   ** mutex must be exited an equal number of times before another thread
   254    246   ** can enter.  If the same thread tries to enter any other kind of mutex
   255    247   ** more than once, the behavior is undefined.
   256    248   */
   257    249   static void winMutexEnter(sqlite3_mutex *p){
          250  +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
          251  +  DWORD tid = GetCurrentThreadId();
          252  +#endif
   258    253   #ifdef SQLITE_DEBUG
   259         -  DWORD tid = GetCurrentThreadId(); 
          254  +  assert( p );
   260    255     assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
          256  +#else
          257  +  assert( p );
   261    258   #endif
   262    259     EnterCriticalSection(&p->mutex);
   263    260   #ifdef SQLITE_DEBUG
   264    261     assert( p->nRef>0 || p->owner==0 );
   265         -  p->owner = tid; 
          262  +  p->owner = tid;
   266    263     p->nRef++;
   267    264     if( p->trace ){
   268         -    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
          265  +    OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
          266  +             tid, p, p->trace, p->nRef));
   269    267     }
   270    268   #endif
   271    269   }
          270  +
   272    271   static int winMutexTry(sqlite3_mutex *p){
   273         -#ifndef NDEBUG
   274         -  DWORD tid = GetCurrentThreadId(); 
          272  +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
          273  +  DWORD tid = GetCurrentThreadId();
   275    274   #endif
   276    275     int rc = SQLITE_BUSY;
          276  +  assert( p );
   277    277     assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
   278    278     /*
   279    279     ** The sqlite3_mutex_try() routine is very rarely used, and when it
   280    280     ** is used it is merely an optimization.  So it is OK for it to always
   281         -  ** fail.  
          281  +  ** fail.
   282    282     **
   283    283     ** The TryEnterCriticalSection() interface is only available on WinNT.
   284    284     ** And some windows compilers complain if you try to use it without
   285    285     ** first doing some #defines that prevent SQLite from building on Win98.
   286    286     ** For that reason, we will omit this optimization for now.  See
   287    287     ** ticket #2685.
   288    288     */
   289         -#if 0
   290         -  if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
          289  +#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400
          290  +  if( sqlite3_win32_is_nt() && TryEnterCriticalSection(&p->mutex) ){
          291  +#ifdef SQLITE_DEBUG
   291    292       p->owner = tid;
   292    293       p->nRef++;
          294  +#endif
   293    295       rc = SQLITE_OK;
   294    296     }
   295    297   #else
   296    298     UNUSED_PARAMETER(p);
   297    299   #endif
   298    300   #ifdef SQLITE_DEBUG
   299         -  if( rc==SQLITE_OK && p->trace ){
   300         -    printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
          301  +  if( p->trace ){
          302  +    OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
          303  +             tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
   301    304     }
   302    305   #endif
   303    306     return rc;
   304    307   }
   305    308   
   306    309   /*
   307    310   ** The sqlite3_mutex_leave() routine exits a mutex that was
   308    311   ** previously entered by the same thread.  The behavior
   309    312   ** is undefined if the mutex is not currently entered or
   310    313   ** is not currently allocated.  SQLite will never do either.
   311    314   */
   312    315   static void winMutexLeave(sqlite3_mutex *p){
   313         -#ifndef NDEBUG
          316  +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
   314    317     DWORD tid = GetCurrentThreadId();
          318  +#endif
          319  +  assert( p );
          320  +#ifdef SQLITE_DEBUG
   315    321     assert( p->nRef>0 );
   316    322     assert( p->owner==tid );
   317    323     p->nRef--;
   318    324     if( p->nRef==0 ) p->owner = 0;
   319    325     assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
   320    326   #endif
   321    327     LeaveCriticalSection(&p->mutex);
   322    328   #ifdef SQLITE_DEBUG
   323    329     if( p->trace ){
   324         -    printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
          330  +    OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
          331  +             tid, p, p->trace, p->nRef));
   325    332     }
   326    333   #endif
   327    334   }
   328    335   
   329    336   sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
   330    337     static const sqlite3_mutex_methods sMutex = {
   331    338       winMutexInit,
................................................................................
   339    346       winMutexHeld,
   340    347       winMutexNotheld
   341    348   #else
   342    349       0,
   343    350       0
   344    351   #endif
   345    352     };
   346         -
   347    353     return &sMutex;
   348    354   }
          355  +
   349    356   #endif /* SQLITE_MUTEX_W32 */

Changes to src/os_win.c.

  1294   1294   #if !defined(SQLITE_WIN32_GETVERSIONEX) || !SQLITE_WIN32_GETVERSIONEX
  1295   1295   # define osIsNT()  (1)
  1296   1296   #elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
  1297   1297   # define osIsNT()  (1)
  1298   1298   #elif !defined(SQLITE_WIN32_HAS_WIDE)
  1299   1299   # define osIsNT()  (0)
  1300   1300   #else
  1301         -  static int osIsNT(void){
  1302         -    if( sqlite3_os_type==0 ){
         1301  +# define osIsNT()  (sqlite3_win32_is_nt())
         1302  +#endif
         1303  +
         1304  +/*
         1305  +** This function determines if the machine is running a version of Windows
         1306  +** based on the NT kernel.
         1307  +*/
         1308  +int sqlite3_win32_is_nt(void){
         1309  +  if( sqlite3_os_type==0 ){
  1303   1310   #if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
  1304         -      OSVERSIONINFOW sInfo;
  1305         -      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
  1306         -      osGetVersionExW(&sInfo);
         1311  +    OSVERSIONINFOW sInfo;
         1312  +    sInfo.dwOSVersionInfoSize = sizeof(sInfo);
         1313  +    osGetVersionExW(&sInfo);
  1307   1314   #else
  1308         -      OSVERSIONINFOA sInfo;
  1309         -      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
  1310         -      osGetVersionExA(&sInfo);
         1315  +    OSVERSIONINFOA sInfo;
         1316  +    sInfo.dwOSVersionInfoSize = sizeof(sInfo);
         1317  +    osGetVersionExA(&sInfo);
  1311   1318   #endif
  1312         -      sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
  1313         -    }
  1314         -    return sqlite3_os_type==2;
         1319  +    sqlite3_os_type = (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1;
  1315   1320     }
  1316         -#endif
         1321  +  return (sqlite3_os_type == 2);
         1322  +}
  1317   1323   
  1318   1324   #ifdef SQLITE_WIN32_MALLOC
  1319   1325   /*
  1320   1326   ** Allocate nBytes of memory.
  1321   1327   */
  1322   1328   static void *winMemMalloc(int nBytes){
  1323   1329     HANDLE hHeap;