File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / src / test_mutex.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:17 2012 UTC (12 years, 7 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    1: /*
    2: ** 2008 June 18
    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 test logic for the sqlite3_mutex interfaces.
   13: */
   14: 
   15: #include "tcl.h"
   16: #include "sqlite3.h"
   17: #include "sqliteInt.h"
   18: #include <stdlib.h>
   19: #include <assert.h>
   20: #include <string.h>
   21: 
   22: /* defined in test1.c */
   23: const char *sqlite3TestErrorName(int);
   24: 
   25: /* A countable mutex */
   26: struct sqlite3_mutex {
   27:   sqlite3_mutex *pReal;
   28:   int eType;
   29: };
   30: 
   31: /* State variables */
   32: 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 */
   40: } g = {0};
   41: 
   42: /* Return true if the countable mutex is currently held */
   43: static int counterMutexHeld(sqlite3_mutex *p){
   44:   return g.m.xMutexHeld(p->pReal);
   45: }
   46: 
   47: /* Return true if the countable mutex is not currently held */
   48: static int counterMutexNotheld(sqlite3_mutex *p){
   49:   return g.m.xMutexNotheld(p->pReal);
   50: }
   51: 
   52: /* Initialize the countable mutex interface
   53: ** Or, if g.disableInit is non-zero, then do not initialize but instead
   54: ** return the value of g.disableInit as the result code.  This can be used
   55: ** to simulate an initialization failure.
   56: */
   57: static int counterMutexInit(void){ 
   58:   int rc;
   59:   if( g.disableInit ) return g.disableInit;
   60:   rc = g.m.xMutexInit();
   61:   g.isInit = 1;
   62:   return rc;
   63: }
   64: 
   65: /*
   66: ** Uninitialize the mutex subsystem
   67: */
   68: static int counterMutexEnd(void){ 
   69:   g.isInit = 0;
   70:   return g.m.xMutexEnd();
   71: }
   72: 
   73: /*
   74: ** Allocate a countable mutex
   75: */
   76: static sqlite3_mutex *counterMutexAlloc(int eType){
   77:   sqlite3_mutex *pReal;
   78:   sqlite3_mutex *pRet = 0;
   79: 
   80:   assert( g.isInit );
   81:   assert(eType<8 && eType>=0);
   82: 
   83:   pReal = g.m.xMutexAlloc(eType);
   84:   if( !pReal ) return 0;
   85: 
   86:   if( eType==SQLITE_MUTEX_FAST || eType==SQLITE_MUTEX_RECURSIVE ){
   87:     pRet = (sqlite3_mutex *)malloc(sizeof(sqlite3_mutex));
   88:   }else{
   89:     pRet = &g.aStatic[eType-2];
   90:   }
   91: 
   92:   pRet->eType = eType;
   93:   pRet->pReal = pReal;
   94:   return pRet;
   95: }
   96: 
   97: /*
   98: ** Free a countable mutex
   99: */
  100: static void counterMutexFree(sqlite3_mutex *p){
  101:   assert( g.isInit );
  102:   g.m.xMutexFree(p->pReal);
  103:   if( p->eType==SQLITE_MUTEX_FAST || p->eType==SQLITE_MUTEX_RECURSIVE ){
  104:     free(p);
  105:   }
  106: }
  107: 
  108: /*
  109: ** Enter a countable mutex.  Block until entry is safe.
  110: */
  111: static void counterMutexEnter(sqlite3_mutex *p){
  112:   assert( g.isInit );
  113:   g.aCounter[p->eType]++;
  114:   g.m.xMutexEnter(p->pReal);
  115: }
  116: 
  117: /*
  118: ** Try to enter a mutex.  Return true on success.
  119: */
  120: static int counterMutexTry(sqlite3_mutex *p){
  121:   assert( g.isInit );
  122:   g.aCounter[p->eType]++;
  123:   if( g.disableTry ) return SQLITE_BUSY;
  124:   return g.m.xMutexTry(p->pReal);
  125: }
  126: 
  127: /* Leave a mutex
  128: */
  129: static void counterMutexLeave(sqlite3_mutex *p){
  130:   assert( g.isInit );
  131:   g.m.xMutexLeave(p->pReal);
  132: }
  133: 
  134: /*
  135: ** sqlite3_shutdown
  136: */
  137: static int test_shutdown(
  138:   void * clientData,
  139:   Tcl_Interp *interp,
  140:   int objc,
  141:   Tcl_Obj *CONST objv[]
  142: ){
  143:   int rc;
  144: 
  145:   if( objc!=1 ){
  146:     Tcl_WrongNumArgs(interp, 1, objv, "");
  147:     return TCL_ERROR;
  148:   }
  149: 
  150:   rc = sqlite3_shutdown();
  151:   Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
  152:   return TCL_OK;
  153: }
  154: 
  155: /*
  156: ** sqlite3_initialize
  157: */
  158: static int test_initialize(
  159:   void * clientData,
  160:   Tcl_Interp *interp,
  161:   int objc,
  162:   Tcl_Obj *CONST objv[]
  163: ){
  164:   int rc;
  165: 
  166:   if( objc!=1 ){
  167:     Tcl_WrongNumArgs(interp, 1, objv, "");
  168:     return TCL_ERROR;
  169:   }
  170: 
  171:   rc = sqlite3_initialize();
  172:   Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
  173:   return TCL_OK;
  174: }
  175: 
  176: /*
  177: ** install_mutex_counters BOOLEAN
  178: */
  179: static int test_install_mutex_counters(
  180:   void * clientData,
  181:   Tcl_Interp *interp,
  182:   int objc,
  183:   Tcl_Obj *CONST objv[]
  184: ){
  185:   int rc = SQLITE_OK;
  186:   int isInstall;
  187: 
  188:   sqlite3_mutex_methods counter_methods = {
  189:     counterMutexInit,
  190:     counterMutexEnd,
  191:     counterMutexAlloc,
  192:     counterMutexFree,
  193:     counterMutexEnter,
  194:     counterMutexTry,
  195:     counterMutexLeave,
  196:     counterMutexHeld,
  197:     counterMutexNotheld
  198:   };
  199: 
  200:   if( objc!=2 ){
  201:     Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
  202:     return TCL_ERROR;
  203:   }
  204:   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
  205:     return TCL_ERROR;
  206:   }
  207: 
  208:   assert(isInstall==0 || isInstall==1);
  209:   assert(g.isInstalled==0 || g.isInstalled==1);
  210:   if( isInstall==g.isInstalled ){
  211:     Tcl_AppendResult(interp, "mutex counters are ", 0);
  212:     Tcl_AppendResult(interp, isInstall?"already installed":"not installed", 0);
  213:     return TCL_ERROR;
  214:   }
  215: 
  216:   if( isInstall ){
  217:     assert( g.m.xMutexAlloc==0 );
  218:     rc = sqlite3_config(SQLITE_CONFIG_GETMUTEX, &g.m);
  219:     if( rc==SQLITE_OK ){
  220:       sqlite3_config(SQLITE_CONFIG_MUTEX, &counter_methods);
  221:     }
  222:     g.disableTry = 0;
  223:   }else{
  224:     assert( g.m.xMutexAlloc );
  225:     rc = sqlite3_config(SQLITE_CONFIG_MUTEX, &g.m);
  226:     memset(&g.m, 0, sizeof(sqlite3_mutex_methods));
  227:   }
  228: 
  229:   if( rc==SQLITE_OK ){
  230:     g.isInstalled = isInstall;
  231:   }
  232: 
  233:   Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
  234:   return TCL_OK;
  235: }
  236: 
  237: /*
  238: ** read_mutex_counters
  239: */
  240: static int test_read_mutex_counters(
  241:   void * clientData,
  242:   Tcl_Interp *interp,
  243:   int objc,
  244:   Tcl_Obj *CONST objv[]
  245: ){
  246:   Tcl_Obj *pRet;
  247:   int ii;
  248:   char *aName[8] = {
  249:     "fast",        "recursive",   "static_master", "static_mem", 
  250:     "static_open", "static_prng", "static_lru",    "static_pmem"
  251:   };
  252: 
  253:   if( objc!=1 ){
  254:     Tcl_WrongNumArgs(interp, 1, objv, "");
  255:     return TCL_ERROR;
  256:   }
  257: 
  258:   pRet = Tcl_NewObj();
  259:   Tcl_IncrRefCount(pRet);
  260:   for(ii=0; ii<8; ii++){
  261:     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(aName[ii], -1));
  262:     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(g.aCounter[ii]));
  263:   }
  264:   Tcl_SetObjResult(interp, pRet);
  265:   Tcl_DecrRefCount(pRet);
  266: 
  267:   return TCL_OK;
  268: }
  269: 
  270: /*
  271: ** clear_mutex_counters
  272: */
  273: static int test_clear_mutex_counters(
  274:   void * clientData,
  275:   Tcl_Interp *interp,
  276:   int objc,
  277:   Tcl_Obj *CONST objv[]
  278: ){
  279:   int ii;
  280: 
  281:   if( objc!=1 ){
  282:     Tcl_WrongNumArgs(interp, 1, objv, "");
  283:     return TCL_ERROR;
  284:   }
  285: 
  286:   for(ii=0; ii<8; ii++){
  287:     g.aCounter[ii] = 0;
  288:   }
  289:   return TCL_OK;
  290: }
  291: 
  292: /*
  293: ** Create and free a mutex.  Return the mutex pointer.  The pointer
  294: ** will be invalid since the mutex has already been freed.  The
  295: ** return pointer just checks to see if the mutex really was allocated.
  296: */
  297: static int test_alloc_mutex(
  298:   void * clientData,
  299:   Tcl_Interp *interp,
  300:   int objc,
  301:   Tcl_Obj *CONST objv[]
  302: ){
  303: #if SQLITE_THREADSAFE
  304:   sqlite3_mutex *p = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  305:   char zBuf[100];
  306:   sqlite3_mutex_free(p);
  307:   sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p);
  308:   Tcl_AppendResult(interp, zBuf, (char*)0);
  309: #endif
  310:   return TCL_OK;
  311: }
  312: 
  313: /*
  314: ** sqlite3_config OPTION
  315: **
  316: ** OPTION can be either one of the keywords:
  317: **
  318: **            SQLITE_CONFIG_SINGLETHREAD
  319: **            SQLITE_CONFIG_MULTITHREAD
  320: **            SQLITE_CONFIG_SERIALIZED
  321: **
  322: ** Or OPTION can be an raw integer.
  323: */
  324: static int test_config(
  325:   void * clientData,
  326:   Tcl_Interp *interp,
  327:   int objc,
  328:   Tcl_Obj *CONST objv[]
  329: ){
  330:   struct ConfigOption {
  331:     const char *zName;
  332:     int iValue;
  333:   } aOpt[] = {
  334:     {"singlethread", SQLITE_CONFIG_SINGLETHREAD},
  335:     {"multithread",  SQLITE_CONFIG_MULTITHREAD},
  336:     {"serialized",   SQLITE_CONFIG_SERIALIZED},
  337:     {0, 0}
  338:   };
  339:   int s = sizeof(struct ConfigOption);
  340:   int i;
  341:   int rc;
  342: 
  343:   if( objc!=2 ){
  344:     Tcl_WrongNumArgs(interp, 1, objv, "");
  345:     return TCL_ERROR;
  346:   }
  347: 
  348:   if( Tcl_GetIndexFromObjStruct(interp, objv[1], aOpt, s, "flag", 0, &i) ){
  349:     if( Tcl_GetIntFromObj(interp, objv[1], &i) ){
  350:       return TCL_ERROR;
  351:     }
  352:   }else{
  353:     i = aOpt[i].iValue;
  354:   }
  355: 
  356:   rc = sqlite3_config(i);
  357:   Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
  358:   return TCL_OK;
  359: }
  360: 
  361: static sqlite3 *getDbPointer(Tcl_Interp *pInterp, Tcl_Obj *pObj){
  362:   sqlite3 *db;
  363:   Tcl_CmdInfo info;
  364:   char *zCmd = Tcl_GetString(pObj);
  365:   if( Tcl_GetCommandInfo(pInterp, zCmd, &info) ){
  366:     db = *((sqlite3 **)info.objClientData);
  367:   }else{
  368:     db = (sqlite3*)sqlite3TestTextToPtr(zCmd);
  369:   }
  370:   assert( db );
  371:   return db;
  372: }
  373: 
  374: static int test_enter_db_mutex(
  375:   void * clientData,
  376:   Tcl_Interp *interp,
  377:   int objc,
  378:   Tcl_Obj *CONST objv[]
  379: ){
  380:   sqlite3 *db;
  381:   if( objc!=2 ){
  382:     Tcl_WrongNumArgs(interp, 1, objv, "DB");
  383:     return TCL_ERROR;
  384:   }
  385:   db = getDbPointer(interp, objv[1]);
  386:   if( !db ){
  387:     return TCL_ERROR;
  388:   }
  389:   sqlite3_mutex_enter(sqlite3_db_mutex(db));
  390:   return TCL_OK;
  391: }
  392: 
  393: static int test_leave_db_mutex(
  394:   void * clientData,
  395:   Tcl_Interp *interp,
  396:   int objc,
  397:   Tcl_Obj *CONST objv[]
  398: ){
  399:   sqlite3 *db;
  400:   if( objc!=2 ){
  401:     Tcl_WrongNumArgs(interp, 1, objv, "DB");
  402:     return TCL_ERROR;
  403:   }
  404:   db = getDbPointer(interp, objv[1]);
  405:   if( !db ){
  406:     return TCL_ERROR;
  407:   }
  408:   sqlite3_mutex_leave(sqlite3_db_mutex(db));
  409:   return TCL_OK;
  410: }
  411: 
  412: int Sqlitetest_mutex_Init(Tcl_Interp *interp){
  413:   static struct {
  414:     char *zName;
  415:     Tcl_ObjCmdProc *xProc;
  416:   } aCmd[] = {
  417:     { "sqlite3_shutdown",        (Tcl_ObjCmdProc*)test_shutdown },
  418:     { "sqlite3_initialize",      (Tcl_ObjCmdProc*)test_initialize },
  419:     { "sqlite3_config",          (Tcl_ObjCmdProc*)test_config },
  420: 
  421:     { "enter_db_mutex",          (Tcl_ObjCmdProc*)test_enter_db_mutex },
  422:     { "leave_db_mutex",          (Tcl_ObjCmdProc*)test_leave_db_mutex },
  423: 
  424:     { "alloc_dealloc_mutex",     (Tcl_ObjCmdProc*)test_alloc_mutex },
  425:     { "install_mutex_counters",  (Tcl_ObjCmdProc*)test_install_mutex_counters },
  426:     { "read_mutex_counters",     (Tcl_ObjCmdProc*)test_read_mutex_counters },
  427:     { "clear_mutex_counters",    (Tcl_ObjCmdProc*)test_clear_mutex_counters },
  428:   };
  429:   int i;
  430:   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
  431:     Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
  432:   }
  433: 
  434:   Tcl_LinkVar(interp, "disable_mutex_init", 
  435:               (char*)&g.disableInit, TCL_LINK_INT);
  436:   Tcl_LinkVar(interp, "disable_mutex_try", 
  437:               (char*)&g.disableTry, TCL_LINK_INT);
  438:   return SQLITE_OK;
  439: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>