os/persistentdata/persistentstorage/sqlite3api/TEST/SRC/test_mutex.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
** 2008 June 18
sl@0
     3
**
sl@0
     4
** The author disclaims copyright to this source code.  In place of
sl@0
     5
** a legal notice, here is a blessing:
sl@0
     6
**
sl@0
     7
**    May you do good and not evil.
sl@0
     8
**    May you find forgiveness for yourself and forgive others.
sl@0
     9
**    May you share freely, never taking more than you give.
sl@0
    10
**
sl@0
    11
*************************************************************************
sl@0
    12
** 
sl@0
    13
** $Id: test_mutex.c,v 1.11 2008/07/19 13:43:24 danielk1977 Exp $
sl@0
    14
*/
sl@0
    15
sl@0
    16
#include "tcl.h"
sl@0
    17
#include "sqlite3.h"
sl@0
    18
#include "sqliteInt.h"
sl@0
    19
#include <stdlib.h>
sl@0
    20
#include <assert.h>
sl@0
    21
#include <string.h>
sl@0
    22
sl@0
    23
/* defined in test1.c */
sl@0
    24
const char *sqlite3TestErrorName(int);
sl@0
    25
sl@0
    26
/* A countable mutex */
sl@0
    27
struct sqlite3_mutex {
sl@0
    28
  sqlite3_mutex *pReal;
sl@0
    29
  int eType;
sl@0
    30
};
sl@0
    31
sl@0
    32
/* State variables */
sl@0
    33
static struct test_mutex_globals {
sl@0
    34
  int isInstalled;              /* True if installed */
sl@0
    35
  int disableInit;              /* True to cause sqlite3_initalize() to fail */
sl@0
    36
  int disableTry;               /* True to force sqlite3_mutex_try() to fail */
sl@0
    37
  int isInit;                   /* True if initialized */
sl@0
    38
  sqlite3_mutex_methods m;      /* Interface to "real" mutex system */
sl@0
    39
  int aCounter[8];              /* Number of grabs of each type of mutex */
sl@0
    40
  sqlite3_mutex aStatic[6];     /* The six static mutexes */
sl@0
    41
} g;
sl@0
    42
sl@0
    43
/* Return true if the countable mutex is currently held */
sl@0
    44
static int counterMutexHeld(sqlite3_mutex *p){
sl@0
    45
  return g.m.xMutexHeld(p->pReal);
sl@0
    46
}
sl@0
    47
sl@0
    48
/* Return true if the countable mutex is not currently held */
sl@0
    49
static int counterMutexNotheld(sqlite3_mutex *p){
sl@0
    50
  return g.m.xMutexNotheld(p->pReal);
sl@0
    51
}
sl@0
    52
sl@0
    53
/* Initialize the countable mutex interface
sl@0
    54
** Or, if g.disableInit is non-zero, then do not initialize but instead
sl@0
    55
** return the value of g.disableInit as the result code.  This can be used
sl@0
    56
** to simulate an initialization failure.
sl@0
    57
*/
sl@0
    58
static int counterMutexInit(void){ 
sl@0
    59
  int rc;
sl@0
    60
  if( g.disableInit ) return g.disableInit;
sl@0
    61
  rc = g.m.xMutexInit();
sl@0
    62
  g.isInit = 1;
sl@0
    63
  return rc;
sl@0
    64
}
sl@0
    65
sl@0
    66
/*
sl@0
    67
** Uninitialize the mutex subsystem
sl@0
    68
*/
sl@0
    69
static int counterMutexEnd(void){ 
sl@0
    70
  g.isInit = 0;
sl@0
    71
  return g.m.xMutexEnd();
sl@0
    72
}
sl@0
    73
sl@0
    74
/*
sl@0
    75
** Allocate a countable mutex
sl@0
    76
*/
sl@0
    77
static sqlite3_mutex *counterMutexAlloc(int eType){
sl@0
    78
  sqlite3_mutex *pReal;
sl@0
    79
  sqlite3_mutex *pRet = 0;
sl@0
    80
sl@0
    81
  assert( g.isInit );
sl@0
    82
  assert(eType<8 && eType>=0);
sl@0
    83
sl@0
    84
  pReal = g.m.xMutexAlloc(eType);
sl@0
    85
  if( !pReal ) return 0;
sl@0
    86
sl@0
    87
  if( eType==SQLITE_MUTEX_FAST || eType==SQLITE_MUTEX_RECURSIVE ){
sl@0
    88
    pRet = (sqlite3_mutex *)malloc(sizeof(sqlite3_mutex));
sl@0
    89
  }else{
sl@0
    90
    pRet = &g.aStatic[eType-2];
sl@0
    91
  }
sl@0
    92
sl@0
    93
  pRet->eType = eType;
sl@0
    94
  pRet->pReal = pReal;
sl@0
    95
  return pRet;
sl@0
    96
}
sl@0
    97
sl@0
    98
/*
sl@0
    99
** Free a countable mutex
sl@0
   100
*/
sl@0
   101
static void counterMutexFree(sqlite3_mutex *p){
sl@0
   102
  assert( g.isInit );
sl@0
   103
  g.m.xMutexFree(p->pReal);
sl@0
   104
  if( p->eType==SQLITE_MUTEX_FAST || p->eType==SQLITE_MUTEX_RECURSIVE ){
sl@0
   105
    free(p);
sl@0
   106
  }
sl@0
   107
}
sl@0
   108
sl@0
   109
/*
sl@0
   110
** Enter a countable mutex.  Block until entry is safe.
sl@0
   111
*/
sl@0
   112
static void counterMutexEnter(sqlite3_mutex *p){
sl@0
   113
  assert( g.isInit );
sl@0
   114
  g.aCounter[p->eType]++;
sl@0
   115
  g.m.xMutexEnter(p->pReal);
sl@0
   116
}
sl@0
   117
sl@0
   118
/*
sl@0
   119
** Try to enter a mutex.  Return true on success.
sl@0
   120
*/
sl@0
   121
static int counterMutexTry(sqlite3_mutex *p){
sl@0
   122
  assert( g.isInit );
sl@0
   123
  g.aCounter[p->eType]++;
sl@0
   124
  if( g.disableTry ) return SQLITE_BUSY;
sl@0
   125
  return g.m.xMutexTry(p->pReal);
sl@0
   126
}
sl@0
   127
sl@0
   128
/* Leave a mutex
sl@0
   129
*/
sl@0
   130
static void counterMutexLeave(sqlite3_mutex *p){
sl@0
   131
  assert( g.isInit );
sl@0
   132
  g.m.xMutexLeave(p->pReal);
sl@0
   133
}
sl@0
   134
sl@0
   135
/*
sl@0
   136
** sqlite3_shutdown
sl@0
   137
*/
sl@0
   138
static int test_shutdown(
sl@0
   139
  void * clientData,
sl@0
   140
  Tcl_Interp *interp,
sl@0
   141
  int objc,
sl@0
   142
  Tcl_Obj *CONST objv[]
sl@0
   143
){
sl@0
   144
  int rc;
sl@0
   145
sl@0
   146
  if( objc!=1 ){
sl@0
   147
    Tcl_WrongNumArgs(interp, 1, objv, "");
sl@0
   148
    return TCL_ERROR;
sl@0
   149
  }
sl@0
   150
sl@0
   151
  rc = sqlite3_shutdown();
sl@0
   152
  Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
sl@0
   153
  return TCL_OK;
sl@0
   154
}
sl@0
   155
sl@0
   156
/*
sl@0
   157
** sqlite3_initialize
sl@0
   158
*/
sl@0
   159
static int test_initialize(
sl@0
   160
  void * clientData,
sl@0
   161
  Tcl_Interp *interp,
sl@0
   162
  int objc,
sl@0
   163
  Tcl_Obj *CONST objv[]
sl@0
   164
){
sl@0
   165
  int rc;
sl@0
   166
sl@0
   167
  if( objc!=1 ){
sl@0
   168
    Tcl_WrongNumArgs(interp, 1, objv, "");
sl@0
   169
    return TCL_ERROR;
sl@0
   170
  }
sl@0
   171
sl@0
   172
  rc = sqlite3_initialize();
sl@0
   173
  Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
sl@0
   174
  return TCL_OK;
sl@0
   175
}
sl@0
   176
sl@0
   177
/*
sl@0
   178
** install_mutex_counters BOOLEAN
sl@0
   179
*/
sl@0
   180
static int test_install_mutex_counters(
sl@0
   181
  void * clientData,
sl@0
   182
  Tcl_Interp *interp,
sl@0
   183
  int objc,
sl@0
   184
  Tcl_Obj *CONST objv[]
sl@0
   185
){
sl@0
   186
  int rc = SQLITE_OK;
sl@0
   187
  int isInstall;
sl@0
   188
sl@0
   189
  sqlite3_mutex_methods counter_methods = {
sl@0
   190
    counterMutexInit,
sl@0
   191
    counterMutexEnd,
sl@0
   192
    counterMutexAlloc,
sl@0
   193
    counterMutexFree,
sl@0
   194
    counterMutexEnter,
sl@0
   195
    counterMutexTry,
sl@0
   196
    counterMutexLeave,
sl@0
   197
    counterMutexHeld,
sl@0
   198
    counterMutexNotheld
sl@0
   199
  };
sl@0
   200
sl@0
   201
  if( objc!=2 ){
sl@0
   202
    Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
sl@0
   203
    return TCL_ERROR;
sl@0
   204
  }
sl@0
   205
  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
sl@0
   206
    return TCL_ERROR;
sl@0
   207
  }
sl@0
   208
sl@0
   209
  assert(isInstall==0 || isInstall==1);
sl@0
   210
  assert(g.isInstalled==0 || g.isInstalled==1);
sl@0
   211
  if( isInstall==g.isInstalled ){
sl@0
   212
    Tcl_AppendResult(interp, "mutex counters are ", 0);
sl@0
   213
    Tcl_AppendResult(interp, isInstall?"already installed":"not installed", 0);
sl@0
   214
    return TCL_ERROR;
sl@0
   215
  }
sl@0
   216
sl@0
   217
  if( isInstall ){
sl@0
   218
    assert( g.m.xMutexAlloc==0 );
sl@0
   219
    rc = sqlite3_config(SQLITE_CONFIG_GETMUTEX, &g.m);
sl@0
   220
    if( rc==SQLITE_OK ){
sl@0
   221
      sqlite3_config(SQLITE_CONFIG_MUTEX, &counter_methods);
sl@0
   222
    }
sl@0
   223
    g.disableTry = 0;
sl@0
   224
  }else{
sl@0
   225
    assert( g.m.xMutexAlloc );
sl@0
   226
    rc = sqlite3_config(SQLITE_CONFIG_MUTEX, &g.m);
sl@0
   227
    memset(&g.m, 0, sizeof(sqlite3_mutex_methods));
sl@0
   228
  }
sl@0
   229
sl@0
   230
  if( rc==SQLITE_OK ){
sl@0
   231
    g.isInstalled = isInstall;
sl@0
   232
  }
sl@0
   233
sl@0
   234
  Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
sl@0
   235
  return TCL_OK;
sl@0
   236
}
sl@0
   237
sl@0
   238
/*
sl@0
   239
** read_mutex_counters
sl@0
   240
*/
sl@0
   241
static int test_read_mutex_counters(
sl@0
   242
  void * clientData,
sl@0
   243
  Tcl_Interp *interp,
sl@0
   244
  int objc,
sl@0
   245
  Tcl_Obj *CONST objv[]
sl@0
   246
){
sl@0
   247
  Tcl_Obj *pRet;
sl@0
   248
  int ii;
sl@0
   249
  char *aName[8] = {
sl@0
   250
    "fast",        "recursive",   "static_master", "static_mem", 
sl@0
   251
    "static_mem2", "static_prng", "static_lru",    "static_lru2"
sl@0
   252
  };
sl@0
   253
sl@0
   254
  if( objc!=1 ){
sl@0
   255
    Tcl_WrongNumArgs(interp, 1, objv, "");
sl@0
   256
    return TCL_ERROR;
sl@0
   257
  }
sl@0
   258
sl@0
   259
  pRet = Tcl_NewObj();
sl@0
   260
  Tcl_IncrRefCount(pRet);
sl@0
   261
  for(ii=0; ii<8; ii++){
sl@0
   262
    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(aName[ii], -1));
sl@0
   263
    Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(g.aCounter[ii]));
sl@0
   264
  }
sl@0
   265
  Tcl_SetObjResult(interp, pRet);
sl@0
   266
  Tcl_DecrRefCount(pRet);
sl@0
   267
sl@0
   268
  return TCL_OK;
sl@0
   269
}
sl@0
   270
sl@0
   271
/*
sl@0
   272
** clear_mutex_counters
sl@0
   273
*/
sl@0
   274
static int test_clear_mutex_counters(
sl@0
   275
  void * clientData,
sl@0
   276
  Tcl_Interp *interp,
sl@0
   277
  int objc,
sl@0
   278
  Tcl_Obj *CONST objv[]
sl@0
   279
){
sl@0
   280
  int ii;
sl@0
   281
sl@0
   282
  if( objc!=1 ){
sl@0
   283
    Tcl_WrongNumArgs(interp, 1, objv, "");
sl@0
   284
    return TCL_ERROR;
sl@0
   285
  }
sl@0
   286
sl@0
   287
  for(ii=0; ii<8; ii++){
sl@0
   288
    g.aCounter[ii] = 0;
sl@0
   289
  }
sl@0
   290
  return TCL_OK;
sl@0
   291
}
sl@0
   292
sl@0
   293
/*
sl@0
   294
** Create and free a mutex.  Return the mutex pointer.  The pointer
sl@0
   295
** will be invalid since the mutex has already been freed.  The
sl@0
   296
** return pointer just checks to see if the mutex really was allocated.
sl@0
   297
*/
sl@0
   298
static int test_alloc_mutex(
sl@0
   299
  void * clientData,
sl@0
   300
  Tcl_Interp *interp,
sl@0
   301
  int objc,
sl@0
   302
  Tcl_Obj *CONST objv[]
sl@0
   303
){
sl@0
   304
#if SQLITE_THREADSAFE
sl@0
   305
  sqlite3_mutex *p = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
sl@0
   306
  char zBuf[100];
sl@0
   307
  sqlite3_mutex_free(p);
sl@0
   308
  sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p);
sl@0
   309
  Tcl_AppendResult(interp, zBuf, (char*)0);
sl@0
   310
#endif
sl@0
   311
  return TCL_OK;
sl@0
   312
}
sl@0
   313
sl@0
   314
/*
sl@0
   315
** sqlite3_config OPTION
sl@0
   316
**
sl@0
   317
** OPTION can be either one of the keywords:
sl@0
   318
**
sl@0
   319
**            SQLITE_CONFIG_SINGLETHREAD
sl@0
   320
**            SQLITE_CONFIG_MULTITHREAD
sl@0
   321
**            SQLITE_CONFIG_SERIALIZED
sl@0
   322
**
sl@0
   323
** Or OPTION can be an raw integer.
sl@0
   324
*/
sl@0
   325
static int test_config(
sl@0
   326
  void * clientData,
sl@0
   327
  Tcl_Interp *interp,
sl@0
   328
  int objc,
sl@0
   329
  Tcl_Obj *CONST objv[]
sl@0
   330
){
sl@0
   331
  struct ConfigOption {
sl@0
   332
    const char *zName;
sl@0
   333
    int iValue;
sl@0
   334
  } aOpt[] = {
sl@0
   335
    {"singlethread", SQLITE_CONFIG_SINGLETHREAD},
sl@0
   336
    {"multithread",  SQLITE_CONFIG_MULTITHREAD},
sl@0
   337
    {"serialized",   SQLITE_CONFIG_SERIALIZED},
sl@0
   338
    {0, 0}
sl@0
   339
  };
sl@0
   340
  int s = sizeof(struct ConfigOption);
sl@0
   341
  int i;
sl@0
   342
  int rc;
sl@0
   343
sl@0
   344
  if( objc!=2 ){
sl@0
   345
    Tcl_WrongNumArgs(interp, 1, objv, "");
sl@0
   346
    return TCL_ERROR;
sl@0
   347
  }
sl@0
   348
sl@0
   349
  if( Tcl_GetIndexFromObjStruct(interp, objv[1], aOpt, s, "flag", 0, &i) ){
sl@0
   350
    if( Tcl_GetIntFromObj(interp, objv[1], &i) ){
sl@0
   351
      return TCL_ERROR;
sl@0
   352
    }
sl@0
   353
  }else{
sl@0
   354
    i = aOpt[i].iValue;
sl@0
   355
  }
sl@0
   356
sl@0
   357
  rc = sqlite3_config(i);
sl@0
   358
  Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
sl@0
   359
  return TCL_OK;
sl@0
   360
}
sl@0
   361
sl@0
   362
int Sqlitetest_mutex_Init(Tcl_Interp *interp){
sl@0
   363
  static struct {
sl@0
   364
    char *zName;
sl@0
   365
    Tcl_ObjCmdProc *xProc;
sl@0
   366
  } aCmd[] = {
sl@0
   367
    { "sqlite3_shutdown",        (Tcl_ObjCmdProc*)test_shutdown },
sl@0
   368
    { "sqlite3_initialize",      (Tcl_ObjCmdProc*)test_initialize },
sl@0
   369
    { "sqlite3_config",          (Tcl_ObjCmdProc*)test_config },
sl@0
   370
sl@0
   371
    { "alloc_dealloc_mutex",     (Tcl_ObjCmdProc*)test_alloc_mutex },
sl@0
   372
    { "install_mutex_counters",  (Tcl_ObjCmdProc*)test_install_mutex_counters },
sl@0
   373
    { "read_mutex_counters",     (Tcl_ObjCmdProc*)test_read_mutex_counters },
sl@0
   374
    { "clear_mutex_counters",    (Tcl_ObjCmdProc*)test_clear_mutex_counters },
sl@0
   375
  };
sl@0
   376
  int i;
sl@0
   377
  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
sl@0
   378
    Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
sl@0
   379
  }
sl@0
   380
  memset(&g, 0, sizeof(g));
sl@0
   381
sl@0
   382
  Tcl_LinkVar(interp, "disable_mutex_init", 
sl@0
   383
              (char*)&g.disableInit, TCL_LINK_INT);
sl@0
   384
  Tcl_LinkVar(interp, "disable_mutex_try", 
sl@0
   385
              (char*)&g.disableTry, TCL_LINK_INT);
sl@0
   386
  return SQLITE_OK;
sl@0
   387
}