Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -7,11 +7,11 @@ ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.465 2008/06/17 15:12:01 drh Exp $ +** $Id: btree.c,v 1.466 2008/06/18 17:09:10 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ @@ -1199,11 +1199,11 @@ if( !zFullPathname ){ sqlite3_free(p); return SQLITE_NOMEM; } sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname); - mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); + mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); sqlite3_mutex_enter(mutexShared); for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){ assert( pBt->nRef>0 ); if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager)) && sqlite3PagerVfs(pBt->pPager)==pVfs ){ @@ -1296,13 +1296,13 @@ /* Add the new BtShared object to the linked list sharable BtShareds. */ if( p->sharable ){ sqlite3_mutex *mutexShared; pBt->nRef = 1; - mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); - if( SQLITE_THREADSAFE ){ - pBt->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); + if( SQLITE_THREADSAFE && sqlite3Config.bCoreMutex ){ + pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST); if( pBt->mutex==0 ){ rc = SQLITE_NOMEM; db->mallocFailed = 0; goto btree_open_out; } @@ -1371,11 +1371,11 @@ sqlite3_mutex *pMaster; BtShared *pList; int removed = 0; assert( sqlite3_mutex_notheld(pBt->mutex) ); - pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); + pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); sqlite3_mutex_enter(pMaster); pBt->nRef--; if( pBt->nRef<=0 ){ if( sqlite3SharedCacheList==pBt ){ sqlite3SharedCacheList = pBt->pNext; Index: src/date.c ================================================================== --- src/date.c +++ src/date.c @@ -14,11 +14,11 @@ ** ** There is only one exported symbol in this file - the function ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.84 2008/06/15 02:51:47 drh Exp $ +** $Id: date.c,v 1.85 2008/06/18 17:09:10 danielk1977 Exp $ ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon ** in Greenwich on November 24, 4714 B.C. according to the Gregorian ** calendar system. @@ -472,19 +472,19 @@ y.s = sLocal.tm_sec; } #else { struct tm *pTm; - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); pTm = localtime(&t); y.Y = pTm->tm_year + 1900; y.M = pTm->tm_mon + 1; y.D = pTm->tm_mday; y.h = pTm->tm_hour; y.m = pTm->tm_min; y.s = pTm->tm_sec; - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } #endif y.validYMD = 1; y.validHMS = 1; y.validJD = 0; @@ -1029,14 +1029,14 @@ strftime(zBuf, 20, zFormat, &sNow); } #else { struct tm *pTm; - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); pTm = gmtime(&t); strftime(zBuf, 20, zFormat, pTm); - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } #endif sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); } Index: src/loadext.c ================================================================== --- src/loadext.c +++ src/loadext.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains code used to dynamically load extensions into ** the SQLite library. ** -** $Id: loadext.c,v 1.48 2008/06/13 18:24:27 drh Exp $ +** $Id: loadext.c,v 1.49 2008/06/18 17:09:10 danielk1977 Exp $ */ #ifndef SQLITE_CORE #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */ #endif @@ -476,11 +476,11 @@ }else #endif { int i; #ifndef SQLITE_MUTEX_NOOP - sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif sqlite3_mutex_enter(mutex); for(i=0; i=autoext.nExt ){ xInit = 0; go = 0; Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -12,11 +12,11 @@ ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.448 2008/06/18 13:27:47 drh Exp $ +** $Id: main.c,v 1.449 2008/06/18 17:09:10 danielk1977 Exp $ */ #include "sqliteInt.h" #include #ifdef SQLITE_ENABLE_FTS3 @@ -74,11 +74,11 @@ int sqlite3_initialize(void){ int rc; if( sqlite3IsInit ) return SQLITE_OK; rc = sqlite3_mutex_init(); if( rc==SQLITE_OK ){ - sqlite3_mutex *pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); + sqlite3_mutex *pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); sqlite3_mutex_enter(pMutex); if( sqlite3IsInit==0 ){ sqlite3IsInit = 1; if( rc==SQLITE_OK ) rc = sqlite3MallocInit(); if( rc==SQLITE_OK ) rc = sqlite3_os_init(); @@ -1206,15 +1206,17 @@ ); /* Allocate the sqlite data structure */ db = sqlite3MallocZero( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; - db->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); - if( db->mutex==0 ){ - sqlite3_free(db); - db = 0; - goto opendb_out; + if( sqlite3Config.bFullMutex ){ + db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); + if( db->mutex==0 ){ + sqlite3_free(db); + db = 0; + goto opendb_out; + } } sqlite3_mutex_enter(db->mutex); db->errMask = 0xff; db->priorNewRowid = 0; db->nDb = 2; @@ -1361,11 +1363,11 @@ SQLITE_DEFAULT_LOCKING_MODE); #endif opendb_out: if( db ){ - assert( db->mutex!=0 ); + assert( db->mutex!=0 || sqlite3Config.bFullMutex==0 ); sqlite3_mutex_leave(db->mutex); } if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){ sqlite3_close(db); db = 0; Index: src/malloc.c ================================================================== --- src/malloc.c +++ src/malloc.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** ** Memory allocation functions used throughout sqlite. ** -** $Id: malloc.c,v 1.18 2008/06/17 15:12:01 drh Exp $ +** $Id: malloc.c,v 1.19 2008/06/18 17:09:10 danielk1977 Exp $ */ #include "sqliteInt.h" #include #include @@ -100,12 +100,12 @@ int sqlite3MallocInit(void){ if( sqlite3Config.m.xMalloc==0 ){ sqlite3MemSetDefault(); } memset(&mem0, 0, sizeof(mem0)); - if( sqlite3Config.bMemstat && sqlite3Config.bCoreMutex ){ - mem0.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); + if( sqlite3Config.bMemstat ){ + mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); } return sqlite3Config.m.xInit(sqlite3Config.m.pAppData); } /* Index: src/mem2.c ================================================================== --- src/mem2.c +++ src/mem2.c @@ -17,11 +17,11 @@ ** leaks and memory usage errors. ** ** This file contains implementations of the low-level memory allocation ** routines specified in the sqlite3_mem_methods object. ** -** $Id: mem2.c,v 1.31 2008/06/17 17:21:18 danielk1977 Exp $ +** $Id: mem2.c,v 1.32 2008/06/18 17:09:10 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** This version of the memory allocator is used only if the @@ -160,11 +160,11 @@ /* ** Initialize the memory allocation subsystem. */ static int sqlite3MemInit(void *NotUsed){ - mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); return SQLITE_OK; } /* ** Deinitialize the memory allocation subsystem. Index: src/mem3.c ================================================================== --- src/mem3.c +++ src/mem3.c @@ -18,11 +18,11 @@ ** fixed memory pool is SQLITE_MEMORY_SIZE bytes. ** ** This version of the memory allocation subsystem is used if ** and only if SQLITE_MEMORY_SIZE is defined. ** -** $Id: mem3.c,v 1.13 2008/06/13 18:24:27 drh Exp $ +** $Id: mem3.c,v 1.14 2008/06/18 17:09:10 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** This version of the memory allocator is used only when @@ -212,11 +212,11 @@ ** Also: Initialize the memory allocation subsystem the first time ** this routine is called. */ static void memsys3Enter(void){ if( mem.mutex==0 ){ - mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); + mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); mem.aPool[0].u.hdr.size4x = SQLITE_MEMORY_SIZE/2 + 2; mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.prevSize = SQLITE_MEMORY_SIZE/8; mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.size4x = 1; mem.iMaster = 1; mem.szMaster = SQLITE_MEMORY_SIZE/8; Index: src/mem4.c ================================================================== --- src/mem4.c +++ src/mem4.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** -** $Id: mem4.c,v 1.2 2008/02/14 23:26:56 drh Exp $ +** $Id: mem4.c,v 1.3 2008/06/18 17:09:10 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** This version of the memory allocator attempts to obtain memory @@ -110,11 +110,11 @@ ** Enter the mutex mem.mutex. Allocate it if it is not already allocated. ** The mmap() region is initialized the first time this routine is called. */ static void memsys4Enter(void){ if( mem.mutex==0 ){ - mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); + mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); } sqlite3_mutex_enter(mem.mutex); } /* Index: src/mem5.c ================================================================== --- src/mem5.c +++ src/mem5.c @@ -18,11 +18,11 @@ ** fixed memory pool is SQLITE_POW2_MEMORY_SIZE bytes. ** ** This version of the memory allocation subsystem is used if ** and only if SQLITE_POW2_MEMORY_SIZE is defined. ** -** $Id: mem5.c,v 1.5 2008/06/13 18:24:27 drh Exp $ +** $Id: mem5.c,v 1.6 2008/06/18 17:09:10 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** This version of the memory allocator is used only when @@ -191,11 +191,11 @@ if( mem.mutex==0 ){ int i; assert( sizeof(Mem5Block)==POW2_MIN ); assert( (SQLITE_POW2_MEMORY_SIZE % POW2_MAX)==0 ); assert( SQLITE_POW2_MEMORY_SIZE>=POW2_MAX ); - mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); + mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); sqlite3_mutex_enter(mem.mutex); for(i=0; ixMutexInit(); - if( rc==SQLITE_OK ){ - pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER); - assert(pMaster); - p->xMutexEnter(pMaster); - assert( sqlite3Config.mutex.xMutexAlloc==0 - || sqlite3Config.mutex.xMutexAlloc==p->xMutexAlloc - ); - if( !sqlite3Config.mutex.xMutexAlloc ){ - sqlite3Config.mutex = *p; - } - p->xMutexLeave(pMaster); - } - }else{ - rc = sqlite3Config.mutex.xMutexInit(); + int rc = SQLITE_OK; + if( sqlite3Config.bCoreMutex ){ + if( !sqlite3Config.mutex.xMutexAlloc ){ + /* If the xMutexAlloc method has not been set, then the user did not + ** install a mutex implementation via sqlite3_config() prior to + ** sqlite3_initialize() being called. This block copies pointers to + ** the default implementation into the sqlite3Config structure. + ** + ** The danger is that although sqlite3_config() is not a threadsafe + ** API, sqlite3_initialize() is, and so multiple threads may be + ** attempting to run this function simultaneously. To guard write + ** access to the sqlite3Config structure, the 'MASTER' static mutex + ** is obtained before modifying it. + */ + sqlite3_mutex_methods *p = sqlite3DefaultMutex(); + sqlite3_mutex *pMaster = 0; + + rc = p->xMutexInit(); + if( rc==SQLITE_OK ){ + pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER); + assert(pMaster); + p->xMutexEnter(pMaster); + assert( sqlite3Config.mutex.xMutexAlloc==0 + || sqlite3Config.mutex.xMutexAlloc==p->xMutexAlloc + ); + if( !sqlite3Config.mutex.xMutexAlloc ){ + sqlite3Config.mutex = *p; + } + p->xMutexLeave(pMaster); + } + }else{ + rc = sqlite3Config.mutex.xMutexInit(); + } } return rc; } @@ -78,10 +80,17 @@ ** Retrieve a pointer to a static mutex or allocate a new dynamic one. */ sqlite3_mutex *sqlite3_mutex_alloc(int id){ return sqlite3Config.mutex.xMutexAlloc(id); } + +sqlite3_mutex *sqlite3MutexAlloc(int id){ + if( !sqlite3Config.bCoreMutex ){ + return 0; + } + return sqlite3Config.mutex.xMutexAlloc(id); +} /* ** Free a dynamic mutex. */ void sqlite3_mutex_free(sqlite3_mutex *p){ Index: src/os.c ================================================================== --- src/os.c +++ src/os.c @@ -11,11 +11,11 @@ ****************************************************************************** ** ** This file contains OS interface code that is common to all ** architectures. ** -** $Id: os.c,v 1.113 2008/06/15 02:51:48 drh Exp $ +** $Id: os.c,v 1.114 2008/06/18 17:09:10 danielk1977 Exp $ */ #define _SQLITE_OS_C_ 1 #include "sqliteInt.h" #undef _SQLITE_OS_C_ @@ -205,11 +205,11 @@ #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); if( rc ) return 0; #endif #ifndef SQLITE_MUTEX_NOOP - mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); + mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif sqlite3_vfs *pVfs = 0; static int isInit = 0; sqlite3_mutex_enter(mutex); if( !isInit ){ @@ -226,11 +226,11 @@ /* ** Unlink a VFS from the linked list */ static void vfsUnlink(sqlite3_vfs *pVfs){ - assert( sqlite3_mutex_held(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)) ); + assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) ); if( pVfs==0 ){ /* No-op */ }else if( vfsList==pVfs ){ vfsList = pVfs->pNext; }else if( vfsList ){ @@ -256,11 +256,11 @@ #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); if( rc ) return rc; #endif #ifndef SQLITE_MUTEX_NOOP - mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); + mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif sqlite3_vfs_find(0); /* Make sure we are initialized */ sqlite3_mutex_enter(mutex); vfsUnlink(pVfs); if( makeDflt || vfsList==0 ){ @@ -278,11 +278,11 @@ /* ** Unregister a VFS so that it is no longer accessible. */ int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ #ifndef SQLITE_MUTEX_NOOP - sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif sqlite3_mutex_enter(mutex); vfsUnlink(pVfs); sqlite3_mutex_leave(mutex); return SQLITE_OK; Index: src/os_unix.c ================================================================== --- src/os_unix.c +++ src/os_unix.c @@ -10,11 +10,11 @@ ** ****************************************************************************** ** ** This file contains code that is specific to Unix systems. ** -** $Id: os_unix.c,v 1.187 2008/06/13 18:24:27 drh Exp $ +** $Id: os_unix.c,v 1.188 2008/06/18 17:09:10 danielk1977 Exp $ */ #include "sqliteInt.h" #if OS_UNIX /* This file is used on unix only */ /* #define SQLITE_ENABLE_LOCKING_STYLE 0 */ @@ -365,14 +365,14 @@ /* ** Helper functions to obtain and relinquish the global mutex. */ static void enterMutex(){ - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } static void leaveMutex(){ - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } #if SQLITE_THREADSAFE /* ** This variable records whether or not threads can override each others Index: src/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -16,11 +16,11 @@ ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.458 2008/06/17 15:12:01 drh Exp $ +** @(#) $Id: pager.c,v 1.459 2008/06/18 17:09:10 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include #include @@ -516,11 +516,11 @@ static void pagerEnter(Pager *p){ p->iInUseDB++; if( p->iInUseMM && p->iInUseDB==1 ){ #ifndef SQLITE_MUTEX_NOOP sqlite3_mutex *mutex; - mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); + mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2); #endif p->iInUseDB = 0; sqlite3_mutex_enter(mutex); p->iInUseDB = 1; sqlite3_mutex_leave(mutex); @@ -614,13 +614,13 @@ */ static void lruListAdd(PgHdr *pPg){ listAdd(&pPg->pPager->lru, &pPg->free, pPg); #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT if( !pPg->pPager->memDb ){ - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); listAdd(&sqlite3LruPageList, &pPg->gfree, pPg); - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); } #endif } /* @@ -630,13 +630,13 @@ */ static void lruListRemove(PgHdr *pPg){ listRemove(&pPg->pPager->lru, &pPg->free, pPg); #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT if( !pPg->pPager->memDb ){ - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); listRemove(&sqlite3LruPageList, &pPg->gfree, pPg); - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); } #endif } /* @@ -649,15 +649,15 @@ static void lruListSetFirstSynced(Pager *pPager){ pPager->lru.pFirstSynced = pPager->lru.pFirst; #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT if( !pPager->memDb ){ PgHdr *p; - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); for(p=sqlite3LruPageList.pFirst; p && p->needSync; p=p->gfree.pNext); assert(p==pPager->lru.pFirstSynced || p==sqlite3LruPageList.pFirstSynced); sqlite3LruPageList.pFirstSynced = p; - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); } #endif } /* @@ -2362,11 +2362,11 @@ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT pPager->iInUseMM = 0; pPager->iInUseDB = 0; if( !memDb ){ #ifndef SQLITE_MUTEX_NOOP - sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2); #endif sqlite3_mutex_enter(mutex); pPager->pNext = sqlite3PagerList; if( sqlite3PagerList ){ assert( sqlite3PagerList->pPrev==0 ); @@ -2749,11 +2749,11 @@ */ int sqlite3PagerClose(Pager *pPager){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT if( !MEMDB ){ #ifndef SQLITE_MUTEX_NOOP - sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2); #endif sqlite3_mutex_enter(mutex); if( pPager->pPrev ){ pPager->pPrev->pNext = pPager->pNext; }else{ @@ -3276,11 +3276,11 @@ /* Acquire the memory-management mutex */ #ifndef SQLITE_MUTEX_NOOP sqlite3_mutex *mutex; /* The MEM2 mutex */ - mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); + mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2); #endif sqlite3_mutex_enter(mutex); /* Signal all database connections that memory management wants ** to have access to the pagers. @@ -3294,11 +3294,11 @@ PgHdr *pRecycled; /* Try to find a page to recycle that does not require a sync(). If ** this is not possible, find one that does require a sync(). */ - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); pPg = sqlite3LruPageList.pFirstSynced; while( pPg && (pPg->needSync || pPg->pPager->iInUseDB) ){ pPg = pPg->gfree.pNext; } if( !pPg ){ @@ -3305,11 +3305,11 @@ pPg = sqlite3LruPageList.pFirst; while( pPg && pPg->pPager->iInUseDB ){ pPg = pPg->gfree.pNext; } } - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU)); /* If pPg==0, then the block above has failed to find a page to ** recycle. In this case return early - no further memory will ** be released. */ Index: src/random.c ================================================================== --- src/random.c +++ src/random.c @@ -13,11 +13,11 @@ ** generator (PRNG) for SQLite. ** ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** -** $Id: random.c,v 1.23 2008/03/21 16:45:47 drh Exp $ +** $Id: random.c,v 1.24 2008/06/18 17:09:10 danielk1977 Exp $ */ #include "sqliteInt.h" /* All threads share a single random number generator. @@ -90,14 +90,11 @@ /* ** Return N random bytes. */ void sqlite3_randomness(int N, void *pBuf){ unsigned char *zBuf = pBuf; - static sqlite3_mutex *mutex = 0; - if( mutex==0 ){ - mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG); - } + sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG); sqlite3_mutex_enter(mutex); while( N-- ){ *(zBuf++) = randomByte(); } sqlite3_mutex_leave(mutex); Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.713 2008/06/18 13:27:47 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.714 2008/06/18 17:09:10 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* @@ -1804,10 +1804,11 @@ void *sqlite3PageMalloc(int); void sqlite3PageFree(void*); void sqlite3MemSetDefault(void); sqlite3_mutex_methods *sqlite3DefaultMutex(void); +sqlite3_mutex *sqlite3MutexAlloc(int); int sqlite3IsNaN(double); char *sqlite3MPrintf(sqlite3*,const char*, ...); char *sqlite3VMPrintf(sqlite3*,const char*, va_list); Index: src/test3.c ================================================================== --- src/test3.c +++ src/test3.c @@ -11,11 +11,11 @@ ************************************************************************* ** Code for testing the btree.c module in SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test3.c,v 1.97 2008/06/06 11:11:26 danielk1977 Exp $ +** $Id: test3.c,v 1.98 2008/06/18 17:09:10 danielk1977 Exp $ */ #include "sqliteInt.h" #include "btreeInt.h" #include "tcl.h" #include @@ -76,11 +76,11 @@ if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR; if( Tcl_GetInt(interp, argv[3], &flags) ) return TCL_ERROR; nRefSqlite3++; if( nRefSqlite3==1 ){ sDb.pVfs = sqlite3_vfs_find(0); - sDb.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); + sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); sqlite3_mutex_enter(sDb.mutex); } rc = sqlite3BtreeOpen(argv[1], &sDb, &pBt, flags, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB); if( rc!=SQLITE_OK ){ Index: src/test_mutex.c ================================================================== --- src/test_mutex.c +++ src/test_mutex.c @@ -8,11 +8,11 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** -** $Id: test_mutex.c,v 1.1 2008/06/18 09:45:56 danielk1977 Exp $ +** $Id: test_mutex.c,v 1.2 2008/06/18 17:09:10 danielk1977 Exp $ */ #include "tcl.h" #include "sqlite3.h" #include @@ -244,18 +244,55 @@ for(ii=0; ii<8; ii++){ g.aCounter[ii] = 0; } return TCL_OK; } + +/* +** sqlite3_config OPTION +*/ +static int test_config( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + struct ConfigOption { + const char *zName; + int iValue; + } aOpt[] = { + {"singlethread", SQLITE_CONFIG_SINGLETHREAD}, + {"multithread", SQLITE_CONFIG_MULTITHREAD}, + {"serialized", SQLITE_CONFIG_SERIALIZED}, + {0, 0} + }; + int s = sizeof(struct ConfigOption); + int i; + int rc; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + + if( Tcl_GetIndexFromObjStruct(interp, objv[1], aOpt, s, "flag", 0, &i) ){ + return TCL_ERROR; + } + + rc = sqlite3_config(aOpt[i].iValue); + Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); + return TCL_OK; +} int Sqlitetest_mutex_Init(Tcl_Interp *interp){ static struct { char *zName; Tcl_ObjCmdProc *xProc; } aCmd[] = { { "sqlite3_shutdown", (Tcl_ObjCmdProc*)test_shutdown }, { "sqlite3_initialize", (Tcl_ObjCmdProc*)test_initialize }, + { "sqlite3_config", (Tcl_ObjCmdProc*)test_config }, { "install_mutex_counters", (Tcl_ObjCmdProc*)test_install_mutex_counters }, { "read_mutex_counters", (Tcl_ObjCmdProc*)test_read_mutex_counters }, { "clear_mutex_counters", (Tcl_ObjCmdProc*)test_clear_mutex_counters }, }; Index: src/vdbeapi.c ================================================================== --- src/vdbeapi.c +++ src/vdbeapi.c @@ -11,11 +11,11 @@ ************************************************************************* ** ** This file contains code use to implement APIs that are part of the ** VDBE. ** -** $Id: vdbeapi.c,v 1.132 2008/05/16 15:24:58 danielk1977 Exp $ +** $Id: vdbeapi.c,v 1.133 2008/06/18 17:09:10 danielk1977 Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT @@ -66,14 +66,14 @@ ** Add vdbe p to the end of the statement lru list. It is assumed that ** p is not already part of the list when this is called. The lru list ** is protected by the SQLITE_MUTEX_STATIC_LRU mutex. */ static void stmtLruAdd(Vdbe *p){ - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); if( p->pLruPrev || p->pLruNext || sqlite3LruStatements.pFirst==p ){ - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); return; } assert( stmtLruCheck() ); @@ -88,11 +88,11 @@ sqlite3LruStatements.pLast = p; } assert( stmtLruCheck() ); - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); } /* ** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is already held, remove ** statement p from the least-recently-used statement list. If the @@ -121,13 +121,13 @@ ** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is not held, remove ** statement p from the least-recently-used statement list. If the ** statement is not currently part of the list, this call is a no-op. */ static void stmtLruRemove(Vdbe *p){ - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); stmtLruRemoveNomutex(p); - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); } /* ** Try to release n bytes of memory by freeing buffers associated ** with the memory registers of currently unused vdbes. @@ -135,11 +135,11 @@ int sqlite3VdbeReleaseMemory(int n){ Vdbe *p; Vdbe *pNext; int nFree = 0; - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); for(p=sqlite3LruStatements.pFirst; p && nFreepLruNext; /* For each statement handle in the lru list, attempt to obtain the ** associated database mutex. If it cannot be obtained, continue @@ -150,11 +150,11 @@ nFree += sqlite3VdbeReleaseBuffers(p); stmtLruRemoveNomutex(p); sqlite3_mutex_leave(p->db->mutex); } } - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); return nFree; } /* Index: test/mutex1.test ================================================================== --- test/mutex1.test +++ test/mutex1.test @@ -7,11 +7,11 @@ # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # -# $Id: mutex1.test,v 1.1 2008/06/18 09:45:56 danielk1977 Exp $ +# $Id: mutex1.test,v 1.2 2008/06/18 17:09:10 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl proc mutex_counters {varname} { @@ -73,14 +73,56 @@ do_test mutex1-1.9 { mutex_counters counters list $counters(total) $counters(static_master) } {0 0} +#------------------------------------------------------------------------- +# Tests mutex1-2.* test the three thread-safety related modes that +# can be selected using sqlite3_config: +# +# * Serialized mode, +# * Multi-threaded mode, +# * Single-threaded mode. +# + +foreach {mode mutexes} { + singlethread {} + multithread {fast static_master static_mem static_prng} + serialized {fast recursive static_master static_mem static_prng} +} { + do_test mutex1.2.$mode.1 { + catch {db close} + sqlite3_shutdown + sqlite3_config $mode + } SQLITE_OK + + do_test mutex1.2.$mode.2 { + clear_mutex_counters + sqlite3 db test.db + catchsql { CREATE TABLE abc(a, b, c) } + db eval { + INSERT INTO abc VALUES(1, 2, 3); + } + } {} + + do_test mutex1.2.$mode.3 { + mutex_counters counters + + set res [list] + foreach {key value} [array get counters] { + if {$key ne "total" && $value > 0} { + lappend res $key + } + } + lsort $res + } $mutexes +} do_test mutex1-X { + db close sqlite3_shutdown clear_mutex_counters install_mutex_counters 0 } {SQLITE_OK} finish_test ADDED test/mutex2.test Index: test/mutex2.test ================================================================== --- /dev/null +++ test/mutex2.test @@ -0,0 +1,72 @@ +# 2007 March 26 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# This file runs some other test files after calling sqlite3_config to +# set the thread-safety mode to SQLITE_CONFIG_SINGLETHREAD and +# SQLITE_CONFIG_MULTITHREAD (instead of the default SQLITE_CONFIG_SERIALIZED). +# +# $Id: mutex2.test,v 1.1 2008/06/18 17:09:10 danielk1977 Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +ifcapable {!pager_pragmas} { + finish_test + return +} + +rename finish_test really_finish_test2 +proc finish_test {} {} +set ISQUICK 1 + +rename do_test really_do_test +proc do_test {args} { + set sc [concat really_do_test "mutex2-${::thread_mode}.[lindex $args 0]" \ + [lrange $args 1 end]] + eval $sc +} + +foreach ::thread_mode {singlethread multithread} { + do_test mutex2-$::thread_mode.0 { + catch {db close} + sqlite3_shutdown + sqlite3_config $::thread_mode + } SQLITE_OK + + source $testdir/delete.test + source $testdir/delete2.test + source $testdir/insert.test + source $testdir/rollback.test + source $testdir/select1.test + source $testdir/select2.test + source $testdir/trans.test + source $testdir/update.test + source $testdir/vacuum.test + source $testdir/types.test + source $testdir/types2.test + source $testdir/types3.test + + #source $testdir/malloc.test + #source $testdir/ioerr.test +} + +do_test mutex2-X { + catch {db close} + sqlite3_shutdown + sqlite3_config serialized +} SQLITE_OK + +rename finish_test "" +rename really_finish_test2 finish_test +rename do_test "" +rename really_do_test do_test +finish_test + Index: test/quick.test ================================================================== --- test/quick.test +++ test/quick.test @@ -4,11 +4,11 @@ # May you share freely, never taking more than you give. # #*********************************************************************** # This file runs all tests. # -# $Id: quick.test,v 1.78 2008/04/19 20:34:19 drh Exp $ +# $Id: quick.test,v 1.79 2008/06/18 17:09:10 danielk1977 Exp $ proc lshift {lvar} { upvar $lvar l set ret [lindex $l 0] set l [lrange $l 1 end] @@ -62,10 +62,11 @@ malloc3.test malloc4.test memleak.test misc7.test misuse.test + mutex2.test onefile.test quick.test soak.test speed1.test speed1p.test Index: test/veryquick.test ================================================================== --- test/veryquick.test +++ test/veryquick.test @@ -4,11 +4,11 @@ # May you share freely, never taking more than you give. # #*********************************************************************** # This file runs all tests. # -# $Id: veryquick.test,v 1.3 2008/04/19 20:34:19 drh Exp $ +# $Id: veryquick.test,v 1.4 2008/06/18 17:09:10 danielk1977 Exp $ proc lshift {lvar} { upvar $lvar l set ret [lindex $l 0] set l [lrange $l 1 end] @@ -84,10 +84,11 @@ mallocF.test mallocG.test memleak.test misc7.test misuse.test + mutex2.test onefile.test quick.test soak.test speed1.test speed1p.test