]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Reenable the memory management logic. The quick.test script now runs with
authordrh <drh@noemail.net>
Wed, 22 Aug 2007 00:39:19 +0000 (00:39 +0000)
committerdrh <drh@noemail.net>
Wed, 22 Aug 2007 00:39:19 +0000 (00:39 +0000)
SQLITE_MEMDEBUG and SQLITE_ENABLE_MEMORY_MANAGEMENT. 7 minor errors. (CVS 4265)

FossilOrigin-Name: 1914044b8832041f13b20ead613bd13725425d7a

14 files changed:
manifest
manifest.uuid
src/btree.c
src/btreeInt.h
src/main.c
src/malloc.c
src/mutex.c
src/pager.c
src/prepare.c
src/sqlite.h.in
src/tclsqlite.c
src/test1.c
src/vdbeapi.c
test/capi2.test

index fa52920b334a1e5b88bb903ea99b5cf5f8a97f15..b1e1d3fcbc0b0a8f3b272e54de5160a4e7f10df2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C All\smutexing\sand\slocking\sappears\sto\sbe\sin\splace.\s\sNow\swe\sjust\shave\sto\ntest\sit\sand\smake\sit\sall\swork.\s(CVS\s4264)
-D 2007-08-21T20:25:40
+C Reenable\sthe\smemory\smanagement\slogic.\s\sThe\squick.test\sscript\snow\sruns\swith\nSQLITE_MEMDEBUG\sand\sSQLITE_ENABLE_MEMORY_MANAGEMENT.\s7\sminor\serrors.\s(CVS\s4265)
+D 2007-08-22T00:39:20
 F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe
 F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -80,9 +80,9 @@ F src/alter.c f0aac0060ae8102e58f210b44d35b53438d53173
 F src/analyze.c a14237d869c6bea0846493b59317e4097e81a0b6
 F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8
 F src/auth.c 083c1205b45e3f52291ec539d396b4fc557856b3
-F src/btree.c 4cfe2fe8d61dd906662833732919dc27116ffce7
+F src/btree.c e35f1d7d662681a567cafaef6dba529ccd577a0d
 F src/btree.h aeb85d6a48573785666fb97566bf5802d5f9b7ca
-F src/btreeInt.h e93edf57832278138b98cf60cbc54241103c6988
+F src/btreeInt.h 7fc6e51dc3d4bbed15639a8ea1aae737631d6670
 F src/build.c 2159551184160e2cf17ff945e9a05fbe6f331c3d
 F src/callback.c fdd527372162a974094103eae82119fcfcf11260
 F src/complete.c b6dea59fb6d7b3201fa1e0e552cda8c2258a4f50
@@ -97,12 +97,12 @@ F src/insert.c 633322aef1799f6604fa805e12488bc628570b0c
 F src/legacy.c a83519a8fbb488c3155fca577b010d590ec479e9
 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
 F src/loadext.c dd803303fd06ef0b13913faaa4a7fc7d8c8c4e77
-F src/main.c 7cec512d2c83afea2b83977b384633b9edb1ae1d
-F src/malloc.c c291b07b6b03ba1a1db0c24f630b745071679ed0
+F src/main.c 316381eeaf9c166a9edfe0e7d65b363432ed95ca
+F src/malloc.c f5ace943194fba04f09b590496a751a5ed6734f1
 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
 F src/mem1.c 30bf8be3846f92fdf88c490c5e5378512383bcbe
 F src/mem2.c 482f0aaf14e8ef1db64cb8c5b9a9bfe708297c92
-F src/mutex.c 56bd91271f18300aa7da45608bd8956abe471d10
+F src/mutex.c 839c4226939081a4b736bb7ab6520b2f835be8ae
 F src/os.c 89b93d67bc436c2d9df4b5d296f30a59144e55bb
 F src/os.h 399c89cafa93b9ef35c3dc70f77644d10936b535
 F src/os_common.h a5c446d3b93f09f369d13bf217de4bed3437dd1c
@@ -114,23 +114,23 @@ F src/os_unix.c 7aad42b1ee70d68034a4ac45fa822edccdc3d9e6
 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
 F src/os_win.c 29c0e19c1072679a4c7818c49fab2f35d2ad7747
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c df16604a2a8c6808cd9b309a7e1bdb556d868c8e
+F src/pager.c d68e8c7b7e258c3e22c7872b602ff1b00d6cb41a
 F src/pager.h 53087c6fb9db01aed17c7fd044662a27507e89b8
 F src/parse.y 2d2ce439dc6184621fb0b86f4fc5aca7f391a590
 F src/pragma.c 9b989506a1b7c8aecd6befb8235e2f57a4aba7e5
-F src/prepare.c d30764fabc3eb704c0d18bdeb9f38df028f19567
+F src/prepare.c 7c11bab711f44ef12950816a8cfe495ccb295648
 F src/printf.c a8f46e0ed360c18d40e89aa636533be300b406c2
 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
 F src/select.c 98c367bce3f38c5adfcc97de9ab5c79b0e5dc2b2
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c ac29402b538515fa4697282387be9c1205e6e9eb
-F src/sqlite.h.in b2a7484c024c42f2e639f289beb7c8db36513a2c
+F src/sqlite.h.in 39f920631c49a8a79502d8b7908e608d7a0029bd
 F src/sqlite3ext.h 647a6b8a8f76ff6c9611e4a071531d8e63ff2d6b
 F src/sqliteInt.h 23eb6a5b1f10d5d3d34c3c7846b7c3b93acf1276
 F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa
 F src/table.c c725e47f6f3092b9a7b569fc58e408e2173ee008
-F src/tclsqlite.c 299fb45c5cf983b49b2c984b87b936b8132fbfe2
-F src/test1.c 70b96fc5ef8d013e2da0f936a62fe76e387faf83
+F src/tclsqlite.c 92e06e076d613484aa2afc5ad830d9080de92347
+F src/test1.c d665d85c7a4e4aef588d5c6f01761082358d291d
 F src/test2.c 4f742e99ed1bea5c14692f627bdb59a146f30504
 F src/test3.c 2e4da0fe90a0aa8cf9276ea34cbe92e91dc1db07
 F src/test4.c d97b87919dc3db1cc5fccc04a33f030d5940e1a9
@@ -159,7 +159,7 @@ F src/vacuum.c 318ccae7c4e3ddf241aeaee4d2611bfe1949a373
 F src/vdbe.c 9d4d00589c174aad9a616f1615464ddddebba0ec
 F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3
 F src/vdbeInt.h 39fb069ce04137545ca0bc790f80ddc64a8c99d9
-F src/vdbeapi.c e12f99aa859118afbffff67eb32df36d564b5c80
+F src/vdbeapi.c 62cc5b08fc33c05fe8a74b6bd78aff5e0c0ba4f2
 F src/vdbeaux.c b0aeed4ff33352904b392ee6c7408bae5b141b9b
 F src/vdbeblob.c d12ed95dac0992e1e372d079d76af047cc42f7c7
 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
@@ -205,7 +205,7 @@ F test/btree8.test fadc112bcbd6a0c622d34c813fc8a648eacf8804
 F test/btree9.test 5d8711b241145b90f65dd1795d5dd8290846fa5e
 F test/busy.test 0271c854738e23ad76e10d4096a698e5af29d211
 F test/cache.test 008668c54b38ba5b4c1134ba51447b01ac5520ec
-F test/capi2.test 7ecc9b342cc9ec27b53bbf95724cf2e5874fd496
+F test/capi2.test 3c5066836cbaa9923bcc8282c010aa227bb5efd4
 F test/capi3.test f4e77c300d870653f9fc1b20bef6788f0790b3f1
 F test/capi3b.test 664eb55318132f292f2c436f90906f578cad6b97
 F test/capi3c.test 76a3fb94755288a2977ee387e95305e6224c0198
@@ -558,7 +558,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 9287276191a582c1cf7cf6b71d8399727d8e534d
-R c2481d632c284d895f66ae3d4866a0ab
+P 0f7941aef976aa4f3be3e0046edd1ae042e5d9a3
+R a1e419f66e7c78d94227b10198dd19bc
 U drh
-Z aa5c15d669e0ef0f762ec1f2d438a5a0
+Z 60989ee4c1d273be71e169d0d08476db
index 780479153af77e6a9843e78403abcba02dd87056..aaeb86537e6e471508f2d673cca1fac748c58a5e 100644 (file)
@@ -1 +1 @@
-0f7941aef976aa4f3be3e0046edd1ae042e5d9a3
\ No newline at end of file
+1914044b8832041f13b20ead613bd13725425d7a
\ No newline at end of file
index 3e8ef4929e0d29431c6c8cecc589522f5f9b53e2..c99e3ca0fe61171e92a0731aa22190396350087e 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.406 2007/08/21 19:33:56 drh Exp $
+** $Id: btree.c,v 1.407 2007/08/22 00:39:20 drh Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** See the header comment on "btreeInt.h" for additional information.
@@ -31,12 +31,14 @@ static const char zMagicHeader[] = SQLITE_FILE_HEADER;
 int sqlite3_btree_trace=0;  /* True to enable tracing */
 #endif
 
+
+
 #ifndef SQLITE_OMIT_SHARED_CACHE
 /*
 ** A flag to indicate whether or not shared cache is enabled.  Also,
 ** a list of BtShared objects that are eligible for participation
 ** in shared cache.  The variables have file scope during normal builds,
-** but the test harness needs to access these variables so make them
+** but the test harness needs to access these variables so we make them
 ** global for test builds.
 */
 #ifdef SQLITE_TEST
index 6d2335870a723fddf33d3e442fdadd6fa99a5c76..d67a7cf08c65c94a266f0ca20b8aa17498b4790b 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btreeInt.h,v 1.8 2007/08/20 22:48:42 drh Exp $
+** $Id: btreeInt.h,v 1.9 2007/08/22 00:39:20 drh Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** For a detailed discussion of BTrees, refer to
@@ -382,10 +382,10 @@ struct BtShared {
   int nTransaction;     /* Number of open transactions (read + write) */
   void *pSchema;        /* Pointer to space allocated by sqlite3BtreeSchema() */
   void (*xFreeSchema)(void*);  /* Destructor for BtShared.pSchema */
+  sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */
 #ifndef SQLITE_OMIT_SHARED_CACHE
   int nRef;             /* Number of references to this structure */
   BtShared *pNext;      /* Next on a list of sharable BtShared structs */
-  sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */
   BtLock *pLock;        /* List of locks held on this shared-btree struct */
 #endif
 };
index 69e49752b77c95d52c38abb1c3ee01f3788c6251..1793911a5d6437f6d89fdb74b76ca63cae9b4ed0 100644 (file)
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.393 2007/08/21 19:33:56 drh Exp $
+** $Id: main.c,v 1.394 2007/08/22 00:39:20 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -771,10 +771,10 @@ const char *sqlite3_errmsg(sqlite3 *db){
     return sqlite3ErrStr(SQLITE_NOMEM);
   }
   sqlite3_mutex_enter(db->mutex);
-  assert( !db->mallocFailed );
   if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){
     return sqlite3ErrStr(SQLITE_MISUSE);
   }
+  assert( !db->mallocFailed );
   z = (char*)sqlite3_value_text(db->pErr);
   if( z==0 ){
     z = sqlite3ErrStr(db->errCode);
index 482e7636ffc9931a0bb4d90e9ad85c1231da191c..c8a5025ea12052864da044b694f9fb349125b7cf 100644 (file)
@@ -12,7 +12,7 @@
 ** Memory allocation functions used throughout sqlite.
 **
 **
-** $Id: malloc.c,v 1.8 2007/08/21 19:33:56 drh Exp $
+** $Id: malloc.c,v 1.9 2007/08/22 00:39:20 drh Exp $
 */
 #include "sqliteInt.h"
 #include <stdarg.h>
@@ -58,7 +58,7 @@ void sqlite3_soft_heap_limit(int n){
 ** Release memory held by SQLite instances created by the current thread.
 */
 int sqlite3_release_memory(int n){
-#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
   return sqlite3PagerReleaseMemory(n);
 #else
   return SQLITE_OK;
index db2e33ed06e0c7e2f9bd2047e96c7b6783e3240c..4e52935c6303054bb151f0c18b045e877ad60923 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains the C functions that implement mutexes for
 ** use by the SQLite core.
 **
-** $Id: mutex.c,v 1.6 2007/08/21 10:44:16 drh Exp $
+** $Id: mutex.c,v 1.7 2007/08/22 00:39:20 drh Exp $
 */
 /*
 ** If SQLITE_MUTEX_APPDEF is defined, then this whole module is
@@ -126,7 +126,7 @@ struct sqlite3_mutex {
 ** that means that a mutex could not be allocated. 
 */
 sqlite3_mutex *sqlite3_mutex_alloc(int id){
-  static sqlite3_mutex aStatic[3];
+  static sqlite3_mutex aStatic[4];
   sqlite3_mutex *pNew = 0;
   switch( id ){
     case SQLITE_MUTEX_FAST:
@@ -139,6 +139,8 @@ sqlite3_mutex *sqlite3_mutex_alloc(int id){
       break;
     }
     default: {
+      assert( id-SQLITE_MUTEX_STATIC_MASTER >= 0 );
+      assert( id-SQLITE_MUTEX_STATIC_MASTER < count(aStatic) );
       pNew = &aStatic[id-SQLITE_MUTEX_STATIC_MASTER];
       pNew->id = id;
       break;
@@ -269,6 +271,7 @@ sqlite3_mutex *sqlite3_mutex_alloc(int iType){
     { PTHREAD_MUTEX_INITIALIZER, },
     { PTHREAD_MUTEX_INITIALIZER, },
     { PTHREAD_MUTEX_INITIALIZER, },
+    { PTHREAD_MUTEX_INITIALIZER, },
   };
   sqlite3_mutex *p;
   switch( iType ){
@@ -291,6 +294,8 @@ sqlite3_mutex *sqlite3_mutex_alloc(int iType){
       break;
     }
     default: {
+      assert( iType-2 >= 0 );
+      assert( iType-2 < count(staticMutexes) );
       p = &staticMutexes[iType-2];
       p->id = iType;
       break;
index 208241a5c603537d2b456f482aa5605352a7aefa..d75bc5fe2026ef9511beaf0cdb1b4552836e8748 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.364 2007/08/21 14:27:02 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.365 2007/08/22 00:39:20 drh Exp $
 */
 #ifndef SQLITE_OMIT_DISKIO
 #include "sqliteInt.h"
@@ -362,7 +362,10 @@ struct Pager {
   int nHash;                  /* Size of the pager hash table */
   PgHdr **aHash;              /* Hash table to map page number to PgHdr */
 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  Pager *pNext;               /* Linked list of pagers in this thread */
+  Pager *pNext;               /* Doubly linked list of pagers on which */
+  Pager *pPrev;               /* sqlite3_release_memory() will work */
+  int iInUseMM;               /* Non-zero if unavailable to MM */
+  int iInUseDB;               /* Non-zero if in sqlite3_release_memory() */
 #endif
   char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
   char dbFileVers[16];        /* Changes whenever database file changes */
@@ -383,6 +386,15 @@ int sqlite3_pager_pgfree_count = 0;    /* Number of cache pages freed */
 # define PAGER_INCR(v)
 #endif
 
+/*
+** The following variable points to the head of a double-linked list
+** of all pagers that are eligible for page stealing by the
+** sqlite3_release_memory() interface.  Access to this list is
+** protected by the SQLITE_MUTEX_STATIC_MEM2 mutex.
+*/
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+static Pager *sqlite3PagerList = 0;
+#endif
 
 
 /*
@@ -452,6 +464,38 @@ static const unsigned char aJournalMagic[] = {
 */
 #define PAGER_MAX_PGNO 2147483647
 
+/*
+** The pagerEnter() and pagerLeave() routines acquire and release
+** a mutex on each pager.  The mutex is recursive.
+**
+** This is a special-purpose mutex.  It only provides mutual exclusion
+** between the Btree and the Memory Management sqlite3_release_memory()
+** function.  It does not prevent, for example, two Btrees from accessing
+** the same pager at the same time.  Other general-purpose mutexes in
+** the btree layer handle that chore.
+*/
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+  static void pagerEnter(Pager *p){
+    p->iInUseDB++;
+    if( p->iInUseMM && p->iInUseDB==1 ){
+      sqlite3_mutex *mutex;
+      mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
+      p->iInUseDB = 0;
+      sqlite3_mutex_enter(mutex);
+      p->iInUseDB = 1;
+      sqlite3_mutex_leave(mutex);
+    }
+    assert( p->iInUseMM==0 );
+  }
+  static void pagerLeave(Pager *p){
+    p->iInUseDB--;
+    assert( p->iInUseDB>=0 );
+  }
+#else
+# define pagerEnter(X)
+# define pagerLeave(X)
+#endif
+
 /*
 ** Enable reference count tracking (for debugging) here:
 */
@@ -1760,7 +1804,7 @@ static int sqlite3PagerOpentemp(
 ** in-memory database.
 */
 int sqlite3PagerOpen(
-  sqlite3_vfs *pVfs,
+  sqlite3_vfs *pVfs,       /* The virtual file system to use */
   Pager **ppPager,         /* Return the Pager structure here */
   const char *zFilename,   /* Name of the database file to open */
   int nExtra,              /* Extra bytes append to each in-memory page */
@@ -1777,24 +1821,7 @@ int sqlite3PagerOpen(
   int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
   int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
 
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to 
-  ** malloc() must have already been made by this thread before it gets
-  ** to this point. This means the ThreadData must have been allocated already
-  ** so that ThreadData.nAlloc can be set. It would be nice to assert
-  ** that ThreadData.nAlloc is non-zero, but alas this breaks test cases 
-  ** written to invoke the pager directly.
-  */
-  ThreadData *pTsd = sqlite3ThreadData();
-  assert( pTsd );
-#endif
-
-  /* We used to test if malloc() had already failed before proceeding. 
-  ** But the way this function is used in SQLite means that can never
-  ** happen. Furthermore, if the malloc-failed flag is already set, 
-  ** either the call to sqlite3StrDup() or sqlite3_malloc() below will
-  ** fail shortly and SQLITE_NOMEM returned anyway.
-  */
+  /* The default return is a NULL pointer */
   *ppPager = 0;
 
   /* Allocate memory for the pager structure */
@@ -1915,8 +1942,20 @@ int sqlite3PagerOpen(
   /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
   *ppPager = pPager;
 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  pPager->pNext = pTsd->pPager;
-  pTsd->pPager = pPager;
+  pPager->iInUseMM = 0;
+  pPager->iInUseDB = 0;
+  if( !memDb ){
+    sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
+    sqlite3_mutex_enter(mutex);
+    pPager->pNext = sqlite3PagerList;
+    if( sqlite3PagerList ){
+      assert( sqlite3PagerList->pPrev==0 );
+      sqlite3PagerList->pPrev = pPager;
+    }
+    pPager->pPrev = 0;
+    sqlite3PagerList = pPager;
+    sqlite3_mutex_leave(mutex);
+  }
 #endif
   return SQLITE_OK;
 }
@@ -1959,8 +1998,10 @@ void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*,int)){
 int sqlite3PagerSetPagesize(Pager *pPager, int pageSize){
   assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE );
   if( !pPager->memDb && pPager->nRef==0 ){
+    pagerEnter(pPager);
     pager_reset(pPager);
     pPager->pageSize = pageSize;
+    pagerLeave(pPager);
     sqlite3_free(pPager->pTmpSpace);
     pPager->pTmpSpace = sqlite3_malloc(pageSize);
   }
@@ -2242,13 +2283,17 @@ int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
     pager_truncate_cache(pPager);
     return SQLITE_OK;
   }
+  pagerEnter(pPager);
   rc = syncJournal(pPager);
+  pagerLeave(pPager);
   if( rc!=SQLITE_OK ){
     return rc;
   }
 
   /* Get an exclusive lock on the database before truncating. */
+  pagerEnter(pPager);
   rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+  pagerLeave(pPager);
   if( rc!=SQLITE_OK ){
     return rc;
   }
@@ -2273,14 +2318,19 @@ int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
 */
 int sqlite3PagerClose(Pager *pPager){
 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to 
-  ** malloc() must have already been made by this thread before it gets
-  ** to this point. This means the ThreadData must have been allocated already
-  ** so that ThreadData.nAlloc can be set.
-  */
-  ThreadData *pTsd = sqlite3ThreadData();
-  assert( pPager );
-  assert( pTsd && pTsd->nAlloc );
+  if( !MEMDB ){
+    sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
+    sqlite3_mutex_enter(mutex);
+    if( pPager->pPrev ){
+      pPager->pPrev->pNext = pPager->pNext;
+    }else{
+      sqlite3PagerList = pPager->pNext;
+    }
+    if( pPager->pNext ){
+      pPager->pNext->pPrev = pPager->pPrev;
+    }
+    sqlite3_mutex_leave(mutex);
+  }
 #endif
 
   disable_simulated_io_errors();
@@ -2306,18 +2356,6 @@ int sqlite3PagerClose(Pager *pPager){
   ** }
   */
 
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-  /* Remove the pager from the linked list of pagers starting at 
-  ** ThreadData.pPager if memory-management is enabled.
-  */
-  if( pPager==pTsd->pPager ){
-    pTsd->pPager = pPager->pNext;
-  }else{
-    Pager *pTmp;
-    for(pTmp = pTsd->pPager; pTmp->pNext!=pPager; pTmp=pTmp->pNext){}
-    pTmp->pNext = pPager->pNext;
-  }
-#endif
   sqlite3_free(pPager->aHash);
   sqlite3_free(pPager->pTmpSpace);
   sqlite3_free(pPager);
@@ -2383,7 +2421,9 @@ static void _page_ref(PgHdr *pPg){
 ** a reference to the page data.
 */
 int sqlite3PagerRef(DbPage *pPg){
+  pagerEnter(pPg->pPager);
   page_ref(pPg);
+  pagerLeave(pPg->pPager);
   return SQLITE_OK;
 }
 
@@ -2756,32 +2796,33 @@ static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){
   return SQLITE_OK;
 }
 
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
 /*
 ** This function is called to free superfluous dynamically allocated memory
 ** held by the pager system. Memory in use by any SQLite pager allocated
 ** by the current thread may be sqlite3_free()ed.
 **
 ** nReq is the number of bytes of memory required. Once this much has
-** been released, the function returns. A negative value for nReq means
-** free as much memory as possible. The return value is the total number 
+** been released, the function returns. The return value is the total number 
 ** of bytes of memory released.
 */
-#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
 int sqlite3PagerReleaseMemory(int nReq){
-  const ThreadData *pTsdro = sqlite3ThreadDataReadOnly();
-  int nReleased = 0;
-  int i;
+  int nReleased = 0;          /* Bytes of memory released so far */
+  sqlite3_mutex *mutex;       /* The MEM2 mutex */
+  Pager *pPager;              /* For looping over pagers */
+  int i;                      /* Passes over pagers */
 
-  /* If the the global mutex is held, this subroutine becomes a
-  ** o-op; zero bytes of memory are freed.  This is because
-  ** some of the code invoked by this function may also
-  ** try to obtain the mutex, resulting in a deadlock.
+  /* Acquire the memory-management mutex
   */
-#if 0
-  if( sqlite3OsInMutex(0) ){
-    return 0;
+  mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
+  sqlite3_mutex_enter(mutex);
+
+  /* Signal all database connections that memory management wants
+  ** to have access to the pagers.
+  */
+  for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){
+     pPager->iInUseMM = 1;
   }
-#endif
 
   /* Outermost loop runs for at most two iterations. First iteration we
   ** try to find memory that can be released without calling fsync(). Second
@@ -2792,14 +2833,16 @@ int sqlite3PagerReleaseMemory(int nReq){
   for(i=0; i<=1; i++){
 
     /* Loop through all the SQLite pagers opened by the current thread. */
-    Pager *pPager = pTsdro->pPager;
+    Pager *pPager = sqlite3PagerList;
     for( ; pPager && (nReq<0 || nReleased<nReq); pPager=pPager->pNext){
       PgHdr *pPg;
       int rc;
 
-      if( MEMDB ){
-        continue;
-      }
+      /* In-memory databases should not appear on the pager list */
+      assert( !MEMDB );
+
+      /* Skip pagers that are currently in use by the b-tree layer */
+      if( pPager->iInUseDB ) continue;
 
       /* For each pager, try to free as many pages as possible (without 
       ** calling fsync() if this is the first iteration of the outermost 
@@ -2822,15 +2865,11 @@ int sqlite3PagerReleaseMemory(int nReq){
           for( pTmp=pPager->pAll; pTmp->pNextAll!=pPg; pTmp=pTmp->pNextAll ){}
           pTmp->pNextAll = pPg->pNextAll;
         }
-#if 0
-        nReleased += sqliteAllocSize(pPg);
-#else
         nReleased += (
             sizeof(*pPg) + pPager->pageSize
             + sizeof(u32) + pPager->nExtra
             + MEMDB*sizeof(PgHistory) 
         );
-#endif
         IOTRACE(("PGFREE %p %d *\n", pPager, pPg->pgno));
         PAGER_INCR(sqlite3_pager_pgfree_count);
         sqlite3_free(pPg);
@@ -2854,9 +2893,18 @@ int sqlite3PagerReleaseMemory(int nReq){
     }
   }
 
+  /* Clear the memory management flags and release the mutex
+  */
+  for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){
+     pPager->iInUseMM = 0;
+  }
+  sqlite3_mutex_leave(mutex);
+
+  /* Return the number of bytes released
+  */
   return nReleased;
 }
-#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT && !SQLITE_OMIT_DISKIO */
+#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
 
 /*
 ** Read the content of page pPg out of the database file.
@@ -3162,7 +3210,7 @@ static int pager_get_content(PgHdr *pPg){
 ** called again with noContent==0, that means that the content is needed
 ** and the disk read should occur at that point.
 */
-int sqlite3PagerAcquire(
+static int pagerAcquire(
   Pager *pPager,      /* The pager open on the database file */
   Pgno pgno,          /* Page number to fetch */
   DbPage **ppPage,    /* Write a pointer to the page here */
@@ -3287,6 +3335,19 @@ int sqlite3PagerAcquire(
   *ppPage = pPg;
   return SQLITE_OK;
 }
+int sqlite3PagerAcquire(
+  Pager *pPager,      /* The pager open on the database file */
+  Pgno pgno,          /* Page number to fetch */
+  DbPage **ppPage,    /* Write a pointer to the page here */
+  int noContent       /* Do not bother reading content from disk if true */
+){
+  int rc;
+  pagerEnter(pPager);
+  rc = pagerAcquire(pPager, pgno, ppPage, noContent);
+  pagerLeave(pPager);
+  return rc;
+}
+
 
 /*
 ** Acquire a page if it is already in the in-memory cache.  Do
@@ -3300,21 +3361,20 @@ int sqlite3PagerAcquire(
 ** has ever happened.
 */
 DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
-  PgHdr *pPg;
+  PgHdr *pPg = 0;
 
   assert( pPager!=0 );
   assert( pgno!=0 );
 
+  pagerEnter(pPager);
   if( pPager->state==PAGER_UNLOCK ){
     assert( !pPager->pAll || pPager->exclusiveMode );
-    return 0;
-  }
-  if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
-    return 0;
+  }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
+    /* Do nothing */
+  }else if( (pPg = pager_lookup(pPager, pgno))!=0 ){
+    page_ref(pPg);
   }
-  pPg = pager_lookup(pPager, pgno);
-  if( pPg==0 ) return 0;
-  page_ref(pPg);
+  pagerLeave(pPager);
   return pPg;
 }
 
@@ -3331,6 +3391,7 @@ int sqlite3PagerUnref(DbPage *pPg){
   /* Decrement the reference count for this page
   */
   assert( pPg->nRef>0 );
+  pagerEnter(pPg->pPager);
   pPg->nRef--;
   REFINFO(pPg);
 
@@ -3366,6 +3427,7 @@ int sqlite3PagerUnref(DbPage *pPg){
       pagerUnlockAndRollback(pPager);
     }
   }
+  pagerLeave(pPg->pPager);
   return SQLITE_OK;
 }
 
@@ -3469,6 +3531,7 @@ failed_to_open_journal:
 int sqlite3PagerBegin(DbPage *pPg, int exFlag){
   Pager *pPager = pPg->pPager;
   int rc = SQLITE_OK;
+  pagerEnter(pPager);
   assert( pPg->nRef>0 );
   assert( pPager->state!=PAGER_UNLOCK );
   if( pPager->state==PAGER_SHARED ){
@@ -3485,6 +3548,7 @@ int sqlite3PagerBegin(DbPage *pPg, int exFlag){
         }
       }
       if( rc!=SQLITE_OK ){
+        pagerLeave(pPager);
         return rc;
       }
       pPager->dirtyCache = 0;
@@ -3512,6 +3576,7 @@ int sqlite3PagerBegin(DbPage *pPg, int exFlag){
     }
   }
   assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK );
+  pagerLeave(pPager);
   return rc;
 }
 
@@ -3756,6 +3821,7 @@ int sqlite3PagerWrite(DbPage *pDbPage){
   Pager *pPager = pPg->pPager;
   Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
 
+  pagerEnter(pPager);
   if( !MEMDB && nPagePerSector>1 ){
     Pgno nPageCount;          /* Total number of pages in database file */
     Pgno pg1;                 /* First page of the sector pPg is located on. */
@@ -3807,6 +3873,7 @@ int sqlite3PagerWrite(DbPage *pDbPage){
   }else{
     rc = pager_write(pDbPage);
   }
+  pagerLeave(pPager);
   return rc;
 }
 
@@ -3830,6 +3897,7 @@ int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void *pData){
   PgHdr *pPg;
   int rc;
 
+  pagerEnter(pPager);
   rc = sqlite3PagerGet(pPager, pgno, &pPg);
   if( rc==SQLITE_OK ){
     rc = sqlite3PagerWrite(pPg);
@@ -3838,6 +3906,7 @@ int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void *pData){
     }
     sqlite3PagerUnref(pPg);
   }
+  pagerLeave(pPager);
   return rc;
 }
 #endif
@@ -3871,6 +3940,7 @@ void sqlite3PagerDontWrite(DbPage *pDbPage){
   Pager *pPager = pPg->pPager;
 
   if( MEMDB ) return;
+  pagerEnter(pPager);
   pPg->alwaysRollback = 1;
   if( pPg->dirty && !pPager->stmtInUse ){
     assert( pPager->state>=PAGER_SHARED );
@@ -3892,6 +3962,7 @@ void sqlite3PagerDontWrite(DbPage *pDbPage){
 #endif
     }
   }
+  pagerLeave(pPager);
 }
 
 /*
@@ -3908,6 +3979,7 @@ void sqlite3PagerDontWrite(DbPage *pDbPage){
 void sqlite3PagerDontRollback(DbPage *pPg){
   Pager *pPager = pPg->pPager;
 
+  pagerEnter(pPager);
   assert( pPager->state>=PAGER_RESERVED );
   if( pPager->journalOpen==0 ) return;
   if( pPg->alwaysRollback || pPager->alwaysRollback || MEMDB ) return;
@@ -3930,6 +4002,7 @@ void sqlite3PagerDontRollback(DbPage *pPg){
     assert( pPager->aInStmt!=0 );
     pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
   }
+  pagerLeave(pPager);
 }
 
 
@@ -3982,6 +4055,7 @@ int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){
 
   PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", 
       pPager->zFilename, zMaster, nTrunc);
+  pagerEnter(pPager);
 
   /* If this is an in-memory db, or no pages have been written to, or this
   ** function has already been called, it is a no-op.
@@ -4057,6 +4131,7 @@ sync_exit:
      */
     rc = SQLITE_BUSY;
   }
+  pagerLeave(pPager);
   return rc;
 }
 
@@ -4078,6 +4153,7 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
   if( pPager->state<PAGER_RESERVED ){
     return SQLITE_ERROR;
   }
+  pagerEnter(pPager);
   PAGERTRACE2("COMMIT %d\n", PAGERID(pPager));
   if( MEMDB ){
     pPg = pager_get_all_dirty_pages(pPager);
@@ -4107,7 +4183,9 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
   assert( pPager->journalOpen || !pPager->dirtyCache );
   assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache );
   rc = pager_end_transaction(pPager);
-  return pager_error(pPager, rc);
+  rc = pager_error(pPager, rc);
+  pagerLeave(pPager);
+  return rc;
 }
 
 /*
@@ -4161,8 +4239,10 @@ int sqlite3PagerRollback(Pager *pPager){
     return SQLITE_OK;
   }
 
+  pagerEnter(pPager);
   if( !pPager->dirtyCache || !pPager->journalOpen ){
     rc = pager_end_transaction(pPager);
+    pagerLeave(pPager);
     return rc;
   }
 
@@ -4170,6 +4250,7 @@ int sqlite3PagerRollback(Pager *pPager){
     if( pPager->state>=PAGER_EXCLUSIVE ){
       pager_playback(pPager, 0);
     }
+    pagerLeave(pPager);
     return pPager->errCode;
   }
   if( pPager->state==PAGER_RESERVED ){
@@ -4189,7 +4270,9 @@ int sqlite3PagerRollback(Pager *pPager){
   ** cache. So call pager_error() on the way out to make any error 
   ** persistent.
   */
-  return pager_error(pPager, rc);
+  rc = pager_error(pPager, rc);
+  pagerLeave(pPager);
+  return rc;
 }
 
 /*
@@ -4235,7 +4318,7 @@ int *sqlite3PagerStats(Pager *pPager){
 ** open.  A new statement journal is created that can be used to rollback
 ** changes of a single SQL command within a larger transaction.
 */
-int sqlite3PagerStmtBegin(Pager *pPager){
+static int pagerStmtBegin(Pager *pPager){
   int rc;
   assert( !pPager->stmtInUse );
   assert( pPager->state>=PAGER_SHARED );
@@ -4281,11 +4364,19 @@ stmt_begin_failed:
   }
   return rc;
 }
+int sqlite3PagerStmtBegin(Pager *pPager){
+  int rc;
+  pagerEnter(pPager);
+  rc = pagerStmtBegin(pPager);
+  pagerLeave(pPager);
+  return rc;
+}
 
 /*
 ** Commit a statement.
 */
 int sqlite3PagerStmtCommit(Pager *pPager){
+  pagerEnter(pPager);
   if( pPager->stmtInUse ){
     PgHdr *pPg, *pNext;
     PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
@@ -4309,6 +4400,7 @@ int sqlite3PagerStmtCommit(Pager *pPager){
     pPager->pStmt = 0;
   }
   pPager->stmtAutoopen = 0;
+  pagerLeave(pPager);
   return SQLITE_OK;
 }
 
@@ -4317,6 +4409,7 @@ int sqlite3PagerStmtCommit(Pager *pPager){
 */
 int sqlite3PagerStmtRollback(Pager *pPager){
   int rc;
+  pagerEnter(pPager);
   if( pPager->stmtInUse ){
     PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
     if( MEMDB ){
@@ -4341,6 +4434,7 @@ int sqlite3PagerStmtRollback(Pager *pPager){
     rc = SQLITE_OK;
   }
   pPager->stmtAutoopen = 0;
+  pagerLeave(pPager);
   return rc;
 }
 
@@ -4410,6 +4504,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno){
   int h;
   Pgno needSyncPgno = 0;
 
+  pagerEnter(pPager);
   assert( pPg->nRef>0 );
 
   PAGERTRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", 
@@ -4486,6 +4581,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno){
     sqlite3PagerUnref(pPgHdr);
   }
 
+  pagerLeave(pPager);
   return SQLITE_OK;
 }
 #endif
index 0cbbf2ed710875bb89ff25d28879bd31dbc38081..2609f06a03be67ee96fadcc7777123ca04dc91ea 100644 (file)
@@ -13,7 +13,7 @@
 ** interface, and routines that contribute to loading the database schema
 ** from disk.
 **
-** $Id: prepare.c,v 1.56 2007/08/21 19:33:56 drh Exp $
+** $Id: prepare.c,v 1.57 2007/08/22 00:39:20 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -462,14 +462,12 @@ int sqlite3Prepare(
   int rc = SQLITE_OK;
   int i;
 
-  /* Assert that malloc() has not failed */
-  assert( !db->mallocFailed );
-
   assert( ppStmt );
   *ppStmt = 0;
   if( sqlite3SafetyOn(db) ){
     return SQLITE_MISUSE;
   }
+  assert( !db->mallocFailed );
   assert( sqlite3_mutex_held(db->mutex) );
 
   /* If any attached database schemas are locked, do not proceed with
index a4bd04f53e6aaa6d90ab713786171f9e51a41db8..2ecb0e7a3796d1e7dcad98ff1f5c92f646e7afc6 100644 (file)
@@ -30,7 +30,7 @@
 ** the version number) and changes its name to "sqlite3.h" as
 ** part of the build process.
 **
-** @(#) $Id: sqlite.h.in,v 1.235 2007/08/21 20:25:40 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.236 2007/08/22 00:39:20 drh Exp $
 */
 #ifndef _SQLITE3_H_
 #define _SQLITE3_H_
@@ -3259,6 +3259,7 @@ int sqlite3_vfs_unregister(sqlite3_vfs*);
 ** <li>  SQLITE_MUTEX_RECURSIVE
 ** <li>  SQLITE_MUTEX_STATIC_MASTER
 ** <li>  SQLITE_MUTEX_STATIC_MEM
+** <li>  SQLITE_MUTEX_STATIC_MEM2
 ** <li>  SQLITE_MUTEX_STATIC_PRNG
 ** </ul>
 **
@@ -3345,8 +3346,9 @@ int sqlite3_mutex_notheld(sqlite3_mutex*);
 #define SQLITE_MUTEX_FAST             0
 #define SQLITE_MUTEX_RECURSIVE        1
 #define SQLITE_MUTEX_STATIC_MASTER    2
-#define SQLITE_MUTEX_STATIC_MEM       3
-#define SQLITE_MUTEX_STATIC_PRNG      4
+#define SQLITE_MUTEX_STATIC_MEM       3  /* sqlite3_malloc() */
+#define SQLITE_MUTEX_STATIC_MEM2      4  /* sqlite3_release_memory() */
+#define SQLITE_MUTEX_STATIC_PRNG      5  /* sqlite3_random() */
 
 
 /*
index c462900cdedff50dfe5c58ade35e9537197670c9..d953f9a71b68a6cbfdd5f5e3adaaec43ce7b98d8 100644 (file)
@@ -12,7 +12,7 @@
 ** A TCL Interface to SQLite.  Append this file to sqlite3.c and
 ** compile the whole thing to build a TCL-enabled version of SQLite.
 **
-** $Id: tclsqlite.c,v 1.196 2007/08/21 10:44:16 drh Exp $
+** $Id: tclsqlite.c,v 1.197 2007/08/22 00:39:21 drh Exp $
 */
 #include "tcl.h"
 #include <errno.h>
@@ -2370,12 +2370,12 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
 #ifdef SQLITE_TEST
   {
     extern void Md5_Register(sqlite3*);
-#ifdef SQLITE_MEMDEBUG
+#if 0
     int mallocfail = sqlite3_iMallocFail;
     sqlite3_iMallocFail = 0;
 #endif
     Md5_Register(p->db);
-#ifdef SQLITE_MEMDEBUG
+#if 0
     sqlite3_iMallocFail = mallocfail;
 #endif
   }
index c28b514b81783e77a7035775e58391335d3aead1..6f54ffc2f2eee432b7e9c31d136f2aa50d5a6a23 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.267 2007/08/21 19:33:57 drh Exp $
+** $Id: test1.c,v 1.268 2007/08/22 00:39:21 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -916,11 +916,6 @@ static int test_create_function(
   ** because it is not tested anywhere else. */
   if( rc==SQLITE_OK ){
     sqlite3_value *pVal;
-#if 0
-    if( sqlite3_iMallocFail>0 ){
-      sqlite3_iMallocFail++;
-    }
-#endif 
     pVal = sqlite3ValueNew(db);
     sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
     rc = sqlite3_create_function16(db, 
@@ -2095,7 +2090,7 @@ static int test_collate(
             (void *)SQLITE_UTF16LE, val?test_collate_func:0);
     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
 
-#ifdef SQLITE_MEMDEBUG
+#if 0
     if( sqlite3_iMallocFail>0 ){
       sqlite3_iMallocFail++;
     }
@@ -4018,20 +4013,20 @@ static int test_soft_heap_limit(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
-#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
+  static int softHeapLimit = 0;
   int amt;
   if( objc!=1 && objc!=2 ){
     Tcl_WrongNumArgs(interp, 1, objv, "?N?");
     return TCL_ERROR;
   }
-  amt = sqlite3ThreadDataReadOnly()->nSoftHeapLimit;
+  amt = softHeapLimit;
   if( objc==2 ){
     int N;
     if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
     sqlite3_soft_heap_limit(N);
+    softHeapLimit = N;
   }
   Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
-#endif
   return TCL_OK;
 }
 
@@ -4061,9 +4056,6 @@ static int test_tsd_release(
   int objc,
   Tcl_Obj *CONST objv[]
 ){
-#if defined(SQLITE_MEMDEBUG)
-  sqlite3ReleaseThreadData();
-#endif
   return TCL_OK;
 }
 
@@ -4321,8 +4313,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
   extern int sqlite3_where_trace;
   extern int sqlite3_sync_count, sqlite3_fullsync_count;
   extern int sqlite3_opentemp_count;
-  extern int sqlite3_memUsed;
-  extern int sqlite3_memMax;
   extern int sqlite3_like_count;
   extern int sqlite3_xferopt_count;
   extern int sqlite3_pager_readdb_count;
@@ -4403,12 +4393,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
   Tcl_LinkVar(interp, "sqlite_os_trace",
       (char*)&sqlite3_os_trace, TCL_LINK_INT);
 #endif
-#ifdef SQLITE_MEMDEBUG
-  Tcl_LinkVar(interp, "sqlite_memused",
-      (char*)&sqlite3_memUsed, TCL_LINK_INT | TCL_LINK_READ_ONLY);
-  Tcl_LinkVar(interp, "sqlite_memmax",
-      (char*)&sqlite3_memMax, TCL_LINK_INT | TCL_LINK_READ_ONLY);
-#endif
 #ifndef SQLITE_OMIT_DISKIO
   Tcl_LinkVar(interp, "sqlite_opentemp_count",
       (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
index cf8b6dc5ff72a495bad082a7f035ae6960af879b..4091d5123fd15f89f00de4a349fcb4413b405de3 100644 (file)
@@ -44,9 +44,10 @@ int sqlite3_finalize(sqlite3_stmt *pStmt){
     rc = SQLITE_OK;
   }else{
     Vdbe *v = (Vdbe*)pStmt;
-    sqlite3_mutex_enter(v->db->mutex);
+    sqlite3_mutex *mutex = v->db->mutex;
+    sqlite3_mutex_enter(mutex);
     rc = sqlite3VdbeFinalize(v);
-    sqlite3_mutex_leave(v->db->mutex);
+    sqlite3_mutex_leave(mutex);
   }
   return rc;
 }
index 971d6acb4022064e7beb89987fe41bf9104da01c..4ebcff245bb455f7f378394b9a6c37a6e0f6402e 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this script testing the callback-free C/C++ API.
 #
-# $Id: capi2.test,v 1.33 2007/01/03 23:37:29 drh Exp $
+# $Id: capi2.test,v 1.34 2007/08/22 00:39:21 drh Exp $
 #
 
 set testdir [file dirname $argv0]
@@ -208,9 +208,9 @@ do_test capi2-3.11 {
   sqlite3_finalize $VM
 } {SQLITE_OK}
 do_test capi2-3.11b {db changes} {1}
-do_test capi2-3.12-misuse {
-  sqlite3_finalize $VM
-} {SQLITE_MISUSE}
+#do_test capi2-3.12-misuse {
+#  sqlite3_finalize $VM
+#} {SQLITE_MISUSE}
 do_test capi2-3.13 {
   set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(1,3,4)} -1 TAIL]
   list [sqlite3_step $VM] \