/ Check-in [1025873f]
Login

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

Overview
Comment:Enhance mutex testing to include APP and VFS static mutexes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1025873fdfd9e7e53094c48af1a79c60ae50ae97
User & Date: mistachkin 2015-07-03 23:11:36
References
2015-07-03
23:29
Correction to check-in [1025873fdf], tighten up the number of static test mutexes. check-in: 4e515897 user: mistachkin tags: trunk
Context
2015-07-03
23:12
Update clean target in MSVC makefile. check-in: e6c03e72 user: mistachkin tags: trunk
23:11
Enhance mutex testing to include APP and VFS static mutexes. check-in: 1025873f user: mistachkin tags: trunk
21:38
Add static mutexes for use by the built-in / third-party VFSs and use the built-in VFS mutex where appropriate. check-in: b202e2a1 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/test_mutex.c.

    15     15   #include "tcl.h"
    16     16   #include "sqlite3.h"
    17     17   #include "sqliteInt.h"
    18     18   #include <stdlib.h>
    19     19   #include <assert.h>
    20     20   #include <string.h>
    21     21   
           22  +#define MAX_MUTEXES (SQLITE_MUTEX_STATIC_VFS3+1)
           23  +
    22     24   /* defined in main.c */
    23     25   extern const char *sqlite3ErrName(int);
           26  +
           27  +static const char *aName[MAX_MUTEXES+1] = {
           28  +  "fast",        "recursive",   "static_master", "static_mem",
           29  +  "static_open", "static_prng", "static_lru",    "static_pmem",
           30  +  "static_app1", "static_app2", "static_app3",   "static_vfs1",
           31  +  "static_vfs2", "static_vfs3", 0
           32  +};
    24     33   
    25     34   /* A countable mutex */
    26     35   struct sqlite3_mutex {
    27     36     sqlite3_mutex *pReal;
    28     37     int eType;
    29     38   };
    30     39   
    31     40   /* State variables */
    32     41   static struct test_mutex_globals {
    33         -  int isInstalled;              /* True if installed */
    34         -  int disableInit;              /* True to cause sqlite3_initalize() to fail */
    35         -  int disableTry;               /* True to force sqlite3_mutex_try() to fail */
    36         -  int isInit;                   /* True if initialized */
    37         -  sqlite3_mutex_methods m;      /* Interface to "real" mutex system */
    38         -  int aCounter[8];              /* Number of grabs of each type of mutex */
    39         -  sqlite3_mutex aStatic[6];     /* The six static mutexes */
           42  +  int isInstalled;           /* True if installed */
           43  +  int disableInit;           /* True to cause sqlite3_initalize() to fail */
           44  +  int disableTry;            /* True to force sqlite3_mutex_try() to fail */
           45  +  int isInit;                /* True if initialized */
           46  +  sqlite3_mutex_methods m;   /* Interface to "real" mutex system */
           47  +  int aCounter[MAX_MUTEXES]; /* Number of grabs of each type of mutex */
           48  +  sqlite3_mutex aStatic[MAX_MUTEXES]; /* The static mutexes */
    40     49   } g = {0};
    41     50   
    42     51   /* Return true if the countable mutex is currently held */
    43     52   static int counterMutexHeld(sqlite3_mutex *p){
    44     53     return g.m.xMutexHeld(p->pReal);
    45     54   }
    46     55   
................................................................................
    74     83   ** Allocate a countable mutex
    75     84   */
    76     85   static sqlite3_mutex *counterMutexAlloc(int eType){
    77     86     sqlite3_mutex *pReal;
    78     87     sqlite3_mutex *pRet = 0;
    79     88   
    80     89     assert( g.isInit );
    81         -  assert(eType<8 && eType>=0);
           90  +  assert( eType>=SQLITE_MUTEX_FAST );
           91  +  assert( eType<=SQLITE_MUTEX_STATIC_VFS3 );
    82     92   
    83     93     pReal = g.m.xMutexAlloc(eType);
    84     94     if( !pReal ) return 0;
    85     95   
    86     96     if( eType==SQLITE_MUTEX_FAST || eType==SQLITE_MUTEX_RECURSIVE ){
    87     97       pRet = (sqlite3_mutex *)malloc(sizeof(sqlite3_mutex));
    88     98     }else{
    89         -    pRet = &g.aStatic[eType-2];
           99  +    int eStaticType = eType - (SQLITE_MUTEX_RECURSIVE + 1);
          100  +    assert( eStaticType>=0 );
          101  +    assert( eStaticType<MAX_MUTEXES );
          102  +    pRet = &g.aStatic[eStaticType];
    90    103     }
    91    104   
    92    105     pRet->eType = eType;
    93    106     pRet->pReal = pReal;
    94    107     return pRet;
    95    108   }
    96    109   
................................................................................
   106    119   }
   107    120   
   108    121   /*
   109    122   ** Enter a countable mutex.  Block until entry is safe.
   110    123   */
   111    124   static void counterMutexEnter(sqlite3_mutex *p){
   112    125     assert( g.isInit );
          126  +  assert( p->eType>=0 );
          127  +  assert( p->eType<MAX_MUTEXES );
   113    128     g.aCounter[p->eType]++;
   114    129     g.m.xMutexEnter(p->pReal);
   115    130   }
   116    131   
   117    132   /*
   118    133   ** Try to enter a mutex.  Return true on success.
   119    134   */
   120    135   static int counterMutexTry(sqlite3_mutex *p){
   121    136     assert( g.isInit );
          137  +  assert( p->eType>=0 );
          138  +  assert( p->eType<MAX_MUTEXES );
   122    139     g.aCounter[p->eType]++;
   123    140     if( g.disableTry ) return SQLITE_BUSY;
   124    141     return g.m.xMutexTry(p->pReal);
   125    142   }
   126    143   
   127    144   /* Leave a mutex
   128    145   */
................................................................................
   241    258     void * clientData,
   242    259     Tcl_Interp *interp,
   243    260     int objc,
   244    261     Tcl_Obj *CONST objv[]
   245    262   ){
   246    263     Tcl_Obj *pRet;
   247    264     int ii;
   248         -  char *aName[8] = {
   249         -    "fast",        "recursive",   "static_master", "static_mem", 
   250         -    "static_open", "static_prng", "static_lru",    "static_pmem"
   251         -  };
   252    265   
   253    266     if( objc!=1 ){
   254    267       Tcl_WrongNumArgs(interp, 1, objv, "");
   255    268       return TCL_ERROR;
   256    269     }
   257    270   
   258    271     pRet = Tcl_NewObj();
   259    272     Tcl_IncrRefCount(pRet);
   260         -  for(ii=0; ii<8; ii++){
          273  +  for(ii=0; ii<MAX_MUTEXES; ii++){
   261    274       Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(aName[ii], -1));
   262    275       Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(g.aCounter[ii]));
   263    276     }
   264    277     Tcl_SetObjResult(interp, pRet);
   265    278     Tcl_DecrRefCount(pRet);
   266    279   
   267    280     return TCL_OK;
................................................................................
   279    292     int ii;
   280    293   
   281    294     if( objc!=1 ){
   282    295       Tcl_WrongNumArgs(interp, 1, objv, "");
   283    296       return TCL_ERROR;
   284    297     }
   285    298   
   286         -  for(ii=0; ii<8; ii++){
          299  +  for(ii=0; ii<MAX_MUTEXES; ii++){
   287    300       g.aCounter[ii] = 0;
   288    301     }
   289    302     return TCL_OK;
   290    303   }
   291    304   
   292    305   /*
   293    306   ** Create and free a mutex.  Return the mutex pointer.  The pointer
................................................................................
   366    379       db = *((sqlite3 **)info.objClientData);
   367    380     }else{
   368    381       db = (sqlite3*)sqlite3TestTextToPtr(zCmd);
   369    382     }
   370    383     assert( db );
   371    384     return db;
   372    385   }
          386  +
          387  +static sqlite3_mutex *getStaticMutexPointer(
          388  +  Tcl_Interp *pInterp,
          389  +  Tcl_Obj *pObj
          390  +){
          391  +  int iMutex;
          392  +  if( Tcl_GetIndexFromObj(pInterp, pObj, aName, "mutex name", 0, &iMutex) ){
          393  +    return 0;
          394  +  }
          395  +  assert( iMutex!=SQLITE_MUTEX_FAST && iMutex!=SQLITE_MUTEX_RECURSIVE );
          396  +  return counterMutexAlloc(iMutex);
          397  +}
          398  +
          399  +static int test_enter_static_mutex(
          400  +  void * clientData,
          401  +  Tcl_Interp *interp,
          402  +  int objc,
          403  +  Tcl_Obj *CONST objv[]
          404  +){
          405  +  sqlite3_mutex *pMutex;
          406  +  if( objc!=2 ){
          407  +    Tcl_WrongNumArgs(interp, 1, objv, "NAME");
          408  +    return TCL_ERROR;
          409  +  }
          410  +  pMutex = getStaticMutexPointer(interp, objv[1]);
          411  +  if( !pMutex ){
          412  +    return TCL_ERROR;
          413  +  }
          414  +  sqlite3_mutex_enter(pMutex);
          415  +  return TCL_OK;
          416  +}
          417  +
          418  +static int test_leave_static_mutex(
          419  +  void * clientData,
          420  +  Tcl_Interp *interp,
          421  +  int objc,
          422  +  Tcl_Obj *CONST objv[]
          423  +){
          424  +  sqlite3_mutex *pMutex;
          425  +  if( objc!=2 ){
          426  +    Tcl_WrongNumArgs(interp, 1, objv, "NAME");
          427  +    return TCL_ERROR;
          428  +  }
          429  +  pMutex = getStaticMutexPointer(interp, objv[1]);
          430  +  if( !pMutex ){
          431  +    return TCL_ERROR;
          432  +  }
          433  +  sqlite3_mutex_leave(pMutex);
          434  +  return TCL_OK;
          435  +}
   373    436   
   374    437   static int test_enter_db_mutex(
   375    438     void * clientData,
   376    439     Tcl_Interp *interp,
   377    440     int objc,
   378    441     Tcl_Obj *CONST objv[]
   379    442   ){
................................................................................
   413    476     static struct {
   414    477       char *zName;
   415    478       Tcl_ObjCmdProc *xProc;
   416    479     } aCmd[] = {
   417    480       { "sqlite3_shutdown",        (Tcl_ObjCmdProc*)test_shutdown },
   418    481       { "sqlite3_initialize",      (Tcl_ObjCmdProc*)test_initialize },
   419    482       { "sqlite3_config",          (Tcl_ObjCmdProc*)test_config },
          483  +
          484  +    { "enter_static_mutex",      (Tcl_ObjCmdProc*)test_enter_static_mutex },
          485  +    { "leave_static_mutex",      (Tcl_ObjCmdProc*)test_leave_static_mutex },
   420    486   
   421    487       { "enter_db_mutex",          (Tcl_ObjCmdProc*)test_enter_db_mutex },
   422    488       { "leave_db_mutex",          (Tcl_ObjCmdProc*)test_leave_db_mutex },
   423    489   
   424    490       { "alloc_dealloc_mutex",     (Tcl_ObjCmdProc*)test_alloc_mutex },
   425    491       { "install_mutex_counters",  (Tcl_ObjCmdProc*)test_install_mutex_counters },
   426    492       { "read_mutex_counters",     (Tcl_ObjCmdProc*)test_read_mutex_counters },

Changes to test/mutex1.test.

    33     33       set var($name) $value
    34     34       incr var(total) $value
    35     35     }
    36     36   }
    37     37   
    38     38   #-------------------------------------------------------------------------
    39     39   # Tests mutex1-1.* test that sqlite3_config() returns SQLITE_MISUSE if
    40         -# is called at the wrong time. And that the first time sqlite3_initialize 
           40  +# is called at the wrong time. And that the first time sqlite3_initialize
    41     41   # is called it obtains the 'static_master' mutex 3 times and a recursive
    42         -# mutex (sqlite3Config.pInitMutex) twice. Subsequent calls are no-ops 
           42  +# mutex (sqlite3Config.pInitMutex) twice. Subsequent calls are no-ops
    43     43   # that do not require any mutexes.
    44     44   #
    45     45   do_test mutex1-1.0 {
    46     46     install_mutex_counters 1
    47     47   } {SQLITE_MISUSE}
    48     48   
    49     49   do_test mutex1-1.1 {
................................................................................
    98     98   #   * Single-threaded mode.
    99     99   #
   100    100   ifcapable threadsafe&&shared_cache {
   101    101     set enable_shared_cache [sqlite3_enable_shared_cache 1]
   102    102     foreach {mode mutexes} {
   103    103       singlethread {}
   104    104       multithread  {
   105         -      fast static_lru static_master static_mem static_open static_prng 
   106         -      static_pmem
          105  +      fast static_app1 static_app2 static_app3
          106  +      static_lru static_master static_mem static_open
          107  +      static_prng static_pmem static_vfs1 static_vfs2
          108  +      static_vfs3
   107    109       }
   108    110       serialized  {
   109         -      fast recursive static_lru static_master static_mem static_open 
   110         -      static_prng static_pmem
          111  +      fast recursive static_app1 static_app2
          112  +      static_app3 static_lru static_master static_mem
          113  +      static_open static_prng static_pmem static_vfs1
          114  +      static_vfs2 static_vfs3
   111    115       }
   112    116     } {
   113    117   
   114    118       do_test mutex1.2.$mode.1 {
   115    119         catch {db close}
   116    120         sqlite3_shutdown
   117    121         sqlite3_config $mode
................................................................................
   125    129         db eval {
   126    130           INSERT INTO abc VALUES(1, 2, 3);
   127    131         }
   128    132       } {}
   129    133       ifcapable !memorymanage {
   130    134         regsub { static_lru} $mutexes {} mutexes
   131    135       }
   132         -    do_test mutex1.2.$mode.3 {
          136  +    if {$mode ne "singlethread"} {
          137  +      do_test mutex1.2.$mode.3 {
          138  +        #
          139  +        # NOTE: Make sure all the app and vfs mutexes get used.
          140  +        #
          141  +        enter_static_mutex static_app1
          142  +        leave_static_mutex static_app1
          143  +        enter_static_mutex static_app2
          144  +        leave_static_mutex static_app2
          145  +        enter_static_mutex static_app3
          146  +        leave_static_mutex static_app3
          147  +        enter_static_mutex static_vfs1
          148  +        leave_static_mutex static_vfs1
          149  +        enter_static_mutex static_vfs2
          150  +        leave_static_mutex static_vfs2
          151  +        enter_static_mutex static_vfs3
          152  +        leave_static_mutex static_vfs3
          153  +      } {}
          154  +    }
          155  +    do_test mutex1.2.$mode.4 {
   133    156         mutex_counters counters
   134         -  
          157  +
   135    158         set res [list]
   136    159         foreach {key value} [array get counters] {
   137    160           if {$key ne "total" && $value > 0} {
   138    161             lappend res $key
   139    162           }
   140    163         }
   141    164         lsort $res