mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-19 21:43:15 +03:00
Track total memory usage using a 64-bit integer on 64-bit systems. Add
the sqlite3_status64() interface. Make the sqlite3_status() and sqlite3_status64() interfaces atomic using mutexes and verify correct mutex operation using assert() statements. FossilOrigin-Name: 6fc4e79a2350295a15ac464593ad39d904953041
This commit is contained in:
@@ -128,6 +128,11 @@ int sqlite3_initialize(void){
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the following assert() fails on some obscure processor/compiler
|
||||
** combination, the work-around is to set the correct pointer
|
||||
** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */
|
||||
assert( SQLITE_PTRSIZE==sizeof(char*) );
|
||||
|
||||
/* If SQLite is already completely initialized, then this call
|
||||
** to sqlite3_initialize() should be a no-op. But the initialization
|
||||
** must be complete. So isInit must not be set until the very end
|
||||
|
||||
33
src/malloc.c
33
src/malloc.c
@@ -75,6 +75,13 @@ static SQLITE_WSD struct Mem0Global {
|
||||
|
||||
#define mem0 GLOBAL(struct Mem0Global, mem0)
|
||||
|
||||
/*
|
||||
** Return the memory allocator mutex. sqlite3_status() needs it.
|
||||
*/
|
||||
sqlite3_mutex *sqlite3MallocMutex(void){
|
||||
return mem0.mutex;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine runs when the memory allocator sees that the
|
||||
** total memory allocation is about to exceed the soft heap
|
||||
@@ -97,7 +104,7 @@ static int sqlite3MemoryAlarm(
|
||||
void *pArg,
|
||||
sqlite3_int64 iThreshold
|
||||
){
|
||||
int nUsed;
|
||||
sqlite3_int64 nUsed;
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
mem0.alarmCallback = xCallback;
|
||||
mem0.alarmArg = pArg;
|
||||
@@ -266,7 +273,7 @@ static int mallocWithAlarm(int n, void **pp){
|
||||
nFull = sqlite3GlobalConfig.m.xRoundup(n);
|
||||
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
|
||||
if( mem0.alarmCallback!=0 ){
|
||||
int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
if( nUsed >= mem0.alarmThreshold - nFull ){
|
||||
mem0.nearlyFull = 1;
|
||||
sqlite3MallocAlarm(nFull);
|
||||
@@ -283,8 +290,8 @@ static int mallocWithAlarm(int n, void **pp){
|
||||
#endif
|
||||
if( p ){
|
||||
nFull = sqlite3MallocSize(p);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull);
|
||||
sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
}
|
||||
*pp = p;
|
||||
return nFull;
|
||||
@@ -361,14 +368,14 @@ void *sqlite3ScratchMalloc(int n){
|
||||
p = mem0.pScratchFree;
|
||||
mem0.pScratchFree = mem0.pScratchFree->pNext;
|
||||
mem0.nScratchFree--;
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
|
||||
sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
p = sqlite3Malloc(n);
|
||||
if( sqlite3GlobalConfig.bMemstat && p ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
|
||||
sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
|
||||
@@ -409,7 +416,7 @@ void sqlite3ScratchFree(void *p){
|
||||
mem0.pScratchFree = pSlot;
|
||||
mem0.nScratchFree++;
|
||||
assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
|
||||
sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
/* Release memory back to the heap */
|
||||
@@ -419,9 +426,9 @@ void sqlite3ScratchFree(void *p){
|
||||
if( sqlite3GlobalConfig.bMemstat ){
|
||||
int iSize = sqlite3MallocSize(p);
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
|
||||
sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize);
|
||||
sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize);
|
||||
sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
sqlite3GlobalConfig.m.xFree(p);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
@@ -481,8 +488,8 @@ void sqlite3_free(void *p){
|
||||
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
||||
if( sqlite3GlobalConfig.bMemstat ){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
|
||||
sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p));
|
||||
sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
|
||||
sqlite3GlobalConfig.m.xFree(p);
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
@@ -570,7 +577,7 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
|
||||
}
|
||||
if( pNew ){
|
||||
nNew = sqlite3MallocSize(pNew);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
|
||||
sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
|
||||
}
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
|
||||
@@ -195,7 +195,6 @@ void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
|
||||
static void *pcache1Alloc(int nByte){
|
||||
void *p = 0;
|
||||
assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
|
||||
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
||||
if( nByte<=pcache1.szSlot ){
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
p = (PgHdr1 *)pcache1.pFree;
|
||||
@@ -204,7 +203,8 @@ static void *pcache1Alloc(int nByte){
|
||||
pcache1.nFreeSlot--;
|
||||
pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
|
||||
assert( pcache1.nFreeSlot>=0 );
|
||||
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
|
||||
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
||||
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
|
||||
}
|
||||
sqlite3_mutex_leave(pcache1.mutex);
|
||||
}
|
||||
@@ -217,7 +217,8 @@ static void *pcache1Alloc(int nByte){
|
||||
if( p ){
|
||||
int sz = sqlite3MallocSize(p);
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
|
||||
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
||||
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
|
||||
sqlite3_mutex_leave(pcache1.mutex);
|
||||
}
|
||||
#endif
|
||||
@@ -235,7 +236,7 @@ static int pcache1Free(void *p){
|
||||
if( p>=pcache1.pStart && p<pcache1.pEnd ){
|
||||
PgFreeslot *pSlot;
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
|
||||
sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1);
|
||||
pSlot = (PgFreeslot*)p;
|
||||
pSlot->pNext = pcache1.pFree;
|
||||
pcache1.pFree = pSlot;
|
||||
@@ -249,7 +250,7 @@ static int pcache1Free(void *p){
|
||||
nFreed = sqlite3MallocSize(p);
|
||||
#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed);
|
||||
sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed);
|
||||
sqlite3_mutex_leave(pcache1.mutex);
|
||||
#endif
|
||||
sqlite3_free(p);
|
||||
@@ -986,6 +987,14 @@ void sqlite3PCacheSetDefault(void){
|
||||
*/
|
||||
int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); }
|
||||
|
||||
/*
|
||||
** Return the global mutex used by this PCACHE implementation. The
|
||||
** sqlite3_status() routine needs access to this mutex.
|
||||
*/
|
||||
sqlite3_mutex *sqlite3Pcache1Mutex(void){
|
||||
return pcache1.mutex;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
/*
|
||||
** This function is called to free superfluous dynamically allocated memory
|
||||
|
||||
@@ -1550,7 +1550,7 @@ struct sqlite3_mem_methods {
|
||||
** <li> [sqlite3_memory_used()]
|
||||
** <li> [sqlite3_memory_highwater()]
|
||||
** <li> [sqlite3_soft_heap_limit64()]
|
||||
** <li> [sqlite3_status()]
|
||||
** <li> [sqlite3_status64()]
|
||||
** </ul>)^
|
||||
** ^Memory allocation statistics are enabled by default unless SQLite is
|
||||
** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
|
||||
@@ -6305,7 +6305,7 @@ int sqlite3_test_control(int op, ...);
|
||||
/*
|
||||
** CAPI3REF: SQLite Runtime Status
|
||||
**
|
||||
** ^This interface is used to retrieve runtime status information
|
||||
** ^These interfaces are used to retrieve runtime status information
|
||||
** about the performance of SQLite, and optionally to reset various
|
||||
** highwater marks. ^The first argument is an integer code for
|
||||
** the specific parameter to measure. ^(Recognized integer codes
|
||||
@@ -6319,19 +6319,22 @@ int sqlite3_test_control(int op, ...);
|
||||
** ^(Other parameters record only the highwater mark and not the current
|
||||
** value. For these latter parameters nothing is written into *pCurrent.)^
|
||||
**
|
||||
** ^The sqlite3_status() routine returns SQLITE_OK on success and a
|
||||
** non-zero [error code] on failure.
|
||||
** ^The sqlite3_status() and sqlite3_status64() routines return
|
||||
** SQLITE_OK on success and a non-zero [error code] on failure.
|
||||
**
|
||||
** This routine is threadsafe but is not atomic. This routine can be
|
||||
** called while other threads are running the same or different SQLite
|
||||
** interfaces. However the values returned in *pCurrent and
|
||||
** *pHighwater reflect the status of SQLite at different points in time
|
||||
** and it is possible that another thread might change the parameter
|
||||
** in between the times when *pCurrent and *pHighwater are written.
|
||||
** If either the current value or the highwater mark is too large to
|
||||
** be represented by a 32-bit integer, then the values returned by
|
||||
** sqlite3_status() are undefined.
|
||||
**
|
||||
** See also: [sqlite3_db_status()]
|
||||
*/
|
||||
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
int sqlite3_status64(
|
||||
int op,
|
||||
sqlite3_int64 *pCurrent,
|
||||
sqlite3_int64 *pHighwater,
|
||||
int resetFlag
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -594,6 +594,20 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
|
||||
*/
|
||||
typedef INT16_TYPE LogEst;
|
||||
|
||||
/*
|
||||
** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer
|
||||
*/
|
||||
#ifndef SQLITE_PTRSIZE
|
||||
# if defined(__SIZEOF_POINTER__)
|
||||
# define SQLITE_PTRSIZE __SIZEOF_POINTER__
|
||||
# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
|
||||
defined(_M_ARM) || defined(__arm__) || defined(__x86)
|
||||
# define SQLITE_PTRSIZE 4
|
||||
# else
|
||||
# define SQLITE_PTRSIZE 8
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Macros to determine whether the machine is big or little endian,
|
||||
** and whether or not that determination is run-time or compile-time.
|
||||
@@ -3097,10 +3111,15 @@ const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
|
||||
int sqlite3MutexEnd(void);
|
||||
#endif
|
||||
|
||||
int sqlite3StatusValue(int);
|
||||
void sqlite3StatusAdd(int, int);
|
||||
sqlite3_int64 sqlite3StatusValue(int);
|
||||
void sqlite3StatusUp(int, int);
|
||||
void sqlite3StatusDown(int, int);
|
||||
void sqlite3StatusSet(int, int);
|
||||
|
||||
/* Access to mutexes used by sqlite3_status() */
|
||||
sqlite3_mutex *sqlite3Pcache1Mutex(void);
|
||||
sqlite3_mutex *sqlite3MallocMutex(void);
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
int sqlite3IsNaN(double);
|
||||
#else
|
||||
|
||||
93
src/status.c
93
src/status.c
@@ -21,10 +21,32 @@
|
||||
*/
|
||||
typedef struct sqlite3StatType sqlite3StatType;
|
||||
static SQLITE_WSD struct sqlite3StatType {
|
||||
int nowValue[10]; /* Current value */
|
||||
int mxValue[10]; /* Maximum value */
|
||||
#if SQLITE_PTRSIZE>4
|
||||
sqlite3_int64 nowValue[10]; /* Current value */
|
||||
sqlite3_int64 mxValue[10]; /* Maximum value */
|
||||
#else
|
||||
u32 nowValue[10]; /* Current value */
|
||||
u32 mxValue[10]; /* Maximum value */
|
||||
#endif
|
||||
} sqlite3Stat = { {0,}, {0,} };
|
||||
|
||||
/*
|
||||
** Elements of sqlite3Stat[] are protected by either the memory allocator
|
||||
** mutex, or by the pcache1 mutex. The following array determines which.
|
||||
*/
|
||||
static const char statMutex[] = {
|
||||
0, /* SQLITE_STATUS_MEMORY_USED */
|
||||
1, /* SQLITE_STATUS_PAGECACHE_USED */
|
||||
1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */
|
||||
0, /* SQLITE_STATUS_SCRATCH_USED */
|
||||
0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */
|
||||
0, /* SQLITE_STATUS_MALLOC_SIZE */
|
||||
0, /* SQLITE_STATUS_PARSER_STACK */
|
||||
1, /* SQLITE_STATUS_PAGECACHE_SIZE */
|
||||
0, /* SQLITE_STATUS_SCRATCH_SIZE */
|
||||
0, /* SQLITE_STATUS_MALLOC_COUNT */
|
||||
};
|
||||
|
||||
|
||||
/* The "wsdStat" macro will resolve to the status information
|
||||
** state vector. If writable static data is unsupported on the target,
|
||||
@@ -41,33 +63,60 @@ static SQLITE_WSD struct sqlite3StatType {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return the current value of a status parameter.
|
||||
** Return the current value of a status parameter. The caller must
|
||||
** be holding the appropriate mutex.
|
||||
*/
|
||||
int sqlite3StatusValue(int op){
|
||||
sqlite3_int64 sqlite3StatusValue(int op){
|
||||
wsdStatInit;
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
return wsdStat.nowValue[op];
|
||||
}
|
||||
|
||||
/*
|
||||
** Add N to the value of a status record. It is assumed that the
|
||||
** caller holds appropriate locks.
|
||||
** Add N to the value of a status record. The caller must hold the
|
||||
** appropriate mutex. (Locking is checked by assert()).
|
||||
**
|
||||
** The StatusUp() routine can accept positive or negative values for N.
|
||||
** The value of N is added to the current status value and the high-water
|
||||
** mark is adjusted if necessary.
|
||||
**
|
||||
** The StatusDown() routine lowers the current value by N. The highwater
|
||||
** mark is unchanged. N must be non-negative for StatusDown().
|
||||
*/
|
||||
void sqlite3StatusAdd(int op, int N){
|
||||
void sqlite3StatusUp(int op, int N){
|
||||
wsdStatInit;
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
wsdStat.nowValue[op] += N;
|
||||
if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
|
||||
wsdStat.mxValue[op] = wsdStat.nowValue[op];
|
||||
}
|
||||
}
|
||||
void sqlite3StatusDown(int op, int N){
|
||||
wsdStatInit;
|
||||
assert( N>=0 );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
wsdStat.nowValue[op] -= N;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the value of a status to X.
|
||||
** Set the value of a status to X. The highwater mark is adjusted if
|
||||
** necessary. The caller must hold the appropriate mutex.
|
||||
*/
|
||||
void sqlite3StatusSet(int op, int X){
|
||||
wsdStatInit;
|
||||
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
||||
assert( op>=0 && op<ArraySize(statMutex) );
|
||||
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
||||
: sqlite3MallocMutex()) );
|
||||
wsdStat.nowValue[op] = X;
|
||||
if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
|
||||
wsdStat.mxValue[op] = wsdStat.nowValue[op];
|
||||
@@ -76,12 +125,14 @@ void sqlite3StatusSet(int op, int X){
|
||||
|
||||
/*
|
||||
** Query status information.
|
||||
**
|
||||
** This implementation assumes that reading or writing an aligned
|
||||
** 32-bit integer is an atomic operation. If that assumption is not true,
|
||||
** then this routine is not threadsafe.
|
||||
*/
|
||||
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
int sqlite3_status64(
|
||||
int op,
|
||||
sqlite3_int64 *pCurrent,
|
||||
sqlite3_int64 *pHighwater,
|
||||
int resetFlag
|
||||
){
|
||||
sqlite3_mutex *pMutex;
|
||||
wsdStatInit;
|
||||
if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
@@ -89,13 +140,29 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex();
|
||||
sqlite3_mutex_enter(pMutex);
|
||||
*pCurrent = wsdStat.nowValue[op];
|
||||
*pHighwater = wsdStat.mxValue[op];
|
||||
if( resetFlag ){
|
||||
wsdStat.mxValue[op] = wsdStat.nowValue[op];
|
||||
}
|
||||
sqlite3_mutex_leave(pMutex);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
||||
sqlite3_int64 iCur, iHwtr;
|
||||
int rc;
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
|
||||
#endif
|
||||
rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag);
|
||||
if( rc==0 ){
|
||||
*pCurrent = (int)iCur;
|
||||
*pHighwater = (int)iHwtr;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Query status information for a single database connection
|
||||
|
||||
@@ -459,9 +459,11 @@ abort_parse:
|
||||
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
|
||||
}
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
sqlite3_mutex_enter(sqlite3MallocMutex());
|
||||
sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK,
|
||||
sqlite3ParserStackPeak(pEngine)
|
||||
);
|
||||
sqlite3_mutex_leave(sqlite3MallocMutex());
|
||||
#endif /* YYDEBUG */
|
||||
sqlite3ParserFree(pEngine, sqlite3_free);
|
||||
db->lookaside.bEnabled = enableLookaside;
|
||||
|
||||
Reference in New Issue
Block a user