11a9ed0b2Sdanielk1977 /*
21a9ed0b2Sdanielk1977 ** 2008 June 18
31a9ed0b2Sdanielk1977 **
41a9ed0b2Sdanielk1977 ** The author disclaims copyright to this source code. In place of
51a9ed0b2Sdanielk1977 ** a legal notice, here is a blessing:
61a9ed0b2Sdanielk1977 **
71a9ed0b2Sdanielk1977 ** May you do good and not evil.
81a9ed0b2Sdanielk1977 ** May you find forgiveness for yourself and forgive others.
91a9ed0b2Sdanielk1977 ** May you share freely, never taking more than you give.
101a9ed0b2Sdanielk1977 **
111a9ed0b2Sdanielk1977 *************************************************************************
12c81c11f6Sdrh ** This file contains test logic for the sqlite3_mutex interfaces.
131a9ed0b2Sdanielk1977 */
141a9ed0b2Sdanielk1977
1552b1dbb5Smistachkin #if defined(INCLUDE_SQLITE_TCL_H)
1652b1dbb5Smistachkin # include "sqlite_tcl.h"
1752b1dbb5Smistachkin #else
181a9ed0b2Sdanielk1977 # include "tcl.h"
1952b1dbb5Smistachkin #endif
201a9ed0b2Sdanielk1977 #include "sqlite3.h"
21b27475baSdanielk1977 #include "sqliteInt.h"
221a9ed0b2Sdanielk1977 #include <stdlib.h>
231a9ed0b2Sdanielk1977 #include <assert.h>
241a9ed0b2Sdanielk1977 #include <string.h>
251a9ed0b2Sdanielk1977
2628ae577aSmistachkin #define MAX_MUTEXES (SQLITE_MUTEX_STATIC_VFS3+1)
2774db3567Smistachkin #define STATIC_MUTEXES (MAX_MUTEXES-(SQLITE_MUTEX_RECURSIVE+1))
2828ae577aSmistachkin
29e84d8d32Smistachkin /* defined in main.c */
30e84d8d32Smistachkin extern const char *sqlite3ErrName(int);
311a9ed0b2Sdanielk1977
3228ae577aSmistachkin static const char *aName[MAX_MUTEXES+1] = {
33*1e32bed3Sdrh "fast", "recursive", "static_main", "static_mem",
3428ae577aSmistachkin "static_open", "static_prng", "static_lru", "static_pmem",
3528ae577aSmistachkin "static_app1", "static_app2", "static_app3", "static_vfs1",
3628ae577aSmistachkin "static_vfs2", "static_vfs3", 0
3728ae577aSmistachkin };
3828ae577aSmistachkin
39fb45d8c5Sdrh /* A countable mutex */
401a9ed0b2Sdanielk1977 struct sqlite3_mutex {
411a9ed0b2Sdanielk1977 sqlite3_mutex *pReal;
421a9ed0b2Sdanielk1977 int eType;
431a9ed0b2Sdanielk1977 };
441a9ed0b2Sdanielk1977
45fb45d8c5Sdrh /* State variables */
461a9ed0b2Sdanielk1977 static struct test_mutex_globals {
47fb45d8c5Sdrh int isInstalled; /* True if installed */
48fb45d8c5Sdrh int disableInit; /* True to cause sqlite3_initalize() to fail */
498a42cbd3Sdrh int disableTry; /* True to force sqlite3_mutex_try() to fail */
50fb45d8c5Sdrh int isInit; /* True if initialized */
511a9ed0b2Sdanielk1977 sqlite3_mutex_methods m; /* Interface to "real" mutex system */
5228ae577aSmistachkin int aCounter[MAX_MUTEXES]; /* Number of grabs of each type of mutex */
5374db3567Smistachkin sqlite3_mutex aStatic[STATIC_MUTEXES]; /* The static mutexes */
549ec30744Sdanielk1977 } g = {0};
551a9ed0b2Sdanielk1977
56fb45d8c5Sdrh /* Return true if the countable mutex is currently held */
counterMutexHeld(sqlite3_mutex * p)571a9ed0b2Sdanielk1977 static int counterMutexHeld(sqlite3_mutex *p){
581a9ed0b2Sdanielk1977 return g.m.xMutexHeld(p->pReal);
591a9ed0b2Sdanielk1977 }
601a9ed0b2Sdanielk1977
61fb45d8c5Sdrh /* Return true if the countable mutex is not currently held */
counterMutexNotheld(sqlite3_mutex * p)621a9ed0b2Sdanielk1977 static int counterMutexNotheld(sqlite3_mutex *p){
631a9ed0b2Sdanielk1977 return g.m.xMutexNotheld(p->pReal);
641a9ed0b2Sdanielk1977 }
651a9ed0b2Sdanielk1977
66fb45d8c5Sdrh /* Initialize the countable mutex interface
67fb45d8c5Sdrh ** Or, if g.disableInit is non-zero, then do not initialize but instead
68fb45d8c5Sdrh ** return the value of g.disableInit as the result code. This can be used
69fb45d8c5Sdrh ** to simulate an initialization failure.
70fb45d8c5Sdrh */
counterMutexInit(void)711a9ed0b2Sdanielk1977 static int counterMutexInit(void){
72fb45d8c5Sdrh int rc;
73fb45d8c5Sdrh if( g.disableInit ) return g.disableInit;
74fb45d8c5Sdrh rc = g.m.xMutexInit();
75fb45d8c5Sdrh g.isInit = 1;
76fb45d8c5Sdrh return rc;
771a9ed0b2Sdanielk1977 }
781a9ed0b2Sdanielk1977
79fb45d8c5Sdrh /*
80fb45d8c5Sdrh ** Uninitialize the mutex subsystem
81fb45d8c5Sdrh */
counterMutexEnd(void)821a9ed0b2Sdanielk1977 static int counterMutexEnd(void){
83fb45d8c5Sdrh g.isInit = 0;
841a9ed0b2Sdanielk1977 return g.m.xMutexEnd();
851a9ed0b2Sdanielk1977 }
861a9ed0b2Sdanielk1977
87fb45d8c5Sdrh /*
88fb45d8c5Sdrh ** Allocate a countable mutex
89fb45d8c5Sdrh */
counterMutexAlloc(int eType)901a9ed0b2Sdanielk1977 static sqlite3_mutex *counterMutexAlloc(int eType){
911a9ed0b2Sdanielk1977 sqlite3_mutex *pReal;
921a9ed0b2Sdanielk1977 sqlite3_mutex *pRet = 0;
931a9ed0b2Sdanielk1977
94fb45d8c5Sdrh assert( g.isInit );
9528ae577aSmistachkin assert( eType>=SQLITE_MUTEX_FAST );
9628ae577aSmistachkin assert( eType<=SQLITE_MUTEX_STATIC_VFS3 );
971a9ed0b2Sdanielk1977
981a9ed0b2Sdanielk1977 pReal = g.m.xMutexAlloc(eType);
991a9ed0b2Sdanielk1977 if( !pReal ) return 0;
1001a9ed0b2Sdanielk1977
101c8d75674Sdrh if( eType==SQLITE_MUTEX_FAST || eType==SQLITE_MUTEX_RECURSIVE ){
1021a9ed0b2Sdanielk1977 pRet = (sqlite3_mutex *)malloc(sizeof(sqlite3_mutex));
1031a9ed0b2Sdanielk1977 }else{
10474db3567Smistachkin int eStaticType = eType - (MAX_MUTEXES - STATIC_MUTEXES);
10528ae577aSmistachkin assert( eStaticType>=0 );
10674db3567Smistachkin assert( eStaticType<STATIC_MUTEXES );
10728ae577aSmistachkin pRet = &g.aStatic[eStaticType];
1081a9ed0b2Sdanielk1977 }
1091a9ed0b2Sdanielk1977
1101a9ed0b2Sdanielk1977 pRet->eType = eType;
1111a9ed0b2Sdanielk1977 pRet->pReal = pReal;
1121a9ed0b2Sdanielk1977 return pRet;
1131a9ed0b2Sdanielk1977 }
1141a9ed0b2Sdanielk1977
115fb45d8c5Sdrh /*
116fb45d8c5Sdrh ** Free a countable mutex
117fb45d8c5Sdrh */
counterMutexFree(sqlite3_mutex * p)1181a9ed0b2Sdanielk1977 static void counterMutexFree(sqlite3_mutex *p){
119fb45d8c5Sdrh assert( g.isInit );
1201a9ed0b2Sdanielk1977 g.m.xMutexFree(p->pReal);
121c8d75674Sdrh if( p->eType==SQLITE_MUTEX_FAST || p->eType==SQLITE_MUTEX_RECURSIVE ){
1221a9ed0b2Sdanielk1977 free(p);
1231a9ed0b2Sdanielk1977 }
1241a9ed0b2Sdanielk1977 }
1251a9ed0b2Sdanielk1977
126fb45d8c5Sdrh /*
127fb45d8c5Sdrh ** Enter a countable mutex. Block until entry is safe.
128fb45d8c5Sdrh */
counterMutexEnter(sqlite3_mutex * p)1291a9ed0b2Sdanielk1977 static void counterMutexEnter(sqlite3_mutex *p){
130fb45d8c5Sdrh assert( g.isInit );
13128ae577aSmistachkin assert( p->eType>=0 );
13228ae577aSmistachkin assert( p->eType<MAX_MUTEXES );
1331a9ed0b2Sdanielk1977 g.aCounter[p->eType]++;
1341a9ed0b2Sdanielk1977 g.m.xMutexEnter(p->pReal);
1351a9ed0b2Sdanielk1977 }
1361a9ed0b2Sdanielk1977
137fb45d8c5Sdrh /*
138fb45d8c5Sdrh ** Try to enter a mutex. Return true on success.
139fb45d8c5Sdrh */
counterMutexTry(sqlite3_mutex * p)1401a9ed0b2Sdanielk1977 static int counterMutexTry(sqlite3_mutex *p){
141fb45d8c5Sdrh assert( g.isInit );
14228ae577aSmistachkin assert( p->eType>=0 );
14328ae577aSmistachkin assert( p->eType<MAX_MUTEXES );
1441a9ed0b2Sdanielk1977 g.aCounter[p->eType]++;
14519dd29fcSdrh if( g.disableTry ) return SQLITE_BUSY;
1461a9ed0b2Sdanielk1977 return g.m.xMutexTry(p->pReal);
1471a9ed0b2Sdanielk1977 }
1481a9ed0b2Sdanielk1977
149fb45d8c5Sdrh /* Leave a mutex
150fb45d8c5Sdrh */
counterMutexLeave(sqlite3_mutex * p)1511a9ed0b2Sdanielk1977 static void counterMutexLeave(sqlite3_mutex *p){
152fb45d8c5Sdrh assert( g.isInit );
1531a9ed0b2Sdanielk1977 g.m.xMutexLeave(p->pReal);
1541a9ed0b2Sdanielk1977 }
1551a9ed0b2Sdanielk1977
1561a9ed0b2Sdanielk1977 /*
1571a9ed0b2Sdanielk1977 ** sqlite3_shutdown
1581a9ed0b2Sdanielk1977 */
test_shutdown(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])1597617e4a8Smistachkin static int SQLITE_TCLAPI test_shutdown(
1601a9ed0b2Sdanielk1977 void * clientData,
1611a9ed0b2Sdanielk1977 Tcl_Interp *interp,
1621a9ed0b2Sdanielk1977 int objc,
1631a9ed0b2Sdanielk1977 Tcl_Obj *CONST objv[]
1641a9ed0b2Sdanielk1977 ){
1651a9ed0b2Sdanielk1977 int rc;
1661a9ed0b2Sdanielk1977
1671a9ed0b2Sdanielk1977 if( objc!=1 ){
1681a9ed0b2Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "");
1691a9ed0b2Sdanielk1977 return TCL_ERROR;
1701a9ed0b2Sdanielk1977 }
1711a9ed0b2Sdanielk1977
1721a9ed0b2Sdanielk1977 rc = sqlite3_shutdown();
173e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1741a9ed0b2Sdanielk1977 return TCL_OK;
1751a9ed0b2Sdanielk1977 }
1761a9ed0b2Sdanielk1977
1771a9ed0b2Sdanielk1977 /*
1781a9ed0b2Sdanielk1977 ** sqlite3_initialize
1791a9ed0b2Sdanielk1977 */
test_initialize(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])1807617e4a8Smistachkin static int SQLITE_TCLAPI test_initialize(
1811a9ed0b2Sdanielk1977 void * clientData,
1821a9ed0b2Sdanielk1977 Tcl_Interp *interp,
1831a9ed0b2Sdanielk1977 int objc,
1841a9ed0b2Sdanielk1977 Tcl_Obj *CONST objv[]
1851a9ed0b2Sdanielk1977 ){
1861a9ed0b2Sdanielk1977 int rc;
1871a9ed0b2Sdanielk1977
1881a9ed0b2Sdanielk1977 if( objc!=1 ){
1891a9ed0b2Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "");
1901a9ed0b2Sdanielk1977 return TCL_ERROR;
1911a9ed0b2Sdanielk1977 }
1921a9ed0b2Sdanielk1977
1931a9ed0b2Sdanielk1977 rc = sqlite3_initialize();
194e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1951a9ed0b2Sdanielk1977 return TCL_OK;
1961a9ed0b2Sdanielk1977 }
1971a9ed0b2Sdanielk1977
1981a9ed0b2Sdanielk1977 /*
1991a9ed0b2Sdanielk1977 ** install_mutex_counters BOOLEAN
2001a9ed0b2Sdanielk1977 */
test_install_mutex_counters(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])2017617e4a8Smistachkin static int SQLITE_TCLAPI test_install_mutex_counters(
2021a9ed0b2Sdanielk1977 void * clientData,
2031a9ed0b2Sdanielk1977 Tcl_Interp *interp,
2041a9ed0b2Sdanielk1977 int objc,
2051a9ed0b2Sdanielk1977 Tcl_Obj *CONST objv[]
2061a9ed0b2Sdanielk1977 ){
2071a9ed0b2Sdanielk1977 int rc = SQLITE_OK;
2081a9ed0b2Sdanielk1977 int isInstall;
2091a9ed0b2Sdanielk1977
2101a9ed0b2Sdanielk1977 sqlite3_mutex_methods counter_methods = {
2111a9ed0b2Sdanielk1977 counterMutexInit,
2124a9d1f66Sdanielk1977 counterMutexEnd,
2131a9ed0b2Sdanielk1977 counterMutexAlloc,
2141a9ed0b2Sdanielk1977 counterMutexFree,
2151a9ed0b2Sdanielk1977 counterMutexEnter,
2161a9ed0b2Sdanielk1977 counterMutexTry,
2171a9ed0b2Sdanielk1977 counterMutexLeave,
2181a9ed0b2Sdanielk1977 counterMutexHeld,
2191a9ed0b2Sdanielk1977 counterMutexNotheld
2201a9ed0b2Sdanielk1977 };
2211a9ed0b2Sdanielk1977
2221a9ed0b2Sdanielk1977 if( objc!=2 ){
2231a9ed0b2Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
2241a9ed0b2Sdanielk1977 return TCL_ERROR;
2251a9ed0b2Sdanielk1977 }
2261a9ed0b2Sdanielk1977 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
2271a9ed0b2Sdanielk1977 return TCL_ERROR;
2281a9ed0b2Sdanielk1977 }
2291a9ed0b2Sdanielk1977
2301a9ed0b2Sdanielk1977 assert(isInstall==0 || isInstall==1);
2311a9ed0b2Sdanielk1977 assert(g.isInstalled==0 || g.isInstalled==1);
2321a9ed0b2Sdanielk1977 if( isInstall==g.isInstalled ){
2331a9ed0b2Sdanielk1977 Tcl_AppendResult(interp, "mutex counters are ", 0);
2341a9ed0b2Sdanielk1977 Tcl_AppendResult(interp, isInstall?"already installed":"not installed", 0);
2351a9ed0b2Sdanielk1977 return TCL_ERROR;
2361a9ed0b2Sdanielk1977 }
2371a9ed0b2Sdanielk1977
2381a9ed0b2Sdanielk1977 if( isInstall ){
2391a9ed0b2Sdanielk1977 assert( g.m.xMutexAlloc==0 );
2401a9ed0b2Sdanielk1977 rc = sqlite3_config(SQLITE_CONFIG_GETMUTEX, &g.m);
2411a9ed0b2Sdanielk1977 if( rc==SQLITE_OK ){
2421a9ed0b2Sdanielk1977 sqlite3_config(SQLITE_CONFIG_MUTEX, &counter_methods);
2431a9ed0b2Sdanielk1977 }
2448a42cbd3Sdrh g.disableTry = 0;
2451a9ed0b2Sdanielk1977 }else{
2461a9ed0b2Sdanielk1977 assert( g.m.xMutexAlloc );
2471a9ed0b2Sdanielk1977 rc = sqlite3_config(SQLITE_CONFIG_MUTEX, &g.m);
2481a9ed0b2Sdanielk1977 memset(&g.m, 0, sizeof(sqlite3_mutex_methods));
2491a9ed0b2Sdanielk1977 }
2501a9ed0b2Sdanielk1977
2511a9ed0b2Sdanielk1977 if( rc==SQLITE_OK ){
2521a9ed0b2Sdanielk1977 g.isInstalled = isInstall;
2531a9ed0b2Sdanielk1977 }
2541a9ed0b2Sdanielk1977
255e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
2561a9ed0b2Sdanielk1977 return TCL_OK;
2571a9ed0b2Sdanielk1977 }
2581a9ed0b2Sdanielk1977
2591a9ed0b2Sdanielk1977 /*
2601a9ed0b2Sdanielk1977 ** read_mutex_counters
2611a9ed0b2Sdanielk1977 */
test_read_mutex_counters(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])2627617e4a8Smistachkin static int SQLITE_TCLAPI test_read_mutex_counters(
2631a9ed0b2Sdanielk1977 void * clientData,
2641a9ed0b2Sdanielk1977 Tcl_Interp *interp,
2651a9ed0b2Sdanielk1977 int objc,
2661a9ed0b2Sdanielk1977 Tcl_Obj *CONST objv[]
2671a9ed0b2Sdanielk1977 ){
2681a9ed0b2Sdanielk1977 Tcl_Obj *pRet;
2691a9ed0b2Sdanielk1977 int ii;
2701a9ed0b2Sdanielk1977
2711a9ed0b2Sdanielk1977 if( objc!=1 ){
2721a9ed0b2Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "");
2731a9ed0b2Sdanielk1977 return TCL_ERROR;
2741a9ed0b2Sdanielk1977 }
2751a9ed0b2Sdanielk1977
2761a9ed0b2Sdanielk1977 pRet = Tcl_NewObj();
2771a9ed0b2Sdanielk1977 Tcl_IncrRefCount(pRet);
27828ae577aSmistachkin for(ii=0; ii<MAX_MUTEXES; ii++){
2791a9ed0b2Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(aName[ii], -1));
2801a9ed0b2Sdanielk1977 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(g.aCounter[ii]));
2811a9ed0b2Sdanielk1977 }
2821a9ed0b2Sdanielk1977 Tcl_SetObjResult(interp, pRet);
2831a9ed0b2Sdanielk1977 Tcl_DecrRefCount(pRet);
2841a9ed0b2Sdanielk1977
2851a9ed0b2Sdanielk1977 return TCL_OK;
2861a9ed0b2Sdanielk1977 }
2871a9ed0b2Sdanielk1977
2881a9ed0b2Sdanielk1977 /*
2891a9ed0b2Sdanielk1977 ** clear_mutex_counters
2901a9ed0b2Sdanielk1977 */
test_clear_mutex_counters(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])2917617e4a8Smistachkin static int SQLITE_TCLAPI test_clear_mutex_counters(
2921a9ed0b2Sdanielk1977 void * clientData,
2931a9ed0b2Sdanielk1977 Tcl_Interp *interp,
2941a9ed0b2Sdanielk1977 int objc,
2951a9ed0b2Sdanielk1977 Tcl_Obj *CONST objv[]
2961a9ed0b2Sdanielk1977 ){
2971a9ed0b2Sdanielk1977 int ii;
2981a9ed0b2Sdanielk1977
2991a9ed0b2Sdanielk1977 if( objc!=1 ){
3001a9ed0b2Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "");
3011a9ed0b2Sdanielk1977 return TCL_ERROR;
3021a9ed0b2Sdanielk1977 }
3031a9ed0b2Sdanielk1977
30428ae577aSmistachkin for(ii=0; ii<MAX_MUTEXES; ii++){
3051a9ed0b2Sdanielk1977 g.aCounter[ii] = 0;
3061a9ed0b2Sdanielk1977 }
3071a9ed0b2Sdanielk1977 return TCL_OK;
3081a9ed0b2Sdanielk1977 }
3091a9ed0b2Sdanielk1977
31059f8c08eSdanielk1977 /*
311c8d75674Sdrh ** Create and free a mutex. Return the mutex pointer. The pointer
312c8d75674Sdrh ** will be invalid since the mutex has already been freed. The
313c8d75674Sdrh ** return pointer just checks to see if the mutex really was allocated.
314c8d75674Sdrh */
test_alloc_mutex(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])3157617e4a8Smistachkin static int SQLITE_TCLAPI test_alloc_mutex(
316c8d75674Sdrh void * clientData,
317c8d75674Sdrh Tcl_Interp *interp,
318c8d75674Sdrh int objc,
319c8d75674Sdrh Tcl_Obj *CONST objv[]
320c8d75674Sdrh ){
321b912f3e9Sdrh #if SQLITE_THREADSAFE
322c8d75674Sdrh sqlite3_mutex *p = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
323c8d75674Sdrh char zBuf[100];
324c8d75674Sdrh sqlite3_mutex_free(p);
325c8d75674Sdrh sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p);
326c8d75674Sdrh Tcl_AppendResult(interp, zBuf, (char*)0);
327b912f3e9Sdrh #endif
328c8d75674Sdrh return TCL_OK;
329c8d75674Sdrh }
330c8d75674Sdrh
331c8d75674Sdrh /*
33259f8c08eSdanielk1977 ** sqlite3_config OPTION
3338a42cbd3Sdrh **
3348a42cbd3Sdrh ** OPTION can be either one of the keywords:
3358a42cbd3Sdrh **
3368a42cbd3Sdrh ** SQLITE_CONFIG_SINGLETHREAD
3378a42cbd3Sdrh ** SQLITE_CONFIG_MULTITHREAD
3388a42cbd3Sdrh ** SQLITE_CONFIG_SERIALIZED
3398a42cbd3Sdrh **
3408a42cbd3Sdrh ** Or OPTION can be an raw integer.
34159f8c08eSdanielk1977 */
test_config(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])3427617e4a8Smistachkin static int SQLITE_TCLAPI test_config(
34359f8c08eSdanielk1977 void * clientData,
34459f8c08eSdanielk1977 Tcl_Interp *interp,
34559f8c08eSdanielk1977 int objc,
34659f8c08eSdanielk1977 Tcl_Obj *CONST objv[]
34759f8c08eSdanielk1977 ){
34859f8c08eSdanielk1977 struct ConfigOption {
34959f8c08eSdanielk1977 const char *zName;
35059f8c08eSdanielk1977 int iValue;
35159f8c08eSdanielk1977 } aOpt[] = {
35259f8c08eSdanielk1977 {"singlethread", SQLITE_CONFIG_SINGLETHREAD},
35359f8c08eSdanielk1977 {"multithread", SQLITE_CONFIG_MULTITHREAD},
35459f8c08eSdanielk1977 {"serialized", SQLITE_CONFIG_SERIALIZED},
35559f8c08eSdanielk1977 {0, 0}
35659f8c08eSdanielk1977 };
35759f8c08eSdanielk1977 int s = sizeof(struct ConfigOption);
35859f8c08eSdanielk1977 int i;
35959f8c08eSdanielk1977 int rc;
36059f8c08eSdanielk1977
36159f8c08eSdanielk1977 if( objc!=2 ){
36259f8c08eSdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "");
36359f8c08eSdanielk1977 return TCL_ERROR;
36459f8c08eSdanielk1977 }
36559f8c08eSdanielk1977
36659f8c08eSdanielk1977 if( Tcl_GetIndexFromObjStruct(interp, objv[1], aOpt, s, "flag", 0, &i) ){
3678a42cbd3Sdrh if( Tcl_GetIntFromObj(interp, objv[1], &i) ){
36859f8c08eSdanielk1977 return TCL_ERROR;
36959f8c08eSdanielk1977 }
3708a42cbd3Sdrh }else{
3718a42cbd3Sdrh i = aOpt[i].iValue;
3728a42cbd3Sdrh }
37359f8c08eSdanielk1977
3748a42cbd3Sdrh rc = sqlite3_config(i);
375e84d8d32Smistachkin Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
37659f8c08eSdanielk1977 return TCL_OK;
37759f8c08eSdanielk1977 }
37859f8c08eSdanielk1977
getDbPointer(Tcl_Interp * pInterp,Tcl_Obj * pObj)3795f6d0268Sdanielk1977 static sqlite3 *getDbPointer(Tcl_Interp *pInterp, Tcl_Obj *pObj){
3805f6d0268Sdanielk1977 sqlite3 *db;
3815f6d0268Sdanielk1977 Tcl_CmdInfo info;
3825f6d0268Sdanielk1977 char *zCmd = Tcl_GetString(pObj);
383b8613ab1Sdrh if( Tcl_GetCommandInfo(pInterp, zCmd, &info) ){
3845f6d0268Sdanielk1977 db = *((sqlite3 **)info.objClientData);
385b8613ab1Sdrh }else{
386b8613ab1Sdrh db = (sqlite3*)sqlite3TestTextToPtr(zCmd);
387b8613ab1Sdrh }
3885f6d0268Sdanielk1977 assert( db );
3895f6d0268Sdanielk1977 return db;
3905f6d0268Sdanielk1977 }
3915f6d0268Sdanielk1977
getStaticMutexPointer(Tcl_Interp * pInterp,Tcl_Obj * pObj)39228ae577aSmistachkin static sqlite3_mutex *getStaticMutexPointer(
39328ae577aSmistachkin Tcl_Interp *pInterp,
39428ae577aSmistachkin Tcl_Obj *pObj
39528ae577aSmistachkin ){
39628ae577aSmistachkin int iMutex;
39728ae577aSmistachkin if( Tcl_GetIndexFromObj(pInterp, pObj, aName, "mutex name", 0, &iMutex) ){
39828ae577aSmistachkin return 0;
39928ae577aSmistachkin }
40028ae577aSmistachkin assert( iMutex!=SQLITE_MUTEX_FAST && iMutex!=SQLITE_MUTEX_RECURSIVE );
40128ae577aSmistachkin return counterMutexAlloc(iMutex);
40228ae577aSmistachkin }
40328ae577aSmistachkin
test_enter_static_mutex(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])4047617e4a8Smistachkin static int SQLITE_TCLAPI test_enter_static_mutex(
40528ae577aSmistachkin void * clientData,
40628ae577aSmistachkin Tcl_Interp *interp,
40728ae577aSmistachkin int objc,
40828ae577aSmistachkin Tcl_Obj *CONST objv[]
40928ae577aSmistachkin ){
41028ae577aSmistachkin sqlite3_mutex *pMutex;
41128ae577aSmistachkin if( objc!=2 ){
41228ae577aSmistachkin Tcl_WrongNumArgs(interp, 1, objv, "NAME");
41328ae577aSmistachkin return TCL_ERROR;
41428ae577aSmistachkin }
41528ae577aSmistachkin pMutex = getStaticMutexPointer(interp, objv[1]);
41628ae577aSmistachkin if( !pMutex ){
41728ae577aSmistachkin return TCL_ERROR;
41828ae577aSmistachkin }
41928ae577aSmistachkin sqlite3_mutex_enter(pMutex);
42028ae577aSmistachkin return TCL_OK;
42128ae577aSmistachkin }
42228ae577aSmistachkin
test_leave_static_mutex(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])4237617e4a8Smistachkin static int SQLITE_TCLAPI test_leave_static_mutex(
42428ae577aSmistachkin void * clientData,
42528ae577aSmistachkin Tcl_Interp *interp,
42628ae577aSmistachkin int objc,
42728ae577aSmistachkin Tcl_Obj *CONST objv[]
42828ae577aSmistachkin ){
42928ae577aSmistachkin sqlite3_mutex *pMutex;
43028ae577aSmistachkin if( objc!=2 ){
43128ae577aSmistachkin Tcl_WrongNumArgs(interp, 1, objv, "NAME");
43228ae577aSmistachkin return TCL_ERROR;
43328ae577aSmistachkin }
43428ae577aSmistachkin pMutex = getStaticMutexPointer(interp, objv[1]);
43528ae577aSmistachkin if( !pMutex ){
43628ae577aSmistachkin return TCL_ERROR;
43728ae577aSmistachkin }
43828ae577aSmistachkin sqlite3_mutex_leave(pMutex);
43928ae577aSmistachkin return TCL_OK;
44028ae577aSmistachkin }
44128ae577aSmistachkin
test_enter_db_mutex(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])4427617e4a8Smistachkin static int SQLITE_TCLAPI test_enter_db_mutex(
4435f6d0268Sdanielk1977 void * clientData,
4445f6d0268Sdanielk1977 Tcl_Interp *interp,
4455f6d0268Sdanielk1977 int objc,
4465f6d0268Sdanielk1977 Tcl_Obj *CONST objv[]
4475f6d0268Sdanielk1977 ){
4485f6d0268Sdanielk1977 sqlite3 *db;
4495f6d0268Sdanielk1977 if( objc!=2 ){
4505f6d0268Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB");
4515f6d0268Sdanielk1977 return TCL_ERROR;
4525f6d0268Sdanielk1977 }
4535f6d0268Sdanielk1977 db = getDbPointer(interp, objv[1]);
4545f6d0268Sdanielk1977 if( !db ){
4555f6d0268Sdanielk1977 return TCL_ERROR;
4565f6d0268Sdanielk1977 }
4575f6d0268Sdanielk1977 sqlite3_mutex_enter(sqlite3_db_mutex(db));
4585f6d0268Sdanielk1977 return TCL_OK;
4595f6d0268Sdanielk1977 }
4605f6d0268Sdanielk1977
test_leave_db_mutex(void * clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])4617617e4a8Smistachkin static int SQLITE_TCLAPI test_leave_db_mutex(
4625f6d0268Sdanielk1977 void * clientData,
4635f6d0268Sdanielk1977 Tcl_Interp *interp,
4645f6d0268Sdanielk1977 int objc,
4655f6d0268Sdanielk1977 Tcl_Obj *CONST objv[]
4665f6d0268Sdanielk1977 ){
4675f6d0268Sdanielk1977 sqlite3 *db;
4685f6d0268Sdanielk1977 if( objc!=2 ){
4695f6d0268Sdanielk1977 Tcl_WrongNumArgs(interp, 1, objv, "DB");
4705f6d0268Sdanielk1977 return TCL_ERROR;
4715f6d0268Sdanielk1977 }
4725f6d0268Sdanielk1977 db = getDbPointer(interp, objv[1]);
4735f6d0268Sdanielk1977 if( !db ){
4745f6d0268Sdanielk1977 return TCL_ERROR;
4755f6d0268Sdanielk1977 }
4765f6d0268Sdanielk1977 sqlite3_mutex_leave(sqlite3_db_mutex(db));
4775f6d0268Sdanielk1977 return TCL_OK;
4785f6d0268Sdanielk1977 }
4795f6d0268Sdanielk1977
Sqlitetest_mutex_Init(Tcl_Interp * interp)4801a9ed0b2Sdanielk1977 int Sqlitetest_mutex_Init(Tcl_Interp *interp){
4811a9ed0b2Sdanielk1977 static struct {
4821a9ed0b2Sdanielk1977 char *zName;
4831a9ed0b2Sdanielk1977 Tcl_ObjCmdProc *xProc;
4841a9ed0b2Sdanielk1977 } aCmd[] = {
4851a9ed0b2Sdanielk1977 { "sqlite3_shutdown", (Tcl_ObjCmdProc*)test_shutdown },
4861a9ed0b2Sdanielk1977 { "sqlite3_initialize", (Tcl_ObjCmdProc*)test_initialize },
48759f8c08eSdanielk1977 { "sqlite3_config", (Tcl_ObjCmdProc*)test_config },
4881a9ed0b2Sdanielk1977
48928ae577aSmistachkin { "enter_static_mutex", (Tcl_ObjCmdProc*)test_enter_static_mutex },
49028ae577aSmistachkin { "leave_static_mutex", (Tcl_ObjCmdProc*)test_leave_static_mutex },
49128ae577aSmistachkin
4925f6d0268Sdanielk1977 { "enter_db_mutex", (Tcl_ObjCmdProc*)test_enter_db_mutex },
4935f6d0268Sdanielk1977 { "leave_db_mutex", (Tcl_ObjCmdProc*)test_leave_db_mutex },
4945f6d0268Sdanielk1977
495c8d75674Sdrh { "alloc_dealloc_mutex", (Tcl_ObjCmdProc*)test_alloc_mutex },
4961a9ed0b2Sdanielk1977 { "install_mutex_counters", (Tcl_ObjCmdProc*)test_install_mutex_counters },
4971a9ed0b2Sdanielk1977 { "read_mutex_counters", (Tcl_ObjCmdProc*)test_read_mutex_counters },
4981a9ed0b2Sdanielk1977 { "clear_mutex_counters", (Tcl_ObjCmdProc*)test_clear_mutex_counters },
4991a9ed0b2Sdanielk1977 };
5001a9ed0b2Sdanielk1977 int i;
5011a9ed0b2Sdanielk1977 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
5021a9ed0b2Sdanielk1977 Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
5031a9ed0b2Sdanielk1977 }
504fb45d8c5Sdrh
505fb45d8c5Sdrh Tcl_LinkVar(interp, "disable_mutex_init",
506fb45d8c5Sdrh (char*)&g.disableInit, TCL_LINK_INT);
5078a42cbd3Sdrh Tcl_LinkVar(interp, "disable_mutex_try",
5088a42cbd3Sdrh (char*)&g.disableTry, TCL_LINK_INT);
5091a9ed0b2Sdanielk1977 return SQLITE_OK;
5101a9ed0b2Sdanielk1977 }
511