/ Check-in [6fc4e79a]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment: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.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6fc4e79a2350295a15ac464593ad39d904953041
User & Date: drh 2015-03-23 19:55:21
Context
2015-03-23
21:32
Disable loadable extensions in the command-line shell on VxWorks user-space. check-in: 0ee2d38d user: drh tags: trunk
19:55
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. check-in: 6fc4e79a user: drh tags: trunk
19:16
Fix a non-C89 variable declaration that causes problems for MSVC. Closed-Leaf check-in: 3de085ea user: drh tags: status64
19:03
Fix datetype size asserts in btree.c. check-in: ff4812d0 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/main.c.

   123    123   
   124    124   #ifdef SQLITE_OMIT_WSD
   125    125     rc = sqlite3_wsd_init(4096, 24);
   126    126     if( rc!=SQLITE_OK ){
   127    127       return rc;
   128    128     }
   129    129   #endif
          130  +
          131  +  /* If the following assert() fails on some obscure processor/compiler
          132  +  ** combination, the work-around is to set the correct pointer
          133  +  ** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */
          134  +  assert( SQLITE_PTRSIZE==sizeof(char*) );
   130    135   
   131    136     /* If SQLite is already completely initialized, then this call
   132    137     ** to sqlite3_initialize() should be a no-op.  But the initialization
   133    138     ** must be complete.  So isInit must not be set until the very end
   134    139     ** of this routine.
   135    140     */
   136    141     if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;

Changes to src/malloc.c.

    70     70     ** True if heap is nearly "full" where "full" is defined by the
    71     71     ** sqlite3_soft_heap_limit() setting.
    72     72     */
    73     73     int nearlyFull;
    74     74   } mem0 = { 0, 0, 0, 0, 0, 0, 0, 0 };
    75     75   
    76     76   #define mem0 GLOBAL(struct Mem0Global, mem0)
           77  +
           78  +/*
           79  +** Return the memory allocator mutex. sqlite3_status() needs it.
           80  +*/
           81  +sqlite3_mutex *sqlite3MallocMutex(void){
           82  +  return mem0.mutex;
           83  +}
    77     84   
    78     85   /*
    79     86   ** This routine runs when the memory allocator sees that the
    80     87   ** total memory allocation is about to exceed the soft heap
    81     88   ** limit.
    82     89   */
    83     90   static void softHeapLimitEnforcer(
................................................................................
    93    100   ** Change the alarm callback
    94    101   */
    95    102   static int sqlite3MemoryAlarm(
    96    103     void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
    97    104     void *pArg,
    98    105     sqlite3_int64 iThreshold
    99    106   ){
   100         -  int nUsed;
          107  +  sqlite3_int64 nUsed;
   101    108     sqlite3_mutex_enter(mem0.mutex);
   102    109     mem0.alarmCallback = xCallback;
   103    110     mem0.alarmArg = pArg;
   104    111     mem0.alarmThreshold = iThreshold;
   105    112     nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
   106    113     mem0.nearlyFull = (iThreshold>0 && iThreshold<=nUsed);
   107    114     sqlite3_mutex_leave(mem0.mutex);
................................................................................
   262    269   static int mallocWithAlarm(int n, void **pp){
   263    270     int nFull;
   264    271     void *p;
   265    272     assert( sqlite3_mutex_held(mem0.mutex) );
   266    273     nFull = sqlite3GlobalConfig.m.xRoundup(n);
   267    274     sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
   268    275     if( mem0.alarmCallback!=0 ){
   269         -    int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
          276  +    sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
   270    277       if( nUsed >= mem0.alarmThreshold - nFull ){
   271    278         mem0.nearlyFull = 1;
   272    279         sqlite3MallocAlarm(nFull);
   273    280       }else{
   274    281         mem0.nearlyFull = 0;
   275    282       }
   276    283     }
................................................................................
   279    286     if( p==0 && mem0.alarmCallback ){
   280    287       sqlite3MallocAlarm(nFull);
   281    288       p = sqlite3GlobalConfig.m.xMalloc(nFull);
   282    289     }
   283    290   #endif
   284    291     if( p ){
   285    292       nFull = sqlite3MallocSize(p);
   286         -    sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
   287         -    sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
          293  +    sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull);
          294  +    sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
   288    295     }
   289    296     *pp = p;
   290    297     return nFull;
   291    298   }
   292    299   
   293    300   /*
   294    301   ** Allocate memory.  This routine is like sqlite3_malloc() except that it
................................................................................
   357    364   
   358    365     sqlite3_mutex_enter(mem0.mutex);
   359    366     sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
   360    367     if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
   361    368       p = mem0.pScratchFree;
   362    369       mem0.pScratchFree = mem0.pScratchFree->pNext;
   363    370       mem0.nScratchFree--;
   364         -    sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
          371  +    sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1);
   365    372       sqlite3_mutex_leave(mem0.mutex);
   366    373     }else{
   367    374       sqlite3_mutex_leave(mem0.mutex);
   368    375       p = sqlite3Malloc(n);
   369    376       if( sqlite3GlobalConfig.bMemstat && p ){
   370    377         sqlite3_mutex_enter(mem0.mutex);
   371         -      sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
          378  +      sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
   372    379         sqlite3_mutex_leave(mem0.mutex);
   373    380       }
   374    381       sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
   375    382     }
   376    383     assert( sqlite3_mutex_notheld(mem0.mutex) );
   377    384   
   378    385   
................................................................................
   405    412         ScratchFreeslot *pSlot;
   406    413         pSlot = (ScratchFreeslot*)p;
   407    414         sqlite3_mutex_enter(mem0.mutex);
   408    415         pSlot->pNext = mem0.pScratchFree;
   409    416         mem0.pScratchFree = pSlot;
   410    417         mem0.nScratchFree++;
   411    418         assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
   412         -      sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
          419  +      sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1);
   413    420         sqlite3_mutex_leave(mem0.mutex);
   414    421       }else{
   415    422         /* Release memory back to the heap */
   416    423         assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
   417    424         assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) );
   418    425         sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
   419    426         if( sqlite3GlobalConfig.bMemstat ){
   420    427           int iSize = sqlite3MallocSize(p);
   421    428           sqlite3_mutex_enter(mem0.mutex);
   422         -        sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
   423         -        sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
   424         -        sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
          429  +        sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize);
          430  +        sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize);
          431  +        sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
   425    432           sqlite3GlobalConfig.m.xFree(p);
   426    433           sqlite3_mutex_leave(mem0.mutex);
   427    434         }else{
   428    435           sqlite3GlobalConfig.m.xFree(p);
   429    436         }
   430    437       }
   431    438     }
................................................................................
   477    484   */
   478    485   void sqlite3_free(void *p){
   479    486     if( p==0 ) return;  /* IMP: R-49053-54554 */
   480    487     assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
   481    488     assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
   482    489     if( sqlite3GlobalConfig.bMemstat ){
   483    490       sqlite3_mutex_enter(mem0.mutex);
   484         -    sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
   485         -    sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
          491  +    sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p));
          492  +    sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
   486    493       sqlite3GlobalConfig.m.xFree(p);
   487    494       sqlite3_mutex_leave(mem0.mutex);
   488    495     }else{
   489    496       sqlite3GlobalConfig.m.xFree(p);
   490    497     }
   491    498   }
   492    499   
................................................................................
   566    573       pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
   567    574       if( pNew==0 && mem0.alarmCallback ){
   568    575         sqlite3MallocAlarm((int)nBytes);
   569    576         pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
   570    577       }
   571    578       if( pNew ){
   572    579         nNew = sqlite3MallocSize(pNew);
   573         -      sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
          580  +      sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
   574    581       }
   575    582       sqlite3_mutex_leave(mem0.mutex);
   576    583     }else{
   577    584       pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
   578    585     }
   579    586     assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-11148-40995 */
   580    587     return pNew;

Changes to src/pcache1.c.

   191    191   **
   192    192   ** Multiple threads can run this routine at the same time.  Global variables
   193    193   ** in pcache1 need to be protected via mutex.
   194    194   */
   195    195   static void *pcache1Alloc(int nByte){
   196    196     void *p = 0;
   197    197     assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
   198         -  sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
   199    198     if( nByte<=pcache1.szSlot ){
   200    199       sqlite3_mutex_enter(pcache1.mutex);
   201    200       p = (PgHdr1 *)pcache1.pFree;
   202    201       if( p ){
   203    202         pcache1.pFree = pcache1.pFree->pNext;
   204    203         pcache1.nFreeSlot--;
   205    204         pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
   206    205         assert( pcache1.nFreeSlot>=0 );
   207         -      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
          206  +      sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
          207  +      sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
   208    208       }
   209    209       sqlite3_mutex_leave(pcache1.mutex);
   210    210     }
   211    211     if( p==0 ){
   212    212       /* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool.  Get
   213    213       ** it from sqlite3Malloc instead.
   214    214       */
   215    215       p = sqlite3Malloc(nByte);
   216    216   #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
   217    217       if( p ){
   218    218         int sz = sqlite3MallocSize(p);
   219    219         sqlite3_mutex_enter(pcache1.mutex);
   220         -      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
          220  +      sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
          221  +      sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
   221    222         sqlite3_mutex_leave(pcache1.mutex);
   222    223       }
   223    224   #endif
   224    225       sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
   225    226     }
   226    227     return p;
   227    228   }
................................................................................
   231    232   */
   232    233   static int pcache1Free(void *p){
   233    234     int nFreed = 0;
   234    235     if( p==0 ) return 0;
   235    236     if( p>=pcache1.pStart && p<pcache1.pEnd ){
   236    237       PgFreeslot *pSlot;
   237    238       sqlite3_mutex_enter(pcache1.mutex);
   238         -    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
          239  +    sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1);
   239    240       pSlot = (PgFreeslot*)p;
   240    241       pSlot->pNext = pcache1.pFree;
   241    242       pcache1.pFree = pSlot;
   242    243       pcache1.nFreeSlot++;
   243    244       pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
   244    245       assert( pcache1.nFreeSlot<=pcache1.nSlot );
   245    246       sqlite3_mutex_leave(pcache1.mutex);
   246    247     }else{
   247    248       assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
   248    249       sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
   249    250       nFreed = sqlite3MallocSize(p);
   250    251   #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
   251    252       sqlite3_mutex_enter(pcache1.mutex);
   252         -    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed);
          253  +    sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed);
   253    254       sqlite3_mutex_leave(pcache1.mutex);
   254    255   #endif
   255    256       sqlite3_free(p);
   256    257     }
   257    258     return nFreed;
   258    259   }
   259    260   
................................................................................
   981    982     sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
   982    983   }
   983    984   
   984    985   /*
   985    986   ** Return the size of the header on each page of this PCACHE implementation.
   986    987   */
   987    988   int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); }
          989  +
          990  +/*
          991  +** Return the global mutex used by this PCACHE implementation.  The
          992  +** sqlite3_status() routine needs access to this mutex.
          993  +*/
          994  +sqlite3_mutex *sqlite3Pcache1Mutex(void){
          995  +  return pcache1.mutex;
          996  +}
   988    997   
   989    998   #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
   990    999   /*
   991   1000   ** This function is called to free superfluous dynamically allocated memory
   992   1001   ** held by the pager system. Memory in use by any SQLite pager allocated
   993   1002   ** by the current thread may be sqlite3_free()ed.
   994   1003   **

Changes to src/sqlite.h.in.

  1546   1546   ** interpreted as a boolean, which enables or disables the collection of
  1547   1547   ** memory allocation statistics. ^(When memory allocation statistics are
  1548   1548   ** disabled, the following SQLite interfaces become non-operational:
  1549   1549   **   <ul>
  1550   1550   **   <li> [sqlite3_memory_used()]
  1551   1551   **   <li> [sqlite3_memory_highwater()]
  1552   1552   **   <li> [sqlite3_soft_heap_limit64()]
  1553         -**   <li> [sqlite3_status()]
         1553  +**   <li> [sqlite3_status64()]
  1554   1554   **   </ul>)^
  1555   1555   ** ^Memory allocation statistics are enabled by default unless SQLite is
  1556   1556   ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
  1557   1557   ** allocation statistics are disabled by default.
  1558   1558   ** </dd>
  1559   1559   **
  1560   1560   ** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
................................................................................
  6301   6301   #define SQLITE_TESTCTRL_SORTER_MMAP             24
  6302   6302   #define SQLITE_TESTCTRL_IMPOSTER                25
  6303   6303   #define SQLITE_TESTCTRL_LAST                    25
  6304   6304   
  6305   6305   /*
  6306   6306   ** CAPI3REF: SQLite Runtime Status
  6307   6307   **
  6308         -** ^This interface is used to retrieve runtime status information
         6308  +** ^These interfaces are used to retrieve runtime status information
  6309   6309   ** about the performance of SQLite, and optionally to reset various
  6310   6310   ** highwater marks.  ^The first argument is an integer code for
  6311   6311   ** the specific parameter to measure.  ^(Recognized integer codes
  6312   6312   ** are of the form [status parameters | SQLITE_STATUS_...].)^
  6313   6313   ** ^The current value of the parameter is returned into *pCurrent.
  6314   6314   ** ^The highest recorded value is returned in *pHighwater.  ^If the
  6315   6315   ** resetFlag is true, then the highest record value is reset after
  6316   6316   ** *pHighwater is written.  ^(Some parameters do not record the highest
  6317   6317   ** value.  For those parameters
  6318   6318   ** nothing is written into *pHighwater and the resetFlag is ignored.)^
  6319   6319   ** ^(Other parameters record only the highwater mark and not the current
  6320   6320   ** value.  For these latter parameters nothing is written into *pCurrent.)^
  6321   6321   **
  6322         -** ^The sqlite3_status() routine returns SQLITE_OK on success and a
  6323         -** non-zero [error code] on failure.
         6322  +** ^The sqlite3_status() and sqlite3_status64() routines return
         6323  +** SQLITE_OK on success and a non-zero [error code] on failure.
  6324   6324   **
  6325         -** This routine is threadsafe but is not atomic.  This routine can be
  6326         -** called while other threads are running the same or different SQLite
  6327         -** interfaces.  However the values returned in *pCurrent and
  6328         -** *pHighwater reflect the status of SQLite at different points in time
  6329         -** and it is possible that another thread might change the parameter
  6330         -** in between the times when *pCurrent and *pHighwater are written.
         6325  +** If either the current value or the highwater mark is too large to
         6326  +** be represented by a 32-bit integer, then the values returned by
         6327  +** sqlite3_status() are undefined.
  6331   6328   **
  6332   6329   ** See also: [sqlite3_db_status()]
  6333   6330   */
  6334   6331   int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
         6332  +int sqlite3_status64(
         6333  +  int op,
         6334  +  sqlite3_int64 *pCurrent,
         6335  +  sqlite3_int64 *pHighwater,
         6336  +  int resetFlag
         6337  +);
  6335   6338   
  6336   6339   
  6337   6340   /*
  6338   6341   ** CAPI3REF: Status Parameters
  6339   6342   ** KEYWORDS: {status parameters}
  6340   6343   **
  6341   6344   ** These integer constants designate various run-time status parameters

Changes to src/sqliteInt.h.

   590    590   ** The LogEst can be negative to indicate fractional values. 
   591    591   ** Examples:
   592    592   **
   593    593   **    0.5 -> -10           0.1 -> -33        0.0625 -> -40
   594    594   */
   595    595   typedef INT16_TYPE LogEst;
   596    596   
          597  +/*
          598  +** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer
          599  +*/
          600  +#ifndef SQLITE_PTRSIZE
          601  +# if defined(__SIZEOF_POINTER__)
          602  +#   define SQLITE_PTRSIZE __SIZEOF_POINTER__
          603  +# elif defined(i386)     || defined(__i386__)   || defined(_M_IX86) ||    \
          604  +       defined(_M_ARM)   || defined(__arm__)    || defined(__x86)
          605  +#   define SQLITE_PTRSIZE 4
          606  +# else
          607  +#   define SQLITE_PTRSIZE 8
          608  +# endif
          609  +#endif
          610  +
   597    611   /*
   598    612   ** Macros to determine whether the machine is big or little endian,
   599    613   ** and whether or not that determination is run-time or compile-time.
   600    614   **
   601    615   ** For best performance, an attempt is made to guess at the byte-order
   602    616   ** using C-preprocessor macros.  If that is unsuccessful, or if
   603    617   ** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
................................................................................
  3093   3107     sqlite3_mutex_methods const *sqlite3DefaultMutex(void);
  3094   3108     sqlite3_mutex_methods const *sqlite3NoopMutex(void);
  3095   3109     sqlite3_mutex *sqlite3MutexAlloc(int);
  3096   3110     int sqlite3MutexInit(void);
  3097   3111     int sqlite3MutexEnd(void);
  3098   3112   #endif
  3099   3113   
  3100         -int sqlite3StatusValue(int);
  3101         -void sqlite3StatusAdd(int, int);
         3114  +sqlite3_int64 sqlite3StatusValue(int);
         3115  +void sqlite3StatusUp(int, int);
         3116  +void sqlite3StatusDown(int, int);
  3102   3117   void sqlite3StatusSet(int, int);
         3118  +
         3119  +/* Access to mutexes used by sqlite3_status() */
         3120  +sqlite3_mutex *sqlite3Pcache1Mutex(void);
         3121  +sqlite3_mutex *sqlite3MallocMutex(void);
  3103   3122   
  3104   3123   #ifndef SQLITE_OMIT_FLOATING_POINT
  3105   3124     int sqlite3IsNaN(double);
  3106   3125   #else
  3107   3126   # define sqlite3IsNaN(X)  0
  3108   3127   #endif
  3109   3128   

Changes to src/status.c.

    17     17   #include "vdbeInt.h"
    18     18   
    19     19   /*
    20     20   ** Variables in which to record status information.
    21     21   */
    22     22   typedef struct sqlite3StatType sqlite3StatType;
    23     23   static SQLITE_WSD struct sqlite3StatType {
    24         -  int nowValue[10];         /* Current value */
    25         -  int mxValue[10];          /* Maximum value */
           24  +#if SQLITE_PTRSIZE>4
           25  +  sqlite3_int64 nowValue[10];         /* Current value */
           26  +  sqlite3_int64 mxValue[10];          /* Maximum value */
           27  +#else
           28  +  u32 nowValue[10];                   /* Current value */
           29  +  u32 mxValue[10];                    /* Maximum value */
           30  +#endif
    26     31   } sqlite3Stat = { {0,}, {0,} };
           32  +
           33  +/*
           34  +** Elements of sqlite3Stat[] are protected by either the memory allocator
           35  +** mutex, or by the pcache1 mutex.  The following array determines which.
           36  +*/
           37  +static const char statMutex[] = {
           38  +  0,  /* SQLITE_STATUS_MEMORY_USED */
           39  +  1,  /* SQLITE_STATUS_PAGECACHE_USED */
           40  +  1,  /* SQLITE_STATUS_PAGECACHE_OVERFLOW */
           41  +  0,  /* SQLITE_STATUS_SCRATCH_USED */
           42  +  0,  /* SQLITE_STATUS_SCRATCH_OVERFLOW */
           43  +  0,  /* SQLITE_STATUS_MALLOC_SIZE */
           44  +  0,  /* SQLITE_STATUS_PARSER_STACK */
           45  +  1,  /* SQLITE_STATUS_PAGECACHE_SIZE */
           46  +  0,  /* SQLITE_STATUS_SCRATCH_SIZE */
           47  +  0,  /* SQLITE_STATUS_MALLOC_COUNT */
           48  +};
    27     49   
    28     50   
    29     51   /* The "wsdStat" macro will resolve to the status information
    30     52   ** state vector.  If writable static data is unsupported on the target,
    31     53   ** we have to locate the state vector at run-time.  In the more common
    32     54   ** case where writable static data is supported, wsdStat can refer directly
    33     55   ** to the "sqlite3Stat" state vector declared above.
................................................................................
    37     59   # define wsdStat x[0]
    38     60   #else
    39     61   # define wsdStatInit
    40     62   # define wsdStat sqlite3Stat
    41     63   #endif
    42     64   
    43     65   /*
    44         -** Return the current value of a status parameter.
           66  +** Return the current value of a status parameter.  The caller must
           67  +** be holding the appropriate mutex.
    45     68   */
    46         -int sqlite3StatusValue(int op){
           69  +sqlite3_int64 sqlite3StatusValue(int op){
    47     70     wsdStatInit;
    48     71     assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
           72  +  assert( op>=0 && op<ArraySize(statMutex) );
           73  +  assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
           74  +                                           : sqlite3MallocMutex()) );
    49     75     return wsdStat.nowValue[op];
    50     76   }
    51     77   
    52     78   /*
    53         -** Add N to the value of a status record.  It is assumed that the
    54         -** caller holds appropriate locks.
           79  +** Add N to the value of a status record.  The caller must hold the
           80  +** appropriate mutex.  (Locking is checked by assert()).
           81  +**
           82  +** The StatusUp() routine can accept positive or negative values for N.
           83  +** The value of N is added to the current status value and the high-water
           84  +** mark is adjusted if necessary.
           85  +**
           86  +** The StatusDown() routine lowers the current value by N.  The highwater
           87  +** mark is unchanged.  N must be non-negative for StatusDown().
    55     88   */
    56         -void sqlite3StatusAdd(int op, int N){
           89  +void sqlite3StatusUp(int op, int N){
    57     90     wsdStatInit;
    58     91     assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
           92  +  assert( op>=0 && op<ArraySize(statMutex) );
           93  +  assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
           94  +                                           : sqlite3MallocMutex()) );
    59     95     wsdStat.nowValue[op] += N;
    60     96     if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
    61     97       wsdStat.mxValue[op] = wsdStat.nowValue[op];
    62     98     }
    63     99   }
          100  +void sqlite3StatusDown(int op, int N){
          101  +  wsdStatInit;
          102  +  assert( N>=0 );
          103  +  assert( op>=0 && op<ArraySize(statMutex) );
          104  +  assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
          105  +                                           : sqlite3MallocMutex()) );
          106  +  assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
          107  +  wsdStat.nowValue[op] -= N;
          108  +}
    64    109   
    65    110   /*
    66         -** Set the value of a status to X.
          111  +** Set the value of a status to X.  The highwater mark is adjusted if
          112  +** necessary.  The caller must hold the appropriate mutex.
    67    113   */
    68    114   void sqlite3StatusSet(int op, int X){
    69    115     wsdStatInit;
    70    116     assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
          117  +  assert( op>=0 && op<ArraySize(statMutex) );
          118  +  assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
          119  +                                           : sqlite3MallocMutex()) );
    71    120     wsdStat.nowValue[op] = X;
    72    121     if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
    73    122       wsdStat.mxValue[op] = wsdStat.nowValue[op];
    74    123     }
    75    124   }
    76    125   
    77    126   /*
    78    127   ** Query status information.
    79         -**
    80         -** This implementation assumes that reading or writing an aligned
    81         -** 32-bit integer is an atomic operation.  If that assumption is not true,
    82         -** then this routine is not threadsafe.
    83    128   */
    84         -int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
          129  +int sqlite3_status64(
          130  +  int op,
          131  +  sqlite3_int64 *pCurrent,
          132  +  sqlite3_int64 *pHighwater,
          133  +  int resetFlag
          134  +){
          135  +  sqlite3_mutex *pMutex;
    85    136     wsdStatInit;
    86    137     if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
    87    138       return SQLITE_MISUSE_BKPT;
    88    139     }
    89    140   #ifdef SQLITE_ENABLE_API_ARMOR
    90    141     if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
    91    142   #endif
          143  +  pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex();
          144  +  sqlite3_mutex_enter(pMutex);
    92    145     *pCurrent = wsdStat.nowValue[op];
    93    146     *pHighwater = wsdStat.mxValue[op];
    94    147     if( resetFlag ){
    95    148       wsdStat.mxValue[op] = wsdStat.nowValue[op];
    96    149     }
          150  +  sqlite3_mutex_leave(pMutex);
    97    151     return SQLITE_OK;
          152  +}
          153  +int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
          154  +  sqlite3_int64 iCur, iHwtr;
          155  +  int rc;
          156  +#ifdef SQLITE_ENABLE_API_ARMOR
          157  +  if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
          158  +#endif
          159  +  rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag);
          160  +  if( rc==0 ){
          161  +    *pCurrent = (int)iCur;
          162  +    *pHighwater = (int)iHwtr;
          163  +  }
          164  +  return rc;
    98    165   }
    99    166   
   100    167   /*
   101    168   ** Query status information for a single database connection
   102    169   */
   103    170   int sqlite3_db_status(
   104    171     sqlite3 *db,          /* The database connection whose status is desired */

Changes to src/tokenize.c.

   455    455       if( lastTokenParsed!=TK_SEMI ){
   456    456         sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
   457    457         pParse->zTail = &zSql[i];
   458    458       }
   459    459       sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
   460    460     }
   461    461   #ifdef YYTRACKMAXSTACKDEPTH
          462  +  sqlite3_mutex_enter(sqlite3MallocMutex());
   462    463     sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK,
   463    464         sqlite3ParserStackPeak(pEngine)
   464    465     );
          466  +  sqlite3_mutex_leave(sqlite3MallocMutex());
   465    467   #endif /* YYDEBUG */
   466    468     sqlite3ParserFree(pEngine, sqlite3_free);
   467    469     db->lookaside.bEnabled = enableLookaside;
   468    470     if( db->mallocFailed ){
   469    471       pParse->rc = SQLITE_NOMEM;
   470    472     }
   471    473     if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){