From: dan Date: Tue, 17 Jul 2012 19:32:32 +0000 (+0000) Subject: Enhance the custom memory allocation interface to allow the user to specify a calloc... X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cb2b9c8e19c9f9a5332893253f6e619db63476e4;p=thirdparty%2Fsqlite.git Enhance the custom memory allocation interface to allow the user to specify a calloc() function. FossilOrigin-Name: 8752237d123240b330baa461f855dbc01ffcab5b --- diff --git a/manifest b/manifest index 8576e56420..88f8ef4219 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index dad8b25eaa..2db5f14677 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e4163596339c2166f9c4356ab824fff8bda8d0b0 \ No newline at end of file +8752237d123240b330baa461f855dbc01ffcab5b \ No newline at end of file diff --git a/src/main.c b/src/main.c index 16294a6199..4914b8aa1d 100644 --- a/src/main.c +++ b/src/main.c @@ -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); diff --git a/src/malloc.c b/src/malloc.c index 35a44e5f61..e49b15b1f2 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -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); } /* diff --git a/src/mem1.c b/src/mem1.c index 8bb8a2f1b3..50d724b195 100644 --- a/src/mem1.c +++ b/src/mem1.c @@ -70,6 +70,7 @@ #include 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 */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 69ea6d15d7..2eab0dde69 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -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