]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Enhance the custom memory allocation interface to allow the user to specify a calloc...
authordan <dan@noemail.net>
Tue, 17 Jul 2012 19:32:32 +0000 (19:32 +0000)
committerdan <dan@noemail.net>
Tue, 17 Jul 2012 19:32:32 +0000 (19:32 +0000)
FossilOrigin-Name: 8752237d123240b330baa461f855dbc01ffcab5b

manifest
manifest.uuid
src/main.c
src/malloc.c
src/mem1.c
src/sqlite.h.in

index 8576e5642026f46fcb271496e0f2ae81cacbcf39..88f8ef42194c42a022fd702362f7a89cbb6e6e25 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Ensure\sthat\sthere\sis\salways\sat\sleast\sone\saReadMark\sslot\susable\sby\san\sunprivileged\sreader\swhile\sa\scheckpoint\sis\srunning.\sAlso,\sif\sone\sor\smore\stransactions\sare\srecovered\sfrom\sa\slog\sfile,\sinitialize\sone\sof\sthe\saReadMark\sslots\sto\scontain\smxFrame\sas\spart\sof\sthe\srecovery\sprocess.
-D 2012-07-17T14:37:12.494
+C Enhance\sthe\scustom\smemory\sallocation\sinterface\sto\sallow\sthe\suser\sto\sspecify\sa\scalloc()\sfunction.
+D 2012-07-17T19:32:32.796
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 8f6d858bf3df9978ba43df19985146a1173025e4
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -145,10 +145,10 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
 F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
 F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
 F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d
-F src/main.c 02255cf1da50956c5427c469abddb15bccc4ba09
-F src/malloc.c fe085aa851b666b7c375c1ff957643dc20a04bf6
+F src/main.c 0ce67958cf9cd68330c9c77d78dae275c867418e
+F src/malloc.c e80dccc5d2be2fc0335fb6f430247460e4211388
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
-F src/mem1.c b3677415e69603d6a0e7c5410a1b3731d55beda1
+F src/mem1.c bc33172c15cbd3d15f0e962311da955c8aba1295
 F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
 F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
 F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f
@@ -178,7 +178,7 @@ F src/resolve.c b3c70ab28cac60de33684c9aa9e5138dcf71d6dd
 F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1
 F src/select.c f6c4833c4d8e94714761d99013d74f381e084f1d
 F src/shell.c 076e1c90d594644f36027c8ecff9a392cf2d3a06
-F src/sqlite.h.in 310ae7e538883fa1619ab0638c775ce11ad43015
+F src/sqlite.h.in c660e2c8c5b5412d1ce51d58807353fa1dfdbee0
 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
 F src/sqliteInt.h 2bc2ebc2ff1a2b530ee5ed9ffd46c6fce93b244c
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
@@ -1005,7 +1005,10 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P 8c9ee1d78f99394eef73a177141ca9e1c67e4e07
-R 21a0c6942de3e9593e3e93f462c443c7
+P e4163596339c2166f9c4356ab824fff8bda8d0b0
+R 884dbf95b40a83feea70896cc9aa3953
+T *branch * calloc
+T *sym-calloc *
+T -sym-trunk *
 U dan
-Z a98d8c358c03bd601d60af308961371e
+Z a86d2e070abe26c339e2a7663eba53d5
index dad8b25eaa94210e88eacc6f7d4cde43dcfc1cf5..2db5f14677c3e732ac0f6c26576afc4d2f9d333b 100644 (file)
@@ -1 +1 @@
-e4163596339c2166f9c4356ab824fff8bda8d0b0
\ No newline at end of file
+8752237d123240b330baa461f855dbc01ffcab5b
\ No newline at end of file
index 16294a619977abac0edd5dd980716eb756526f4b..4914b8aa1dd6eb10eddfa0f8eee42174d94f8169 100644 (file)
@@ -302,6 +302,17 @@ int sqlite3_shutdown(void){
   return SQLITE_OK;
 }
 
+/*
+** If a custom memory allocator is configured using the legacy 
+** SQLITE_CONFIG_MALLOC interface, this function is used as the xCalloc()
+** method.
+*/
+static void *syntheticCalloc(int nByte){
+  void *pRet = sqlite3GlobalConfig.m.xMalloc(nByte);
+  if( pRet ) memset(pRet, 0, nByte);
+  return pRet;
+}
+
 /*
 ** This API allows applications to modify the global configuration of
 ** the SQLite library at run-time.
@@ -357,18 +368,33 @@ int sqlite3_config(int op, ...){
     }
 #endif
 
-
     case SQLITE_CONFIG_MALLOC: {
       /* Specify an alternative malloc implementation */
-      sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*);
+      int nCopy = offsetof(sqlite3_mem_methods, xCalloc);
+      memcpy(&sqlite3GlobalConfig.m, va_arg(ap, sqlite3_mem_methods*), nCopy);
+      sqlite3GlobalConfig.m.xCalloc = syntheticCalloc;
       break;
     }
     case SQLITE_CONFIG_GETMALLOC: {
+      /* Retrieve the current malloc() implementation */
+      int nCopy = offsetof(sqlite3_mem_methods, xCalloc);
+      if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault();
+      memcpy(va_arg(ap, sqlite3_mem_methods*), &sqlite3GlobalConfig.m, nCopy);
+      break;
+    }
+
+    case SQLITE_CONFIG_MALLOC2: {
+      /* Specify an alternative malloc implementation */
+      sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*);
+      break;
+    }
+    case SQLITE_CONFIG_GETMALLOC2: {
       /* Retrieve the current malloc() implementation */
       if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault();
       *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m;
       break;
     }
+
     case SQLITE_CONFIG_MEMSTATUS: {
       /* Enable or disable the malloc status collection */
       sqlite3GlobalConfig.bMemstat = va_arg(ap, int);
index 35a44e5f61c2e44c481c6251bd0aae7acda4de0b..e49b15b1f2c52809fcfe90493f6dc7cac7fe5d79 100644 (file)
@@ -259,10 +259,18 @@ static void sqlite3MallocAlarm(int nByte){
 ** Do a memory allocation with statistics and alarms.  Assume the
 ** lock is already held.
 */
-static int mallocWithAlarm(int n, void **pp){
+static int mallocWithAlarm(
+  void *(*xAlloc)(int),          /* Memory allocation function */
+  int n,                         /* Bytes of memory to allocate */
+  void **pp                      /* OUT: Pointer to allocation */
+){
   int nFull;
   void *p;
+
   assert( sqlite3_mutex_held(mem0.mutex) );
+  assert( xAlloc==sqlite3GlobalConfig.m.xMalloc 
+       || xAlloc==sqlite3GlobalConfig.m.xCalloc 
+  );
   nFull = sqlite3GlobalConfig.m.xRoundup(n);
   sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
   if( mem0.alarmCallback!=0 ){
@@ -274,11 +282,11 @@ static int mallocWithAlarm(int n, void **pp){
       mem0.nearlyFull = 0;
     }
   }
-  p = sqlite3GlobalConfig.m.xMalloc(nFull);
+  p = xAlloc(nFull);
 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
   if( p==0 && mem0.alarmCallback ){
     sqlite3MallocAlarm(nFull);
-    p = sqlite3GlobalConfig.m.xMalloc(nFull);
+    p = xAlloc(nFull);
   }
 #endif
   if( p ){
@@ -291,10 +299,12 @@ static int mallocWithAlarm(int n, void **pp){
 }
 
 /*
-** Allocate memory.  This routine is like sqlite3_malloc() except that it
-** assumes the memory subsystem has already been initialized.
+** Use allocator function xAlloc to allocate n bytes of memory.
 */
-void *sqlite3Malloc(int n){
+static void *memAllocate(
+  void *(*xAlloc)(int),           /* Memory allocation function */
+  int n                           /* Bytes of space to allocate */
+){
   void *p;
   if( n<=0               /* IMP: R-65312-04917 */ 
    || n>=0x7fffff00
@@ -307,15 +317,31 @@ void *sqlite3Malloc(int n){
     p = 0;
   }else if( sqlite3GlobalConfig.bMemstat ){
     sqlite3_mutex_enter(mem0.mutex);
-    mallocWithAlarm(n, &p);
+    mallocWithAlarm(xAlloc, n, &p);
     sqlite3_mutex_leave(mem0.mutex);
   }else{
-    p = sqlite3GlobalConfig.m.xMalloc(n);
+    p = xAlloc(n);
   }
   assert( EIGHT_BYTE_ALIGNMENT(p) );  /* IMP: R-04675-44850 */
   return p;
 }
 
+
+/*
+** Allocate memory.  This routine is like sqlite3_malloc() except that it
+** assumes the memory subsystem has already been initialized.
+*/
+void *sqlite3Malloc(int n){
+  return memAllocate(sqlite3GlobalConfig.m.xMalloc, n);
+}
+
+/*
+** Allocate and zero memory.
+*/ 
+void *sqlite3MallocZero(int n){
+  return memAllocate(sqlite3GlobalConfig.m.xCalloc, n);
+}
+
 /*
 ** This version of the memory allocation is for use by the application.
 ** First make sure the memory subsystem is initialized, then do the
@@ -362,7 +388,7 @@ void *sqlite3ScratchMalloc(int n){
   }else{
     if( sqlite3GlobalConfig.bMemstat ){
       sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
-      n = mallocWithAlarm(n, &p);
+      n = mallocWithAlarm(sqlite3GlobalConfig.m.xMalloc, n, &p);
       if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
       sqlite3_mutex_leave(mem0.mutex);
     }else{
@@ -570,33 +596,9 @@ void *sqlite3_realloc(void *pOld, int n){
   return sqlite3Realloc(pOld, n);
 }
 
-
-/*
-** Allocate and zero memory.
-*/ 
-void *sqlite3MallocZero(int n){
-  void *p = sqlite3Malloc(n);
-  if( p ){
-    memset(p, 0, n);
-  }
-  return p;
-}
-
-/*
-** Allocate and zero memory.  If the allocation fails, make
-** the mallocFailed flag in the connection pointer.
-*/
-void *sqlite3DbMallocZero(sqlite3 *db, int n){
-  void *p = sqlite3DbMallocRaw(db, n);
-  if( p ){
-    memset(p, 0, n);
-  }
-  return p;
-}
-
 /*
-** Allocate and zero memory.  If the allocation fails, make
-** the mallocFailed flag in the connection pointer.
+** Allocate and, if bZero is true, zero memory. If the allocation 
+** fails, set the mallocFailed flag in the connection pointer.
 **
 ** If db!=0 and db->mallocFailed is true (indicating a prior malloc
 ** failure on the same database connection) then always return 0.
@@ -612,7 +614,7 @@ void *sqlite3DbMallocZero(sqlite3 *db, int n){
 ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
 ** that all prior mallocs (ex: "a") worked too.
 */
-void *sqlite3DbMallocRaw(sqlite3 *db, int n){
+static void *dbMalloc(sqlite3 *db, int n, int bZero){
   void *p;
   assert( db==0 || sqlite3_mutex_held(db->mutex) );
   assert( db==0 || db->pnBytesFreed==0 );
@@ -634,6 +636,7 @@ void *sqlite3DbMallocRaw(sqlite3 *db, int n){
         if( db->lookaside.nOut>db->lookaside.mxOut ){
           db->lookaside.mxOut = db->lookaside.nOut;
         }
+        if( bZero ) memset(pBuf, 0, n);
         return (void*)pBuf;
       }
     }
@@ -643,13 +646,33 @@ void *sqlite3DbMallocRaw(sqlite3 *db, int n){
     return 0;
   }
 #endif
-  p = sqlite3Malloc(n);
+  if( bZero ){
+    p = sqlite3MallocZero(n);
+  }else{
+    p = sqlite3Malloc(n);
+  }
   if( !p && db ){
     db->mallocFailed = 1;
   }
   sqlite3MemdebugSetType(p, MEMTYPE_DB |
          ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
   return p;
+} 
+
+/*
+** Allocate and zero memory. If the allocation fails, set the 
+** mallocFailed flag in the connection pointer.
+*/
+void *sqlite3DbMallocZero(sqlite3 *db, int n){
+  return dbMalloc(db, n, 1);
+}
+
+/*
+** Allocate memory. If the allocation fails, make the mallocFailed 
+** flag in the connection pointer.
+*/
+void *sqlite3DbMallocRaw(sqlite3 *db, int n){
+  return dbMalloc(db, n, 0);
 }
 
 /*
index 8bb8a2f1b390cc0bd7c166fa240c4db9630dd0b5..50d724b195d84f416e3c017d723b069957e526d0 100644 (file)
@@ -70,6 +70,7 @@
 #include <libkern/OSAtomic.h>
 static malloc_zone_t* _sqliteZone_;
 #define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
+#define SQLITE_CALLOC(x) malloc_zone_calloc(_sqliteZone_, (x), 1)
 #define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
 #define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
 #define SQLITE_MALLOCSIZE(x) \
@@ -82,6 +83,7 @@ static malloc_zone_t* _sqliteZone_;
 ** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
 */
 #define SQLITE_MALLOC(x)    malloc(x)
+#define SQLITE_CALLOC(x)    calloc((x), 1)
 #define SQLITE_FREE(x)      free(x)
 #define SQLITE_REALLOC(x,y) realloc((x),(y))
 
@@ -100,16 +102,17 @@ static malloc_zone_t* _sqliteZone_;
 #endif /* __APPLE__ or not __APPLE__ */
 
 /*
-** Like malloc(), but remember the size of the allocation
-** so that we can find it later using sqlite3MemSize().
+** Like malloc() (if bZero==0) or calloc() (if bZero!=0), except 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 *sqlite3MemMalloc(int nByte){
+static void *memMalloc(int nByte, int bZero){
 #ifdef SQLITE_MALLOCSIZE
-  void *p = SQLITE_MALLOC( nByte );
+  void *p = (bZero ? SQLITE_CALLOC( nByte ) : SQLITE_MALLOC( nByte ));
   if( p==0 ){
     testcase( sqlite3GlobalConfig.xLog!=0 );
     sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
@@ -119,7 +122,7 @@ static void *sqlite3MemMalloc(int nByte){
   sqlite3_int64 *p;
   assert( nByte>0 );
   nByte = ROUND8(nByte);
-  p = SQLITE_MALLOC( nByte+8 );
+  p = (bZero ? SQLITE_CALLOC( nByte+8 ) : SQLITE_MALLOC( nByte+8 ));
   if( p ){
     p[0] = nByte;
     p++;
@@ -131,6 +134,13 @@ static void *sqlite3MemMalloc(int nByte){
 #endif
 }
 
+static void *sqlite3MemMalloc(int nByte){
+  return memMalloc(nByte, 0);
+}
+static void *sqlite3MemCalloc(int nByte){
+  return memMalloc(nByte, 1);
+}
+
 /*
 ** Like free() but works for allocations obtained from sqlite3MemMalloc()
 ** or sqlite3MemRealloc().
@@ -271,9 +281,10 @@ void sqlite3MemSetDefault(void){
      sqlite3MemRoundup,
      sqlite3MemInit,
      sqlite3MemShutdown,
-     0
+     0,
+     sqlite3MemCalloc
   };
-  sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+  sqlite3_config(SQLITE_CONFIG_MALLOC2, &defaultMethods);
 }
 
 #endif /* SQLITE_SYSTEM_MALLOC */
index 69ea6d15d7f99056595c155aec43fc2664e1ad44..2eab0dde69c3e654ef264d31c6ce78d97b3b8d76 100644 (file)
@@ -1341,6 +1341,7 @@ struct sqlite3_mem_methods {
   int (*xInit)(void*);           /* Initialize the memory allocator */
   void (*xShutdown)(void*);      /* Deinitialize the memory allocator */
   void *pAppData;                /* Argument to xInit() and xShutdown() */
+  void *(*xCalloc)(int);         /* Zeroed memory allocation function */
 };
 
 /*
@@ -1577,8 +1578,8 @@ struct sqlite3_mem_methods {
 #define SQLITE_CONFIG_PAGECACHE     7  /* void*, int sz, int N */
 #define SQLITE_CONFIG_HEAP          8  /* void*, int nByte, int min */
 #define SQLITE_CONFIG_MEMSTATUS     9  /* boolean */
-#define SQLITE_CONFIG_MUTEX        10  /* sqlite3_mutex_methods* */
-#define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* */
+#define SQLITE_CONFIG_MUTEX        10  /* sqlite3_mutex_methods* no xCalloc() */
+#define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* no xCalloc() */
 /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ 
 #define SQLITE_CONFIG_LOOKASIDE    13  /* int int */
 #define SQLITE_CONFIG_PCACHE       14  /* no-op */
@@ -1587,6 +1588,8 @@ struct sqlite3_mem_methods {
 #define SQLITE_CONFIG_URI          17  /* int */
 #define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
 #define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_MALLOC2      20  /* sqlite3_mem_methods* incl xCalloc() */
+#define SQLITE_CONFIG_GETMALLOC2   21  /* sqlite3_mem_methods* incl xCalloc() */
 
 /*
 ** CAPI3REF: Database Connection Configuration Options