Annotation of embedaddon/sqlite3/src/test_mutex.c, revision 1.1
1.1 ! misho 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>