diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/malloc.c | 33 | ||||
-rw-r--r-- | src/pcache1.c | 19 | ||||
-rw-r--r-- | src/sqlite.h.in | 23 | ||||
-rw-r--r-- | src/sqliteInt.h | 9 | ||||
-rw-r--r-- | src/status.c | 86 | ||||
-rw-r--r-- | src/tokenize.c | 2 |
6 files changed, 129 insertions, 43 deletions
diff --git a/src/malloc.c b/src/malloc.c index 8046fb208..264d046ec 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -76,6 +76,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 ** limit. @@ -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{ diff --git a/src/pcache1.c b/src/pcache1.c index f5f789371..a8755a314 100644 --- a/src/pcache1.c +++ b/src/pcache1.c @@ -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 diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 9e48620c6..8419392cf 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -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 +); /* diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 9e174d6f4..78945c1dd 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3097,10 +3097,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 diff --git a/src/status.c b/src/status.c index 4c2eabb66..0f6328318 100644 --- a/src/status.c +++ b/src/status.c @@ -21,10 +21,27 @@ */ typedef struct sqlite3StatType sqlite3StatType; static SQLITE_WSD struct sqlite3StatType { - int nowValue[10]; /* Current value */ - int mxValue[10]; /* Maximum value */ + sqlite3_int64 nowValue[10]; /* Current value */ + sqlite3_int64 mxValue[10]; /* Maximum value */ } 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 +58,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,26 +120,42 @@ 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 +){ wsdStatInit; + sqlite3_mutex *pMutex; if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ return SQLITE_MISUSE_BKPT; } #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); + *pCurrent = (int)iCur; + *pHighwater = (int)iHwtr; + return rc; +} /* ** Query status information for a single database connection diff --git a/src/tokenize.c b/src/tokenize.c index 6fb5a35c3..5068742f3 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -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; |