From: drh Date: Sat, 14 Jun 2008 16:56:21 +0000 (+0000) Subject: Continuing progress on the new memory allocation subsystem. Added the X-Git-Tag: version-3.6.10~958 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fec00eabb3c144813164c9f04cc0fffd93c45247;p=thirdparty%2Fsqlite.git Continuing progress on the new memory allocation subsystem. Added the sqlite3_mem_methods structure for defining new memory allocators at run-time. (CVS 5219) FossilOrigin-Name: f00305f4cd2f487f660f34a21c1c24a0b37c7275 --- diff --git a/manifest b/manifest index 9c2e55197b..ce3a9c8557 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index dd6c30a8b3..119311b891 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a03c5af115889f477e17187a198a7d2d40bc76bf \ No newline at end of file +f00305f4cd2f487f660f34a21c1c24a0b37c7275 \ No newline at end of file diff --git a/src/global.c b/src/global.c index 6c21d89066..9d3a2eb1b8 100644 --- a/src/global.c +++ b/src/global.c @@ -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, }; diff --git a/src/main.c b/src/main.c index d98530cfb1..261fadf163 100644 --- a/src/main.c +++ b/src/main.c @@ -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 @@ -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; diff --git a/src/malloc.c b/src/malloc.c index 55d5c76dee..5916ec251e 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -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 @@ -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; } diff --git a/src/mem1.c b/src/mem1.c index 296dbe7650..e7491f8ab9 100644 --- a/src/mem1.c +++ b/src/mem1.c @@ -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" @@ -24,219 +29,112 @@ #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 */ diff --git a/src/mem2.c b/src/mem2.c index ff8c87a1b7..3206b25a50 100644 --- a/src/mem2.c +++ b/src/mem2.c @@ -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, nByteiSize ? 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; diff --git a/src/mutex.c b/src/mutex.c index 939f362558..82812bc759 100644 --- a/src/mutex.c +++ b/src/mutex.c @@ -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) ); + } } /* diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 3e1cdccc0a..ea46093eee 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -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. ** **
SQLITE_CONFIG_MALLOC
-**
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.
-** -**
SQLITE_CONFIG_MEMSTATS
+**
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.
+** +**
SQLITE_CONFIG_MEMSTATUS
**
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_MEMSTATS 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 */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d2cb424c19..6b9eda6c8e 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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);