]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Continuing progress on the new memory allocation subsystem. Added the
authordrh <drh@noemail.net>
Sat, 14 Jun 2008 16:56:21 +0000 (16:56 +0000)
committerdrh <drh@noemail.net>
Sat, 14 Jun 2008 16:56:21 +0000 (16:56 +0000)
sqlite3_mem_methods structure for defining new memory allocators at
run-time. (CVS 5219)

FossilOrigin-Name: f00305f4cd2f487f660f34a21c1c24a0b37c7275

manifest
manifest.uuid
src/global.c
src/main.c
src/malloc.c
src/mem1.c
src/mem2.c
src/mutex.c
src/sqlite.h.in
src/sqliteInt.h

index 9c2e55197b589c8141ba44d052cc9d15075c1021..ce3a9c85575be0eee6ea1bade3d9662c8314a82d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Progress\stoward\simplementation\sof\ssqlite3_config()\sand\sa\srework\sof\sthe\nmutex\sand\smemory\sallocation\ssubsystems.\s\sThis\sis\san\sincremental\scheck-in.\s(CVS\s5218)
-D 2008-06-13T18:24:27
+C Continuing\sprogress\son\sthe\snew\smemory\sallocation\ssubsystem.\s\sAdded\sthe\nsqlite3_mem_methods\sstructure\sfor\sdefining\snew\smemory\sallocators\sat\nrun-time.\s(CVS\s5219)
+D 2008-06-14T16:56:22
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in dc5608df93faf4406cfd7a1c8ed9ab93d8bfbfd5
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -107,7 +107,7 @@ F src/delete.c d3fc5987f2eb88f7b9549d58a5dfea079a83fe8b
 F src/expr.c ecb3b23d3543427cba3e2ac12a6c6ae4bb20d39b
 F src/fault.c 1f6177188edb00641673e462f3fab8cba9f7422b
 F src/func.c 77a910a1ca7613d291fd0b5cba3be14c02f0dce0
-F src/global.c 8a5c66b6e61c38072c697179dbc2d708e39ddc96
+F src/global.c 2304cfa3288763bd2fed10caf8c6fbaa2b383f4e
 F src/hash.c fd8cb06fb54c2fe7d48c9195792059a2e5be8b70
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
 F src/hwtime.h 745961687a65ef8918cd551c02e5ccb4b8e772de
@@ -115,15 +115,15 @@ F src/insert.c c2ead6c36566de8e3f130e7ab1431723a269d5d7
 F src/journal.c cffd2cd214e58c0e99c3ff632b3bee6c7cbb260e
 F src/legacy.c 8f5a2b25d9673b4004287cf2bf51dbf7d0738406
 F src/loadext.c f99a75534a53e281fa2461239ee4a4b4bf6ad564
-F src/main.c 88caac737f4bdc646c7b298ebca867e9f3828208
-F src/malloc.c 12c1ae98ef1eff34b13c9eb526e0b7b479e1e820
+F src/main.c 4540ec2c0ba99a0dcb8bd114f733007958c6258e
+F src/malloc.c ed5c36588992e63ce5dccdfeb3c8071b8fb34e17
 F src/md5.c 008216bbb5d34c6fbab5357aa68575ad8a31516a
-F src/mem1.c 18ca1e2543252ce13cd9c1ba67853b2d8fece3dd
-F src/mem2.c cb99d152253ae11cc2ccc4073611925e81c2212d
+F src/mem1.c 9ac005ab606a58ffe32e40edd7526375be82a008
+F src/mem2.c 10df776854bee610d5228e6184aaf3bd19f6e542
 F src/mem3.c 617c2e2a72a10ecc5c01af14efc8c2596d2c2e87
 F src/mem4.c 45c328ec6dcb7e8d319cb383615b5fe547ca5409
 F src/mem5.c 3d2ff00c6e3bc37f5d82cd82e1a123b246fb7b39
-F src/mutex.c 1ff43a9f9a8e5a0d98ffccd77f56859d9fd9ffcf
+F src/mutex.c 639881f679d75b30813536ddf9224154321c31fb
 F src/mutex.h 91292a8351b5844f7d622b0da83df4e651a8f40b
 F src/mutex_os2.c b8c1231319e966875f251a7ec137bea353546b87
 F src/mutex_unix.c 28588d08a2221623d66655e536880003fd5234d6
@@ -143,9 +143,9 @@ F src/printf.c f2d4f6c5b0ec24b643e85fe60258adad8b1f6acc
 F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a
 F src/select.c 669687459e7d0193c89de06c5dbed55b4a41191c
 F src/shell.c a12ea645271b7876c8f080146f48e20b00d367ec
-F src/sqlite.h.in 487f5490a9677ef0c105c21a9595bb587be1da6a
+F src/sqlite.h.in 0995188c694b36d041424e1b65b6e01d1802c70b
 F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
-F src/sqliteInt.h c7b8bfb55381f62962eafd9826846c9e6e8bd429
+F src/sqliteInt.h cd66968455ee85b1ffed33bb241cbf30fe760d32
 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
 F src/table.c 1fa8f8113ac9cbc09ae4801c6d2a7f0af82c5822
 F src/tclsqlite.c c57e740e30bd6dda678796eed62c7f0e64689834
@@ -594,7 +594,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P e93079be83a9df7328d9b910fcbdb762be7ec815
-R b8763d642b06205a0aac83d31a5eaad0
+P a03c5af115889f477e17187a198a7d2d40bc76bf
+R 7a7d2d9fd4f0061599821d0212d56ac9
 U drh
-Z 7798430e342a4a876c2baf52ecfbbead
+Z 3478c8b21bc53c2ad4322f8aef50d224
index dd6c30a8b33c1b0fe7f51cc69d1c66bd76d5207c..119311b8917fc68fc9cb80d5fe9e8c8aa9b3ca93 100644 (file)
@@ -1 +1 @@
-a03c5af115889f477e17187a198a7d2d40bc76bf
\ No newline at end of file
+f00305f4cd2f487f660f34a21c1c24a0b37c7275
\ No newline at end of file
index 6c21d890668b2008e6d56cebbafd9673f1d04e4a..9d3a2eb1b817d687f1aa39da4dc1d8e8b3c67afd 100644 (file)
@@ -12,7 +12,7 @@
 **
 ** This file contains definitions of global variables and contants.
 **
-** $Id: global.c,v 1.1 2008/06/13 18:24:27 drh Exp $
+** $Id: global.c,v 1.2 2008/06/14 16:56:22 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -66,4 +66,4 @@ const unsigned char sqlite3UpperToLower[] = {
 ** The following singleton contains the global configuration for
 ** the SQLite library.
 */
-struct Sqlite3Config sqlite3Config;
+struct Sqlite3Config sqlite3Config = { 1, 1, 1, };
index d98530cfb11df0d7e5705b8c3dbb1bd1799dd2b9..261fadf163f245f1b377786dbf0eff2b4efe1785 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.443 2008/06/13 18:24:27 drh Exp $
+** $Id: main.c,v 1.444 2008/06/14 16:56:22 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -103,6 +103,7 @@ int sqlite3_initialize(void){
 */
 int sqlite3_shutdown(void){
   sqlite3_os_end();
+  sqlite3MallocEnd();
   sqlite3_mutex_end();
   sqlite3FullInit = 0;
   sqlite3IsInit = 0;
@@ -149,14 +150,10 @@ int sqlite3_config(int op, ...){
     }
     case SQLITE_CONFIG_MALLOC: {
       /* Specify an alternative malloc implementation */
-      sqlite3Config.xMalloc = va_arg(ap, void*(*)(int));
-      sqlite3Config.xFree = va_arg(ap, void(*)(void*));
-      sqlite3Config.xRealloc = va_arg(ap, void*(*)(void*,int));
-      sqlite3Config.xMemsize = va_arg(ap, int(*)(void*));
-      sqlite3Config.xRoundup = va_arg(ap, int(*)(int));
+      sqlite3Config.m = *va_arg(ap, sqlite3_mem_methods*);
       break;
     }
-    case SQLITE_CONFIG_MEMSTATS: {
+    case SQLITE_CONFIG_MEMSTATUS: {
       /* Enable or disable the malloc status collection */
       sqlite3Config.bMemstat = va_arg(ap, int);
       break;
index 55d5c76dee0b9a8f441ea41aac61ccdabf6de534..5916ec251ec96317efed0deb17bf239b54f66a27 100644 (file)
@@ -9,10 +9,10 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** Memory allocation functions used throughout sqlite.
 **
+** Memory allocation functions used throughout sqlite.
 **
-** $Id: malloc.c,v 1.15 2008/03/26 18:34:43 danielk1977 Exp $
+** $Id: malloc.c,v 1.16 2008/06/14 16:56:22 drh Exp $
 */
 #include "sqliteInt.h"
 #include <stdarg.h>
@@ -67,12 +67,252 @@ int sqlite3_release_memory(int n){
 #endif
 }
 
+/*
+** State information local to the memory allocation subsystem.
+*/
+static struct {
+  sqlite3_mutex *mutex;         /* Mutex to serialize access */
+
+  /*
+  ** The alarm callback and its arguments.  The mem0.mutex lock will
+  ** be held while the callback is running.  Recursive calls into
+  ** the memory subsystem are allowed, but no new callbacks will be
+  ** issued.  The alarmBusy variable is set to prevent recursive
+  ** callbacks.
+  */
+  sqlite3_int64 alarmThreshold;
+  void (*alarmCallback)(void*, sqlite3_int64,int);
+  void *alarmArg;
+  int alarmBusy;
+
+  /*
+  ** Performance statistics
+  */
+  sqlite3_int64 nowUsed;  /* Main memory currently in use */
+  sqlite3_int64 mxUsed;   /* Highwater mark for nowUsed */
+  int mxReq;              /* maximum request size for main or page-cache mem */
+} mem0;
+
+/*
+** Initialize the memory allocation subsystem.
+*/
+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);
+  }
+  return sqlite3Config.m.xInit(sqlite3Config.m.pAppData);
+}
+
+/*
+** Deinitialize the memory allocation subsystem.
+*/
+void sqlite3MallocEnd(void){
+   sqlite3Config.m.xShutdown(sqlite3Config.m.pAppData);
+}
+
+/*
+** Return the amount of memory currently checked out.
+*/
+sqlite3_int64 sqlite3_memory_used(void){
+  sqlite3_int64 n;
+  sqlite3_mutex_enter(mem0.mutex);
+  n = mem0.nowUsed;
+  sqlite3_mutex_leave(mem0.mutex);  
+  return n;
+}
+
+/*
+** Return the maximum amount of memory that has ever been
+** checked out since either the beginning of this process
+** or since the most recent reset.
+*/
+sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
+  sqlite3_int64 n;
+  sqlite3_mutex_enter(mem0.mutex);
+  n = mem0.mxUsed;
+  if( resetFlag ){
+    mem0.mxUsed = mem0.nowUsed;
+  }
+  sqlite3_mutex_leave(mem0.mutex);  
+  return n;
+}
+
+/*
+** Change the alarm callback
+*/
+int sqlite3_memory_alarm(
+  void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
+  void *pArg,
+  sqlite3_int64 iThreshold
+){
+  sqlite3_mutex_enter(mem0.mutex);
+  mem0.alarmCallback = xCallback;
+  mem0.alarmArg = pArg;
+  mem0.alarmThreshold = iThreshold;
+  sqlite3_mutex_leave(mem0.mutex);
+  return SQLITE_OK;
+}
+
+/*
+** Trigger the alarm 
+*/
+static void sqlite3MallocAlarm(int nByte){
+  void (*xCallback)(void*,sqlite3_int64,int);
+  sqlite3_int64 nowUsed;
+  void *pArg;
+  if( mem0.alarmCallback==0 || mem0.alarmBusy  ) return;
+  mem0.alarmBusy = 1;
+  xCallback = mem0.alarmCallback;
+  nowUsed = mem0.nowUsed;
+  pArg = mem0.alarmArg;
+  sqlite3_mutex_leave(mem0.mutex);
+  xCallback(pArg, nowUsed, nByte);
+  sqlite3_mutex_enter(mem0.mutex);
+  mem0.alarmBusy = 0;
+}
+
+
+/*
+** Allocate memory.  This routine is like sqlite3_malloc() except that it
+** assumes the memory subsystem has already been initialized.
+*/
+void *sqlite3Malloc(int n){
+  void *p;
+  int nFull;
+  if( n<=0 ){
+    return 0;
+  }else if( sqlite3Config.bMemstat ){
+    nFull = sqlite3Config.m.xRoundup(n);
+    sqlite3_mutex_enter(mem0.mutex);
+    if( n>mem0.mxReq ) mem0.mxReq = n;
+    if( mem0.alarmCallback!=0 && mem0.nowUsed+nFull>=mem0.alarmThreshold ){
+      sqlite3MallocAlarm(nFull);
+    }
+    if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
+      p = 0;
+    }else{
+      p = sqlite3Config.m.xMalloc(nFull);
+      if( p==0 ){
+        sqlite3MallocAlarm(nFull);
+        p = malloc(nFull);
+      }
+    }
+    if( p ){
+      mem0.nowUsed += nFull;
+      if( mem0.nowUsed>mem0.mxUsed ){
+        mem0.mxUsed = mem0.nowUsed;
+      }
+    }
+    sqlite3_mutex_leave(mem0.mutex);
+  }else{
+    p = sqlite3Config.m.xMalloc(n);
+  }
+  return p;
+}
+
+/*
+** This version of the memory allocation is for use by the application.
+** First make sure the memory subsystem is initialized, then do the
+** allocation.
+*/
+void *sqlite3_malloc(int n){
+#ifndef SQLITE_OMIT_AUTOINIT
+  if( sqlite3_initialize() ) return 0;
+#endif
+  return sqlite3Malloc(n);
+}
+
+/*
+** Return the size of a memory allocation previously obtained from
+** sqlite3Malloc() or sqlite3_malloc().
+*/
+int sqlite3MallocSize(void *p){
+  return sqlite3Config.m.xSize(p);
+}
+
+/*
+** Free memory previously obtained from sqlite3Malloc().
+*/
+void sqlite3_free(void *p){
+  if( p==0 ) return;
+  if( sqlite3Config.bMemstat ){
+    sqlite3_mutex_enter(mem0.mutex);
+    mem0.nowUsed -= sqlite3MallocSize(p);
+    sqlite3Config.m.xFree(p);
+    sqlite3_mutex_leave(mem0.mutex);
+  }else{
+    sqlite3Config.m.xFree(p);
+  }
+}
+
+/*
+** Change the size of an existing memory allocation
+*/
+void *sqlite3Realloc(void *pOld, int nBytes){
+  int nOld, nNew;
+  void *pNew;
+  if( pOld==0 ){
+    return sqlite3Malloc(nBytes);
+  }
+  if( nBytes<=0 ){
+    sqlite3_free(pOld);
+    return 0;
+  }
+  nOld = sqlite3MallocSize(pOld);
+  if( sqlite3Config.bMemstat ){
+    sqlite3_mutex_enter(mem0.mutex);
+    if( nBytes>mem0.mxReq ) mem0.mxReq = nBytes;
+    nNew = sqlite3Config.m.xRoundup(nBytes);
+    if( nOld==nNew ){
+      pNew = pOld;
+    }else{
+      if( mem0.nowUsed+nNew-nOld>=mem0.alarmThreshold ){
+        sqlite3MallocAlarm(nNew-nOld);
+      }
+      if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
+        pNew = 0;
+      }else{
+        pNew = sqlite3Config.m.xRealloc(pOld, nNew);
+        if( pNew==0 ){
+          sqlite3MallocAlarm(nBytes);
+          pNew = sqlite3Config.m.xRealloc(pOld, nNew);
+        }
+      }
+      if( pNew ){
+        mem0.nowUsed += nNew-nOld;
+        if( mem0.nowUsed>mem0.mxUsed ){
+          mem0.mxUsed = mem0.nowUsed;
+        }
+      }
+    }
+    sqlite3_mutex_leave(mem0.mutex);
+  }else{
+    pNew = sqlite3Config.m.xRealloc(pOld, nBytes);
+  }
+  return pNew;
+}
+
+/*
+** The public interface to sqlite3Realloc.  Make sure that the memory
+** subsystem is initialized prior to invoking sqliteRealloc.
+*/
+void *sqlite3_realloc(void *pOld, int n){
+#ifndef SQLITE_OMIT_AUTOINIT
+  if( sqlite3_initialize() ) return 0;
+#endif
+  return sqlite3Realloc(pOld, n);
+}
+
 
 /*
 ** Allocate and zero memory.
 */ 
-void *sqlite3MallocZero(unsigned n){
-  void *p = sqlite3_malloc(n);
+void *sqlite3MallocZero(int n){
+  void *p = sqlite3Malloc(n);
   if( p ){
     memset(p, 0, n);
   }
@@ -83,7 +323,7 @@ void *sqlite3MallocZero(unsigned n){
 ** Allocate and zero memory.  If the allocation fails, make
 ** the mallocFailed flag in the connection pointer.
 */
-void *sqlite3DbMallocZero(sqlite3 *db, unsigned n){
+void *sqlite3DbMallocZero(sqlite3 *db, int n){
   void *p = sqlite3DbMallocRaw(db, n);
   if( p ){
     memset(p, 0, n);
@@ -95,10 +335,10 @@ void *sqlite3DbMallocZero(sqlite3 *db, unsigned n){
 ** Allocate and zero memory.  If the allocation fails, make
 ** the mallocFailed flag in the connection pointer.
 */
-void *sqlite3DbMallocRaw(sqlite3 *db, unsigned n){
+void *sqlite3DbMallocRaw(sqlite3 *db, int n){
   void *p = 0;
   if( !db || db->mallocFailed==0 ){
-    p = sqlite3_malloc(n);
+    p = sqlite3Malloc(n);
     if( !p && db ){
       db->mallocFailed = 1;
     }
index 296dbe7650deb654aef354cad3261eb675322163..e7491f8ab911a72f55c81cddf8d5fde30f65eda0 100644 (file)
@@ -9,10 +9,15 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This file contains the C functions that implement a memory
-** allocation subsystem for use by SQLite.  
 **
-** $Id: mem1.c,v 1.18 2008/06/13 18:24:27 drh Exp $
+** This file contains low-level memory allocation drivers for when
+** SQLite will use the standard C-library malloc/realloc/free interface
+** to obtain the memory it needs.
+**
+** This file contains implementations of the low-level memory allocation
+** routines specified in the sqlite3_mem_methods object.
+**
+** $Id: mem1.c,v 1.19 2008/06/14 16:56:22 drh Exp $
 */
 #include "sqliteInt.h"
 
 #ifdef SQLITE_SYSTEM_MALLOC
 
 /*
-** All of the static variables used by this module are collected
-** into a single structure named "mem".  This is to keep the
-** static variables organized and to reduce namespace pollution
-** when this module is combined with other in the amalgamation.
-*/
-static struct {
-  /*
-  ** The alarm callback and its arguments.  The mem.mutex lock will
-  ** be held while the callback is running.  Recursive calls into
-  ** the memory subsystem are allowed, but no new callbacks will be
-  ** issued.  The alarmBusy variable is set to prevent recursive
-  ** callbacks.
-  */
-  sqlite3_int64 alarmThreshold;
-  void (*alarmCallback)(void*, sqlite3_int64,int);
-  void *alarmArg;
-  int alarmBusy;
-  
-  /*
-  ** Mutex to control access to the memory allocation subsystem.
-  */
-  sqlite3_mutex *mutex;
-  
-  /*
-  ** Current allocation and high-water mark.
-  */
-  sqlite3_int64 nowUsed;
-  sqlite3_int64 mxUsed;
-  
-} mem;
-
-/*
-** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
+** Like malloc(), but remember the size of the allocation
+** so that we can find it later using sqlite3MemSize().
+**
+** For this low-level routine, we are guaranteed that nByte>0 because
+** cases of nByte<=0 will be intercepted and dealt with by higher level
+** routines.
 */
-static void enterMem(void){
-  if( mem.mutex==0 ){
-    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
-  }
-  sqlite3_mutex_enter(mem.mutex);
+static void *sqlite3MemMalloc(int nByte){
+  sqlite3_int64 *p;
+  assert( nByte>0 );
+  nByte = (nByte+7)&~7;
+  p = malloc( nByte+8 );
+  p[0] = nByte;
+  return (void*)&p[1];
 }
 
 /*
-** Return the amount of memory currently checked out.
+** Like free() but works for allocations obtained from sqlite3MemMalloc()
+** or sqlite3MemRealloc().
+**
+** For this low-level routine, we already know that pPrior!=0 since
+** cases where pPrior==0 will have been intecepted and dealt with
+** by higher-level routines.
 */
-sqlite3_int64 sqlite3_memory_used(void){
-  sqlite3_int64 n;
-  enterMem();
-  n = mem.nowUsed;
-  sqlite3_mutex_leave(mem.mutex);  
-  return n;
+static void sqlite3MemFree(void *pPrior){
+  assert( pPrior!=0 );
+  sqlite3_int64 *p = (sqlite3_int64*)pPrior;
+  p--;
+  free(p);
 }
 
 /*
-** Return the maximum amount of memory that has ever been
-** checked out since either the beginning of this process
-** or since the most recent reset.
+** Like realloc().  Resize an allocation previously obtained from
+** sqlite3MemMalloc().
+**
+** For this low-level interface, we know that pPrior!=0.  Cases where
+** pPrior==0 while have been intercepted by higher-level routine and
+** redirected to xMalloc.  Similarly, we know that nByte>0 becauses
+** cases where nByte<=0 will have been intercepted by higher-level
+** routines and redirected to xFree.
 */
-sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
-  sqlite3_int64 n;
-  enterMem();
-  n = mem.mxUsed;
-  if( resetFlag ){
-    mem.mxUsed = mem.nowUsed;
+static void *sqlite3MemRealloc(void *pPrior, int nByte){
+  sqlite3_int64 *p = (sqlite3_int64*)pPrior;
+  assert( pPrior!=0 && nByte>0 );
+  nByte = (nByte+7)&~7;
+  p = (sqlite3_int64*)pPrior;
+  p--;
+  p = realloc(p, nByte+8 );
+  if( p ){
+    p[0] = nByte;
+    p++;
   }
-  sqlite3_mutex_leave(mem.mutex);  
-  return n;
-}
-
-/*
-** Change the alarm callback
-*/
-int sqlite3_memory_alarm(
-  void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
-  void *pArg,
-  sqlite3_int64 iThreshold
-){
-  enterMem();
-  mem.alarmCallback = xCallback;
-  mem.alarmArg = pArg;
-  mem.alarmThreshold = iThreshold;
-  sqlite3_mutex_leave(mem.mutex);
-  return SQLITE_OK;
-}
-
-/*
-** Trigger the alarm 
-*/
-static void sqlite3MemsysAlarm(int nByte){
-  void (*xCallback)(void*,sqlite3_int64,int);
-  sqlite3_int64 nowUsed;
-  void *pArg;
-  if( mem.alarmCallback==0 || mem.alarmBusy  ) return;
-  mem.alarmBusy = 1;
-  xCallback = mem.alarmCallback;
-  nowUsed = mem.nowUsed;
-  pArg = mem.alarmArg;
-  sqlite3_mutex_leave(mem.mutex);
-  xCallback(pArg, nowUsed, nByte);
-  sqlite3_mutex_enter(mem.mutex);
-  mem.alarmBusy = 0;
+  return (void*)p;
 }
 
 /*
-** Allocate nBytes of memory
+** Report the allocated size of a prior return from xMalloc()
+** or xRealloc().
 */
-void *sqlite3_malloc(int nBytes){
-  sqlite3_int64 *p = 0;
-  if( nBytes>0 ){
-    enterMem();
-    if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){
-      sqlite3MemsysAlarm(nBytes);
-    }
-    if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
-      p = 0;
-    }else{
-      p = malloc(nBytes+8);
-      if( p==0 ){
-        sqlite3MemsysAlarm(nBytes);
-        p = malloc(nBytes+8);
-      }
-    }
-    if( p ){
-      p[0] = nBytes;
-      p++;
-      mem.nowUsed += nBytes;
-      if( mem.nowUsed>mem.mxUsed ){
-        mem.mxUsed = mem.nowUsed;
-      }
-    }
-    sqlite3_mutex_leave(mem.mutex);
-  }
-  return (void*)p; 
+static int sqlite3MemSize(void *pPrior){
+  sqlite3_int64 *p;
+  if( pPrior==0 ) return 0;
+  p = (sqlite3_int64*)pPrior;
+  p--;
+  return p[0];
 }
 
 /*
-** Free memory.
+** Round up a request size to the next valid allocation size.
 */
-void sqlite3_free(void *pPrior){
-  sqlite3_int64 *p;
-  int nByte;
-  if( pPrior==0 ){
-    return;
-  }
-  assert( mem.mutex!=0 );
-  p = pPrior;
-  p--;
-  nByte = (int)*p;
-  sqlite3_mutex_enter(mem.mutex);
-  mem.nowUsed -= nByte;
-  free(p);
-  sqlite3_mutex_leave(mem.mutex);  
+static int sqlite3MemRoundup(int n){
+  return (n+7) & ~7;
 }
 
 /*
-** Return the number of bytes allocated at p.
+** Initialize this module.
 */
-int sqlite3MallocSize(void *p){
-  sqlite3_int64 *pInt;
-  if( !p ) return 0;
-  pInt = p;
-  return pInt[-1];
+static int sqlite3MemInit(void *NotUsed){
+  return SQLITE_OK;
 }
 
 /*
-** Initialize the memmory allocation subsystem.
+** Deinitialize this module.
 */
-int sqlite3MallocInit(void){
-  return SQLITE_OK;
+static void sqlite3MemShutdown(void *NotUsed){
+  return;
 }
 
 /*
-** Change the size of an existing memory allocation
+** This routine is the only routine in this file with external linkage.
+**
+** Populate the low-level memory allocation function pointers in
+** sqlite3Config.m with pointers to the routines in this file.
 */
-void *sqlite3_realloc(void *pPrior, int nBytes){
-  int nOld;
-  sqlite3_int64 *p;
-  if( pPrior==0 ){
-    return sqlite3_malloc(nBytes);
-  }
-  if( nBytes<=0 ){
-    sqlite3_free(pPrior);
-    return 0;
-  }
-  p = pPrior;
-  p--;
-  nOld = (int)p[0];
-  assert( mem.mutex!=0 );
-  sqlite3_mutex_enter(mem.mutex);
-  if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){
-    sqlite3MemsysAlarm(nBytes-nOld);
-  }
-  if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
-    p = 0;
-  }else{
-    p = realloc(p, nBytes+8);
-    if( p==0 ){
-      sqlite3MemsysAlarm(nBytes);
-      p = pPrior;
-      p--;
-      p = realloc(p, nBytes+8);
-    }
-  }
-  if( p ){
-    p[0] = nBytes;
-    p++;
-    mem.nowUsed += nBytes-nOld;
-    if( mem.nowUsed>mem.mxUsed ){
-      mem.mxUsed = mem.nowUsed;
-    }
-  }
-  sqlite3_mutex_leave(mem.mutex);
-  return (void*)p;
+void sqlite3MemSetDefault(void){
+  static const sqlite3_mem_methods defaultMethods = {
+     sqlite3MemMalloc,
+     sqlite3MemFree,
+     sqlite3MemRealloc,
+     sqlite3MemSize,
+     sqlite3MemRoundup,
+     sqlite3MemInit,
+     sqlite3MemShutdown,
+     0
+  };
+  sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
 }
 
 #endif /* SQLITE_SYSTEM_MALLOC */
index ff8c87a1b775c21785402392aba1d7f32490d116..3206b25a508bfdb145562a0dddabf01bbadb6f57 100644 (file)
@@ -9,10 +9,17 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This file contains the C functions that implement a memory
-** allocation subsystem for use by SQLite.  
 **
-** $Id: mem2.c,v 1.27 2008/06/13 18:24:27 drh Exp $
+** This file contains low-level memory allocation drivers for when
+** SQLite will use the standard C-library malloc/realloc/free interface
+** to obtain the memory it needs while adding lots of additional debugging
+** information to each allocation in order to help detect and fix memory
+** 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.28 2008/06/14 16:56:22 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -74,29 +81,12 @@ struct MemBlockHdr {
 ** when this module is combined with other in the amalgamation.
 */
 static struct {
-  /*
-  ** The alarm callback and its arguments.  The mem.mutex lock will
-  ** be held while the callback is running.  Recursive calls into
-  ** the memory subsystem are allowed, but no new callbacks will be
-  ** issued.  The alarmBusy variable is set to prevent recursive
-  ** callbacks.
-  */
-  sqlite3_int64 alarmThreshold;
-  void (*alarmCallback)(void*, sqlite3_int64, int);
-  void *alarmArg;
-  int alarmBusy;
   
   /*
   ** Mutex to control access to the memory allocation subsystem.
   */
   sqlite3_mutex *mutex;
-  
-  /*
-  ** Current allocation and high-water mark.
-  */
-  sqlite3_int64 nowUsed;
-  sqlite3_int64 mxUsed;
-  
+
   /*
   ** Head and tail of a linked list of all outstanding allocations
   */
@@ -131,78 +121,6 @@ static struct {
 
 } mem;
 
-
-/*
-** Enter the mutex mem.mutex. Allocate it if it is not already allocated.
-*/
-static void enterMem(void){
-  if( mem.mutex==0 ){
-    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
-  }
-  sqlite3_mutex_enter(mem.mutex);
-}
-
-/*
-** Return the amount of memory currently checked out.
-*/
-sqlite3_int64 sqlite3_memory_used(void){
-  sqlite3_int64 n;
-  enterMem();
-  n = mem.nowUsed;
-  sqlite3_mutex_leave(mem.mutex);  
-  return n;
-}
-
-/*
-** Return the maximum amount of memory that has ever been
-** checked out since either the beginning of this process
-** or since the most recent reset.
-*/
-sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
-  sqlite3_int64 n;
-  enterMem();
-  n = mem.mxUsed;
-  if( resetFlag ){
-    mem.mxUsed = mem.nowUsed;
-  }
-  sqlite3_mutex_leave(mem.mutex);  
-  return n;
-}
-
-/*
-** Change the alarm callback
-*/
-int sqlite3_memory_alarm(
-  void(*xCallback)(void *pArg, sqlite3_int64 used, int N),
-  void *pArg,
-  sqlite3_int64 iThreshold
-){
-  enterMem();
-  mem.alarmCallback = xCallback;
-  mem.alarmArg = pArg;
-  mem.alarmThreshold = iThreshold;
-  sqlite3_mutex_leave(mem.mutex);
-  return SQLITE_OK;
-}
-
-/*
-** Trigger the alarm 
-*/
-static void sqlite3MemsysAlarm(int nByte){
-  void (*xCallback)(void*,sqlite3_int64,int);
-  sqlite3_int64 nowUsed;
-  void *pArg;
-  if( mem.alarmCallback==0 || mem.alarmBusy  ) return;
-  mem.alarmBusy = 1;
-  xCallback = mem.alarmCallback;
-  nowUsed = mem.nowUsed;
-  pArg = mem.alarmArg;
-  sqlite3_mutex_leave(mem.mutex);
-  xCallback(pArg, nowUsed, nByte);
-  sqlite3_mutex_enter(mem.mutex);
-  mem.alarmBusy = 0;
-}
-
 /*
 ** Given an allocation, find the MemBlockHdr for that allocation.
 **
@@ -231,7 +149,7 @@ static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
 /*
 ** Return the number of bytes currently allocated at address p.
 */
-int sqlite3MallocSize(void *p){
+static int sqlite3MemSize(void *p){
   struct MemBlockHdr *pHdr;
   if( !p ){
     return 0;
@@ -241,106 +159,100 @@ int sqlite3MallocSize(void *p){
 }
 
 /*
-** Initialize the memmory allocation subsystem.
+** Initialize the memory allocation subsystem.
 */
-int sqlite3MallocInit(void){
+static int sqlite3MemInit(void *NotUsed){
+  mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
   return SQLITE_OK;
 }
 
+/*
+** Deinitialize the memory allocation subsystem.
+*/
+static void sqlite3MemShutdown(void *NotUsed){
+  sqlite3_mutex_free(mem.mutex);
+  mem.mutex = 0;
+}
+
+/*
+** Round up a request size to the next valid allocation size.
+*/
+static int sqlite3MemRoundup(int n){
+  return (n+7) & ~7;
+}
+
 /*
 ** Allocate nByte bytes of memory.
 */
-void *sqlite3_malloc(int nByte){
+static void *sqlite3MemMalloc(int nByte){
   struct MemBlockHdr *pHdr;
   void **pBt;
   char *z;
   int *pInt;
   void *p = 0;
   int totalSize;
-
-  if( nByte>0 ){
-    int nReserve;
-    enterMem();
-    assert( mem.disallow==0 );
-    if( mem.alarmCallback!=0 && mem.nowUsed+nByte>=mem.alarmThreshold ){
-      sqlite3MemsysAlarm(nByte);
-    }
-    nReserve = (nByte+7)&~7;
-    if( nReserve/8>NCSIZE-1 ){
-      mem.sizeCnt[NCSIZE-1]++;
+  int nReserve;
+  sqlite3_mutex_enter(mem.mutex);
+  assert( mem.disallow==0 );
+  nReserve = (nByte+7)&~7;
+  if( nReserve/8>NCSIZE-1 ){
+    mem.sizeCnt[NCSIZE-1]++;
+  }else{
+    mem.sizeCnt[nReserve/8]++;
+  }
+  totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
+               mem.nBacktrace*sizeof(void*) + mem.nTitle;
+  p = malloc(totalSize);
+  if( p ){
+    z = p;
+    pBt = (void**)&z[mem.nTitle];
+    pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace];
+    pHdr->pNext = 0;
+    pHdr->pPrev = mem.pLast;
+    if( mem.pLast ){
+      mem.pLast->pNext = pHdr;
     }else{
-      mem.sizeCnt[nReserve/8]++;
+      mem.pFirst = pHdr;
     }
-    totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
-                 mem.nBacktrace*sizeof(void*) + mem.nTitle;
-    if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
-      p = 0;
-    }else{
-      p = malloc(totalSize);
-      if( p==0 ){
-        sqlite3MemsysAlarm(nByte);
-        p = malloc(totalSize);
+    mem.pLast = pHdr;
+    pHdr->iForeGuard = FOREGUARD;
+    pHdr->nBacktraceSlots = mem.nBacktrace;
+    pHdr->nTitle = mem.nTitle;
+    if( mem.nBacktrace ){
+      void *aAddr[40];
+      pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
+      memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
+      if( mem.xBacktrace ){
+        mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
       }
+    }else{
+      pHdr->nBacktrace = 0;
     }
-    if( p ){
-      z = p;
-      pBt = (void**)&z[mem.nTitle];
-      pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace];
-      pHdr->pNext = 0;
-      pHdr->pPrev = mem.pLast;
-      if( mem.pLast ){
-        mem.pLast->pNext = pHdr;
-      }else{
-        mem.pFirst = pHdr;
-      }
-      mem.pLast = pHdr;
-      pHdr->iForeGuard = FOREGUARD;
-      pHdr->nBacktraceSlots = mem.nBacktrace;
-      pHdr->nTitle = mem.nTitle;
-      if( mem.nBacktrace ){
-        void *aAddr[40];
-        pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
-        memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
-       if( mem.xBacktrace ){
-          mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
-       }
-      }else{
-        pHdr->nBacktrace = 0;
-      }
-      if( mem.nTitle ){
-        memcpy(z, mem.zTitle, mem.nTitle);
-      }
-      pHdr->iSize = nByte;
-      pInt = (int*)&pHdr[1];
-      pInt[nReserve/sizeof(int)] = REARGUARD;
-      memset(pInt, 0x65, nReserve);
-      mem.nowUsed += nByte;
-      if( mem.nowUsed>mem.mxUsed ){
-        mem.mxUsed = mem.nowUsed;
-      }
-      p = (void*)pInt;
+    if( mem.nTitle ){
+      memcpy(z, mem.zTitle, mem.nTitle);
     }
-    sqlite3_mutex_leave(mem.mutex);
+    pHdr->iSize = nByte;
+    pInt = (int*)&pHdr[1];
+    pInt[nReserve/sizeof(int)] = REARGUARD;
+    memset(pInt, 0x65, nReserve);
+    p = (void*)pInt;
   }
+  sqlite3_mutex_leave(mem.mutex);
   return p; 
 }
 
 /*
 ** Free memory.
 */
-void sqlite3_free(void *pPrior){
+static void sqlite3MemFree(void *pPrior){
   struct MemBlockHdr *pHdr;
   void **pBt;
   char *z;
-  if( pPrior==0 ){
-    return;
-  }
   assert( mem.mutex!=0 );
   pHdr = sqlite3MemsysGetHeader(pPrior);
   pBt = (void**)pHdr;
   pBt -= pHdr->nBacktraceSlots;
   sqlite3_mutex_enter(mem.mutex);
-  mem.nowUsed -= pHdr->iSize;
   if( pHdr->pPrev ){
     assert( pHdr->pPrev->pNext==pHdr );
     pHdr->pPrev->pNext = pHdr->pNext;
@@ -372,29 +284,41 @@ void sqlite3_free(void *pPrior){
 ** much more likely to break and we are much more liking to find
 ** the error.
 */
-void *sqlite3_realloc(void *pPrior, int nByte){
+static void *sqlite3MemRealloc(void *pPrior, int nByte){
   struct MemBlockHdr *pOldHdr;
   void *pNew;
-  if( pPrior==0 ){
-    return sqlite3_malloc(nByte);
-  }
-  if( nByte<=0 ){
-    sqlite3_free(pPrior);
-    return 0;
-  }
   assert( mem.disallow==0 );
   pOldHdr = sqlite3MemsysGetHeader(pPrior);
-  pNew = sqlite3_malloc(nByte);
+  pNew = sqlite3MemMalloc(nByte);
   if( pNew ){
     memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
     if( nByte>pOldHdr->iSize ){
       memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize);
     }
-    sqlite3_free(pPrior);
+    sqlite3MemFree(pPrior);
   }
   return pNew;
 }
 
+
+/*
+** Populate the low-level memory allocation function pointers in
+** sqlite3Config.m with pointers to the routines in this file.
+*/
+void sqlite3MemSetDefault(void){
+  static const sqlite3_mem_methods defaultMethods = {
+     sqlite3MemMalloc,
+     sqlite3MemFree,
+     sqlite3MemRealloc,
+     sqlite3MemSize,
+     sqlite3MemRoundup,
+     sqlite3MemInit,
+     sqlite3MemShutdown,
+     0
+  };
+  sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+}
+
 /*
 ** Set the number of backtrace levels kept for each allocation.
 ** A value of zero turns of backtracing.  The number is always rounded
@@ -416,7 +340,7 @@ void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){
 */
 void sqlite3MemdebugSettitle(const char *zTitle){
   int n = strlen(zTitle) + 1;
-  enterMem();
+  sqlite3_mutex_enter(mem.mutex);
   if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
   memcpy(mem.zTitle, zTitle, n);
   mem.zTitle[n] = 0;
@@ -474,7 +398,7 @@ void sqlite3MemdebugDump(const char *zFilename){
 }
 
 /*
-** Return the number of times sqlite3_malloc() has been called.
+** Return the number of times sqlite3MemMalloc() has been called.
 */
 int sqlite3MemdebugMallocCount(){
   int i;
index 939f3625585aac90800f9f9a251ca5918663888b..82812bc759e776a9e84b4241e18719c99d24ab84 100644 (file)
@@ -19,7 +19,7 @@
 ** implementation is suitable for testing.
 ** debugging purposes
 **
-** $Id: mutex.c,v 1.18 2008/06/13 18:24:27 drh Exp $
+** $Id: mutex.c,v 1.19 2008/06/14 16:56:23 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -77,7 +77,7 @@ sqlite3_mutex *sqlite3_mutex_alloc(int id){
 ** This routine deallocates a previously allocated mutex.
 */
 void sqlite3_mutex_free(sqlite3_mutex *p){
-  assert( p );
+  if( p==0 ) return;
   assert( p->cnt==0 );
   assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
   sqlite3_free(p);
@@ -95,14 +95,16 @@ void sqlite3_mutex_free(sqlite3_mutex *p){
 ** more than once, the behavior is undefined.
 */
 void sqlite3_mutex_enter(sqlite3_mutex *p){
-  assert( p );
-  assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
-  p->cnt++;
+  if( p ){
+    assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
+    p->cnt++;
+  }
 }
 int sqlite3_mutex_try(sqlite3_mutex *p){
-  assert( p );
-  assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
-  p->cnt++;
+  if( p ){
+    assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
+    p->cnt++;
+  }
   return SQLITE_OK;
 }
 
@@ -113,10 +115,11 @@ int sqlite3_mutex_try(sqlite3_mutex *p){
 ** is not currently allocated.  SQLite will never do either.
 */
 void sqlite3_mutex_leave(sqlite3_mutex *p){
-  assert( p );
-  assert( sqlite3_mutex_held(p) );
-  p->cnt--;
-  assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
+  if( p ){
+    assert( sqlite3_mutex_held(p) );
+    p->cnt--;
+    assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
+  }
 }
 
 /*
index 3e1cdccc0a7b1540ef975581e60b6eae943f3f63..ea46093eee746cbc3e9f720f15626b710b2d7e5c 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.326 2008/06/13 18:24:27 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.327 2008/06/14 16:56:23 drh Exp $
 */
 #ifndef _SQLITE3_H_
 #define _SQLITE3_H_
@@ -942,6 +942,60 @@ int sqlite3_os_end(void);
 */
 int sqlite3_config(int, ...);
 
+/*
+** CAPI3REF: Memory Allocation Routines {F10155}
+**
+** An instance of this object defines the interface between SQLite
+** and low-level memory allocation routines.  
+**
+** This object is used in only one place in the SQLite interface.
+** A pointer to an instance of this object is the argument to
+** [sqlite3_config] when the configuration option is
+** [SQLITE_CONFIG_MALLOC].  By creating an instance of this object
+** and passing it to [sqlite3_config] during configuration, an
+** application can specify an alternative memory allocation subsystem
+** for SQLite to use for all of its dynamic memory needs.
+**
+** Note that SQLite comes with a built-in memory allocator that is
+** perfectly adequate for the overwhelming majority of applications
+** and that this object is only useful to a tiny minority of applications
+** with specialized memory allocation requirements.  This object is
+** also used during testing of SQLite in order to specify an alternative
+** memory allocator that simulates memory out-of-memory conditions in
+** order to verify that SQLite recovers gracefully from such
+** conditions.
+**
+** The xMalloc, xFree, and xRealloc methods should work like the
+** malloc(), free(), and realloc() functions from the standard library.
+**
+** xSize should return the allocated size of a memory allocation
+** previously obtained from xMalloc or xRealloc.  The allocated size
+** is always at least as big as the requested size but may be larger.
+**
+** The xRoundup method returns what would be the allocated size of
+** a memory allocation given a particular requested size.  Most memory
+** allocators round up memory allocations at least to the next multiple
+** of 8.  Some round up to a larger multiple or to a power of 2. 
+**
+** The xInit method initializes the memory allocator.  (For example,
+** it might allocate any require mutexes or initialize internal data
+** structures.  The xShutdown method is invoked (indirectly) by
+** [sqlite3_shutdown()] and should deallocate any resources acquired
+** by xInit.  The pAppData pointer is used as the only parameter to
+** xInit and xShutdown.
+*/
+typedef struct sqlite3_mem_methods sqlite3_mem_methods;
+struct sqlite3_mem_methods {
+  void *(*xMalloc)(int);         /* Memory allocation function */
+  void (*xFree)(void*);          /* Free a prior allocation */
+  void *(*xRealloc)(void*,int);  /* Resize an allocation */
+  int (*xSize)(void*);           /* Return the size of an allocation */
+  int (*xRoundup)(int);          /* Round up request size to allocation size */
+  int (*xInit)(void*);           /* Initialize the memory allocator */
+  void (*xShutdown)(void*);      /* Deinitialize the memory allocator */
+  void *pAppData;                /* Argument to xInit() and xShutdown() */
+};
+
 /*
 ** CAPI3REF: Configuration Options {F10160}
 **
@@ -973,16 +1027,12 @@ int sqlite3_config(int, ...);
 ** same [prepared statement] in different threads at the same time.</dd>
 **
 ** <dt>SQLITE_CONFIG_MALLOC</dt>
-** <dd>This option takes five arguments.  The first three
-** arguments are pointers to functions that emulate malloc(), free(),
-** and realloc(), respectively.  The fourth argument must be a pointer to
-** a function that returns the size of a prior allocation when handed a pointer
-** to the allocation. The fifth argument is a pointer to a function that
-** returns the rounded-up size of a memory allocation given the requested
-** allocation size.  This option is used to replace the default memory
-** allocator with an application-defined memory allocator.</dd>
-**
-** <dt>SQLITE_CONFIG_MEMSTATS</dt>
+** <dd>This option takes a single argument which is a pointer to an
+** instance of the [sqlite3_mem_methods] structure.  The argument specifics
+** alternative low-level memory allocation routines to be used in place
+** the memory allocation routines built into SQLite.</dd>
+**
+** <dt>SQLITE_CONFIG_MEMSTATUS</dt>
 ** <dd>This option takes single boolean argument which enables or disables
 ** the collection of memory allocation statistics.  When disabled, the
 ** following SQLite interfaces become non-operational:
@@ -998,8 +1048,8 @@ int sqlite3_config(int, ...);
 #define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
 #define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
 #define SQLITE_CONFIG_SERIALIZED    3  /* nil */
-#define SQLITE_CONFIG_MALLOC        4  /* malloc,free,realloc,memsize,roundup */
-#define SQLITE_CONFIG_MEMSTAT     5  /* boolean */
+#define SQLITE_CONFIG_MALLOC        4  /* sqlite3_mem_methods* */
+#define SQLITE_CONFIG_MEMSTATUS     5  /* boolean */
 
 /* These options are to be added later.  Currently unused and undocumented. */
 #define SQLITE_CONFIG_HEAP          6  /* void*, int64, min, max, tmp */
index d2cb424c199afb56aaaccd7af0a176c4ae444531..6b9eda6c8e23d33b354fc41e7fe1763c43ca08c3 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.708 2008/06/13 18:24:27 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.709 2008/06/14 16:56:23 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1735,18 +1735,14 @@ typedef struct {
 ** Structure containing global configuration data for the SQLite library.
 */
 struct Sqlite3Config {
-  void *(*xMalloc)(int);            /* Low-level malloc() */
-  void *(*xRealloc)(void*,int);     /* Low-level realloc() */
-  void (*xFree)(void*);             /* Low-level free() */
-  int (*xMemsize)(void*);           /* Return size of an allocation */
-  int (*xRoundup)(int);             /* Size of allocation given request */
+  int bMemstat;                     /* True to enable memory status */
+  int bCoreMutex;                   /* True to enable core mutexing */
+  int bFullMutex;                   /* True to enable full mutexing */
+  sqlite3_mem_methods m;            /* Low-level memory allocation interface */
   void *pHeap;                      /* Heap storage space */
   sqlite3_int64 nHeap;              /* Size of pHeap[] */
   int mnReq, mxReq;                 /* Min and max memory request sizes */
   int nTemp;                        /* Part of pHeap for temporary allos */
-  int bMemstat;                     /* True to enable memory status */
-  int bCoreMutex;                   /* True to enable core mutexing */
-  int bFullMutex;                   /* True to enable full mutexing */
 };
 
 /*
@@ -1782,16 +1778,20 @@ int sqlite3StrNICmp(const char *, const char *, int);
 int sqlite3IsNumber(const char*, int*, u8);
 
 int sqlite3MallocInit(void);
-void *sqlite3MallocZero(unsigned);
-void *sqlite3DbMallocZero(sqlite3*, unsigned);
-void *sqlite3DbMallocRaw(sqlite3*, unsigned);
+void sqlite3MallocEnd(void);
+void *sqlite3Malloc(int);
+void *sqlite3MallocZero(int);
+void *sqlite3DbMallocZero(sqlite3*, int);
+void *sqlite3DbMallocRaw(sqlite3*, int);
 char *sqlite3StrDup(const char*);
 char *sqlite3StrNDup(const char*, int);
 char *sqlite3DbStrDup(sqlite3*,const char*);
 char *sqlite3DbStrNDup(sqlite3*,const char*, int);
+void *sqlite3Realloc(void*, int);
 void *sqlite3DbReallocOrFree(sqlite3 *, void *, int);
 void *sqlite3DbRealloc(sqlite3 *, void *, int);
 int sqlite3MallocSize(void *);
+void sqlite3MemSetDefault(void);
 
 int sqlite3IsNaN(double);