/ Check-in [d094a1bf]
Login

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

Overview
Comment:Here is a completely new implementation of the mutex-free-pcache. This one uses a common code base and automatically selects whether or not to use mutexes depending on compile-time and start-time options.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | mutex-free-pcache
Files: files | file ages | folders
SHA1: d094a1bfb7569a52b637fe9ba5d3fa6ce5ea6d94
User & Date: drh 2011-01-17 21:32:24
Context
2011-01-18
15:17
Do not use SQLITE_MUTEX_STATIC_MEM2 since it has been reused as STATIC_OPEN. Instead, create a new static mutex STATIC_PMEM which is an alias for the unused STATIC_LRU2. check-in: f1cf02ef user: drh tags: mutex-free-pcache
2011-01-17
21:32
Here is a completely new implementation of the mutex-free-pcache. This one uses a common code base and automatically selects whether or not to use mutexes depending on compile-time and start-time options. check-in: d094a1bf user: drh tags: mutex-free-pcache
18:30
Fix a typo in the documentation for sqlite3_stmt_readonly(). check-in: 56417a33 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pcache1.c.

    18     18   */
    19     19   
    20     20   #include "sqliteInt.h"
    21     21   
    22     22   typedef struct PCache1 PCache1;
    23     23   typedef struct PgHdr1 PgHdr1;
    24     24   typedef struct PgFreeslot PgFreeslot;
           25  +typedef struct PGroup PGroup;
           26  +
           27  +/* Each page cache (or PCache) belongs to a PGroup.  A PGroup is a set 
           28  +** of one or more PCaches that are able to recycle each others unpinned
           29  +** pages when they are under memory pressure.  A PGroup is an instance of
           30  +** the following object.
           31  +**
           32  +** This page cache implementation works in one of two modes:
           33  +**
           34  +**   (1)  Every PCache is the sole member of its own PGroup.  There is
           35  +**        one PGroup per PCache.
           36  +**
           37  +**   (2)  There is a single global PGroup that all PCaches are a member
           38  +**        of.
           39  +**
           40  +** Mode 1 uses more memory (since PCache instances are not able to rob
           41  +** unused pages from other PCaches) but it also operates without a mutex,
           42  +** and is therefore often faster.  Mode 2 requires a mutex in order to be
           43  +** threadsafe, but is able recycle pages more efficient.
           44  +**
           45  +** For mode (1), PGroup.mutex is NULL.  For mode (2) there is only a single
           46  +** PGroup which is the pcache1.grp global variable and its mutex is
           47  +** SQLITE_MUTEX_STATIC_LRU.
           48  +*/
           49  +struct PGroup {
           50  +  sqlite3_mutex *mutex;          /* MUTEX_STATIC_LRU or NULL */
           51  +  int nMaxPage;                  /* Sum of nMax for purgeable caches */
           52  +  int nMinPage;                  /* Sum of nMin for purgeable caches */
           53  +  int nCurrentPage;              /* Number of purgeable pages allocated */
           54  +  PgHdr1 *pLruHead, *pLruTail;   /* LRU list of unpinned pages */
           55  +};
    25     56   
    26     57   /* Each page cache is an instance of the following object.  Every
    27     58   ** open database file (including each in-memory database and each
    28     59   ** temporary or transient database) has a single page cache which
    29     60   ** is an instance of this object.
    30     61   **
    31     62   ** Pointers to structures of this type are cast and returned as 
    32     63   ** opaque sqlite3_pcache* handles.
    33     64   */
    34     65   struct PCache1 {
    35     66     /* Cache configuration parameters. Page size (szPage) and the purgeable
    36     67     ** flag (bPurgeable) are set when the cache is created. nMax may be 
    37     68     ** modified at any time by a call to the pcache1CacheSize() method.
    38         -  ** The global mutex must be held when accessing nMax.
           69  +  ** The PGroup mutex must be held when accessing nMax.
    39     70     */
           71  +  PGroup *pGroup;                     /* PGroup this cache belongs to */
    40     72     int szPage;                         /* Size of allocated pages in bytes */
    41     73     int bPurgeable;                     /* True if cache is purgeable */
    42     74     unsigned int nMin;                  /* Minimum number of pages reserved */
    43     75     unsigned int nMax;                  /* Configured "cache_size" value */
    44     76   
    45     77     /* Hash table of all pages. The following variables may only be accessed
    46         -  ** when the accessor is holding the global mutex (see pcache1EnterMutex() 
    47         -  ** and pcache1LeaveMutex()).
           78  +  ** when the accessor is holding the PGroup mutex.
    48     79     */
    49     80     unsigned int nRecyclable;           /* Number of pages in the LRU list */
    50     81     unsigned int nPage;                 /* Total number of pages in apHash */
    51     82     unsigned int nHash;                 /* Number of slots in apHash[] */
    52     83     PgHdr1 **apHash;                    /* Hash table for fast lookup by key */
    53     84   
    54     85     unsigned int iMaxKey;               /* Largest key seen since xTruncate() */
................................................................................
    76    107     PgFreeslot *pNext;  /* Next free slot */
    77    108   };
    78    109   
    79    110   /*
    80    111   ** Global data used by this cache.
    81    112   */
    82    113   static SQLITE_WSD struct PCacheGlobal {
    83         -  sqlite3_mutex *mutex;               /* static mutex MUTEX_STATIC_LRU */
          114  +  PGroup grp;                    /* The global PGroup for mode (2) */
    84    115   
    85         -  int nMaxPage;                       /* Sum of nMaxPage for purgeable caches */
    86         -  int nMinPage;                       /* Sum of nMinPage for purgeable caches */
    87         -  int nCurrentPage;                   /* Number of purgeable pages allocated */
    88         -  PgHdr1 *pLruHead, *pLruTail;        /* LRU list of unpinned pages */
    89         -
    90         -  /* Variables related to SQLITE_CONFIG_PAGECACHE settings. */
    91         -  int szSlot;                         /* Size of each free slot */
    92         -  int nSlot;                          /* The number of pcache slots */
    93         -  int nFreeSlot;                      /* Number of unused pcache slots */
    94         -  int nReserve;                       /* Try to keep nFreeSlot above this */
    95         -  void *pStart, *pEnd;                /* Bounds of pagecache malloc range */
    96         -  PgFreeslot *pFree;                  /* Free page blocks */
    97         -  int isInit;                         /* True if initialized */
          116  +  /* Variables related to SQLITE_CONFIG_PAGECACHE settings.  The
          117  +  ** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all
          118  +  ** fixed at sqlite3_initialize() time and do not require mutex protection.
          119  +  ** The nFreeSlot and pFree values do require mutex protection.
          120  +  */
          121  +  int isInit;                    /* True if initialized */
          122  +  int szSlot;                    /* Size of each free slot */
          123  +  int nSlot;                     /* The number of pcache slots */
          124  +  int nReserve;                  /* Try to keep nFreeSlot above this */
          125  +  void *pStart, *pEnd;           /* Bounds of pagecache malloc range */
          126  +  /* Above requires no mutex.  Use mutex below for variable that follow. */
          127  +  sqlite3_mutex *mutex;          /* Mutex for accessing the following: */
          128  +  int nFreeSlot;                 /* Number of unused pcache slots */
          129  +  PgFreeslot *pFree;             /* Free page blocks */
          130  +  /* The following value requires a mutex to change.  We skip the mutex on
          131  +  ** reading because (1) most platforms read a 32-bit integer atomically and
          132  +  ** (2) even if an incorrect value is read, no great harm is done since this
          133  +  ** is really just an optimization. */
          134  +  int bUnderPressure;            /* True if low on PAGECACHE memory */
    98    135   } pcache1_g;
    99    136   
   100    137   /*
   101    138   ** All code in this file should access the global structure above via the
   102    139   ** alias "pcache1". This ensures that the WSD emulation is used when
   103    140   ** compiling for systems that do not support real WSD.
   104    141   */
................................................................................
   116    153   **
   117    154   **   assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(pCache, X))==X );
   118    155   */
   119    156   #define PGHDR1_TO_PAGE(p)    (void*)(((char*)p) - p->pCache->szPage)
   120    157   #define PAGE_TO_PGHDR1(c, p) (PgHdr1*)(((char*)p) + c->szPage)
   121    158   
   122    159   /*
   123         -** Macros to enter and leave the global LRU mutex.
          160  +** Macros to enter and leave the PCache LRU mutex.
   124    161   */
   125         -#define pcache1EnterMutex() sqlite3_mutex_enter(pcache1.mutex)
   126         -#define pcache1LeaveMutex() sqlite3_mutex_leave(pcache1.mutex)
          162  +#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
          163  +#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
   127    164   
   128    165   /******************************************************************************/
   129    166   /******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
   130    167   
   131    168   /*
   132    169   ** This function is called during initialization if a static buffer is 
   133    170   ** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
   134    171   ** verb to sqlite3_config(). Parameter pBuf points to an allocation large
   135    172   ** enough to contain 'n' buffers of 'sz' bytes each.
          173  +**
          174  +** This routine is called from sqlite3_initialize() and so it is guaranteed
          175  +** to be serialized already.  There is no need for further mutexing.
   136    176   */
   137    177   void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
   138    178     if( pcache1.isInit ){
   139    179       PgFreeslot *p;
   140    180       sz = ROUNDDOWN8(sz);
   141    181       pcache1.szSlot = sz;
   142    182       pcache1.nSlot = pcache1.nFreeSlot = n;
   143    183       pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
   144    184       pcache1.pStart = pBuf;
   145    185       pcache1.pFree = 0;
          186  +    pcache1.bUnderPressure = 0;
   146    187       while( n-- ){
   147    188         p = (PgFreeslot*)pBuf;
   148    189         p->pNext = pcache1.pFree;
   149    190         pcache1.pFree = p;
   150    191         pBuf = (void*)&((char*)pBuf)[sz];
   151    192       }
   152    193       pcache1.pEnd = pBuf;
................................................................................
   154    195   }
   155    196   
   156    197   /*
   157    198   ** Malloc function used within this file to allocate space from the buffer
   158    199   ** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no 
   159    200   ** such buffer exists or there is no space left in it, this function falls 
   160    201   ** back to sqlite3Malloc().
          202  +**
          203  +** Multiple threads can run this routine at the same time.  Global variables
          204  +** in pcache1 need to be protected via mutex.
   161    205   */
   162    206   static void *pcache1Alloc(int nByte){
   163         -  void *p;
   164         -  assert( sqlite3_mutex_held(pcache1.mutex) );
          207  +  void *p = 0;
          208  +  assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
   165    209     sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
   166         -  if( nByte<=pcache1.szSlot && pcache1.pFree ){
   167         -    assert( pcache1.isInit );
          210  +  if( nByte<=pcache1.szSlot ){
          211  +    sqlite3_mutex_enter(pcache1.mutex);
   168    212       p = (PgHdr1 *)pcache1.pFree;
   169         -    pcache1.pFree = pcache1.pFree->pNext;
   170         -    pcache1.nFreeSlot--;
   171         -    assert( pcache1.nFreeSlot>=0 );
   172         -    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
   173         -  }else{
   174         -
   175         -    /* Allocate a new buffer using sqlite3Malloc. Before doing so, exit the
   176         -    ** global pcache mutex and unlock the pager-cache object pCache. This is 
   177         -    ** so that if the attempt to allocate a new buffer causes the the 
   178         -    ** configured soft-heap-limit to be breached, it will be possible to
   179         -    ** reclaim memory from this pager-cache.
          213  +    if( p ){
          214  +      pcache1.pFree = pcache1.pFree->pNext;
          215  +      pcache1.nFreeSlot--;
          216  +      pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
          217  +      assert( pcache1.nFreeSlot>=0 );
          218  +      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
          219  +    }
          220  +    sqlite3_mutex_leave(pcache1.mutex);
          221  +  }
          222  +  if( p==0 ){
          223  +    /* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool.  Get
          224  +    ** it from sqlite3Malloc instead.
   180    225       */
   181         -    pcache1LeaveMutex();
   182    226       p = sqlite3Malloc(nByte);
   183         -    pcache1EnterMutex();
   184    227       if( p ){
   185    228         int sz = sqlite3MallocSize(p);
   186    229         sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
   187    230       }
   188    231       sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
   189    232     }
   190    233     return p;
   191    234   }
   192    235   
   193    236   /*
   194    237   ** Free an allocated buffer obtained from pcache1Alloc().
   195    238   */
   196    239   static void pcache1Free(void *p){
   197         -  assert( sqlite3_mutex_held(pcache1.mutex) );
   198    240     if( p==0 ) return;
   199    241     if( p>=pcache1.pStart && p<pcache1.pEnd ){
   200    242       PgFreeslot *pSlot;
          243  +    sqlite3_mutex_enter(pcache1.mutex);
   201    244       sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
   202    245       pSlot = (PgFreeslot*)p;
   203    246       pSlot->pNext = pcache1.pFree;
   204    247       pcache1.pFree = pSlot;
   205    248       pcache1.nFreeSlot++;
          249  +    pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
   206    250       assert( pcache1.nFreeSlot<=pcache1.nSlot );
          251  +    sqlite3_mutex_leave(pcache1.mutex);
   207    252     }else{
   208    253       int iSize;
   209    254       assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
   210    255       sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
   211    256       iSize = sqlite3MallocSize(p);
   212    257       sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
   213    258       sqlite3_free(p);
................................................................................
   215    260   }
   216    261   
   217    262   #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
   218    263   /*
   219    264   ** Return the size of a pcache allocation
   220    265   */
   221    266   static int pcache1MemSize(void *p){
   222         -  assert( sqlite3_mutex_held(pcache1.mutex) );
   223    267     if( p>=pcache1.pStart && p<pcache1.pEnd ){
   224    268       return pcache1.szSlot;
   225    269     }else{
   226    270       int iSize;
   227    271       assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
   228    272       sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
   229    273       iSize = sqlite3MallocSize(p);
................................................................................
   239    283   static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
   240    284     int nByte = sizeof(PgHdr1) + pCache->szPage;
   241    285     void *pPg = pcache1Alloc(nByte);
   242    286     PgHdr1 *p;
   243    287     if( pPg ){
   244    288       p = PAGE_TO_PGHDR1(pCache, pPg);
   245    289       if( pCache->bPurgeable ){
   246         -      pcache1.nCurrentPage++;
          290  +      pCache->pGroup->nCurrentPage++;
   247    291       }
   248    292     }else{
   249    293       p = 0;
   250    294     }
   251    295     return p;
   252    296   }
   253    297   
................................................................................
   256    300   **
   257    301   ** The pointer is allowed to be NULL, which is prudent.  But it turns out
   258    302   ** that the current implementation happens to never call this routine
   259    303   ** with a NULL pointer, so we mark the NULL test with ALWAYS().
   260    304   */
   261    305   static void pcache1FreePage(PgHdr1 *p){
   262    306     if( ALWAYS(p) ){
   263         -    if( p->pCache->bPurgeable ){
   264         -      pcache1.nCurrentPage--;
          307  +    PCache1 *pCache = p->pCache;
          308  +    if( pCache->bPurgeable ){
          309  +      pCache->pGroup->nCurrentPage--;
   265    310       }
   266    311       pcache1Free(PGHDR1_TO_PAGE(p));
   267    312     }
   268    313   }
   269    314   
   270    315   /*
   271    316   ** Malloc function used by SQLite to obtain space from the buffer configured
   272    317   ** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
   273    318   ** exists, this function falls back to sqlite3Malloc().
   274    319   */
   275    320   void *sqlite3PageMalloc(int sz){
   276         -  void *p;
   277         -  pcache1EnterMutex();
   278         -  p = pcache1Alloc(sz);
   279         -  pcache1LeaveMutex();
   280         -  return p;
          321  +  return pcache1Alloc(sz);
   281    322   }
   282    323   
   283    324   /*
   284    325   ** Free an allocated buffer obtained from sqlite3PageMalloc().
   285    326   */
   286    327   void sqlite3PageFree(void *p){
   287         -  pcache1EnterMutex();
   288    328     pcache1Free(p);
   289         -  pcache1LeaveMutex();
   290    329   }
   291    330   
   292    331   
   293    332   /*
   294    333   ** Return true if it desirable to avoid allocating a new page cache
   295    334   ** entry.
   296    335   **
................................................................................
   303    342   **
   304    343   ** Or, the heap is used for all page cache memory put the heap is
   305    344   ** under memory pressure, then again it is desirable to avoid
   306    345   ** allocating a new page cache entry in order to avoid stressing
   307    346   ** the heap even further.
   308    347   */
   309    348   static int pcache1UnderMemoryPressure(PCache1 *pCache){
   310         -  assert( sqlite3_mutex_held(pcache1.mutex) );
   311    349     if( pcache1.nSlot && pCache->szPage<=pcache1.szSlot ){
   312         -    return pcache1.nFreeSlot<pcache1.nReserve;
          350  +    return pcache1.bUnderPressure;
   313    351     }else{
   314    352       return sqlite3HeapNearlyFull();
   315    353     }
   316    354   }
   317    355   
   318    356   /******************************************************************************/
   319    357   /******** General Implementation Functions ************************************/
   320    358   
   321    359   /*
   322    360   ** This function is used to resize the hash table used by the cache passed
   323    361   ** as the first argument.
   324    362   **
   325         -** The global mutex must be held when this function is called.
          363  +** The PCache mutex must be held when this function is called.
   326    364   */
   327    365   static int pcache1ResizeHash(PCache1 *p){
   328    366     PgHdr1 **apNew;
   329    367     unsigned int nNew;
   330    368     unsigned int i;
   331    369   
   332         -  assert( sqlite3_mutex_held(pcache1.mutex) );
          370  +  assert( sqlite3_mutex_held(p->pGroup->mutex) );
   333    371   
   334    372     nNew = p->nHash*2;
   335    373     if( nNew<256 ){
   336    374       nNew = 256;
   337    375     }
   338    376   
   339         -  pcache1LeaveMutex();
          377  +  pcache1LeaveMutex(p->pGroup);
   340    378     if( p->nHash ){ sqlite3BeginBenignMalloc(); }
   341    379     apNew = (PgHdr1 **)sqlite3_malloc(sizeof(PgHdr1 *)*nNew);
   342    380     if( p->nHash ){ sqlite3EndBenignMalloc(); }
   343         -  pcache1EnterMutex();
          381  +  pcache1EnterMutex(p->pGroup);
   344    382     if( apNew ){
   345    383       memset(apNew, 0, sizeof(PgHdr1 *)*nNew);
   346    384       for(i=0; i<p->nHash; i++){
   347    385         PgHdr1 *pPage;
   348    386         PgHdr1 *pNext = p->apHash[i];
   349    387         while( (pPage = pNext)!=0 ){
   350    388           unsigned int h = pPage->iKey % nNew;
................................................................................
   359    397     }
   360    398   
   361    399     return (p->apHash ? SQLITE_OK : SQLITE_NOMEM);
   362    400   }
   363    401   
   364    402   /*
   365    403   ** This function is used internally to remove the page pPage from the 
   366         -** global LRU list, if is part of it. If pPage is not part of the global
          404  +** PGroup LRU list, if is part of it. If pPage is not part of the PGroup
   367    405   ** LRU list, then this function is a no-op.
   368    406   **
   369         -** The global mutex must be held when this function is called.
          407  +** The PGroup mutex must be held when this function is called.
          408  +**
          409  +** If pPage is NULL then this routine is a no-op.
   370    410   */
   371    411   static void pcache1PinPage(PgHdr1 *pPage){
   372         -  assert( sqlite3_mutex_held(pcache1.mutex) );
   373         -  if( pPage && (pPage->pLruNext || pPage==pcache1.pLruTail) ){
          412  +  PCache1 *pCache;
          413  +  PGroup *pGroup;
          414  +
          415  +  if( pPage==0 ) return;
          416  +  pCache = pPage->pCache;
          417  +  pGroup = pCache->pGroup;
          418  +  assert( sqlite3_mutex_held(pGroup->mutex) );
          419  +  if( pPage->pLruNext || pPage==pGroup->pLruTail ){
   374    420       if( pPage->pLruPrev ){
   375    421         pPage->pLruPrev->pLruNext = pPage->pLruNext;
   376    422       }
   377    423       if( pPage->pLruNext ){
   378    424         pPage->pLruNext->pLruPrev = pPage->pLruPrev;
   379    425       }
   380         -    if( pcache1.pLruHead==pPage ){
   381         -      pcache1.pLruHead = pPage->pLruNext;
          426  +    if( pGroup->pLruHead==pPage ){
          427  +      pGroup->pLruHead = pPage->pLruNext;
   382    428       }
   383         -    if( pcache1.pLruTail==pPage ){
   384         -      pcache1.pLruTail = pPage->pLruPrev;
          429  +    if( pGroup->pLruTail==pPage ){
          430  +      pGroup->pLruTail = pPage->pLruPrev;
   385    431       }
   386    432       pPage->pLruNext = 0;
   387    433       pPage->pLruPrev = 0;
   388    434       pPage->pCache->nRecyclable--;
   389    435     }
   390    436   }
   391    437   
   392    438   
   393    439   /*
   394    440   ** Remove the page supplied as an argument from the hash table 
   395    441   ** (PCache1.apHash structure) that it is currently stored in.
   396    442   **
   397         -** The global mutex must be held when this function is called.
          443  +** The PGroup mutex must be held when this function is called.
   398    444   */
   399    445   static void pcache1RemoveFromHash(PgHdr1 *pPage){
   400    446     unsigned int h;
   401    447     PCache1 *pCache = pPage->pCache;
   402    448     PgHdr1 **pp;
   403    449   
          450  +  assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
   404    451     h = pPage->iKey % pCache->nHash;
   405    452     for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext);
   406    453     *pp = (*pp)->pNext;
   407    454   
   408    455     pCache->nPage--;
   409    456   }
   410    457   
   411    458   /*
   412         -** If there are currently more than pcache.nMaxPage pages allocated, try
   413         -** to recycle pages to reduce the number allocated to pcache.nMaxPage.
          459  +** If there are currently more than nMaxPage pages allocated, try
          460  +** to recycle pages to reduce the number allocated to nMaxPage.
   414    461   */
   415         -static void pcache1EnforceMaxPage(void){
   416         -  assert( sqlite3_mutex_held(pcache1.mutex) );
   417         -  while( pcache1.nCurrentPage>pcache1.nMaxPage && pcache1.pLruTail ){
   418         -    PgHdr1 *p = pcache1.pLruTail;
          462  +static void pcache1EnforceMaxPage(PGroup *pGroup){
          463  +  assert( sqlite3_mutex_held(pGroup->mutex) );
          464  +  while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
          465  +    PgHdr1 *p = pGroup->pLruTail;
          466  +    assert( p->pCache->pGroup==pGroup );
   419    467       pcache1PinPage(p);
   420    468       pcache1RemoveFromHash(p);
   421    469       pcache1FreePage(p);
   422    470     }
   423    471   }
   424    472   
   425    473   /*
   426    474   ** Discard all pages from cache pCache with a page number (key value) 
   427    475   ** greater than or equal to iLimit. Any pinned pages that meet this 
   428    476   ** criteria are unpinned before they are discarded.
   429    477   **
   430         -** The global mutex must be held when this function is called.
          478  +** The PCache mutex must be held when this function is called.
   431    479   */
   432    480   static void pcache1TruncateUnsafe(
   433         -  PCache1 *pCache, 
   434         -  unsigned int iLimit 
          481  +  PCache1 *pCache,             /* The cache to truncate */
          482  +  unsigned int iLimit          /* Drop pages with this pgno or larger */
   435    483   ){
   436         -  TESTONLY( unsigned int nPage = 0; )      /* Used to assert pCache->nPage is correct */
          484  +  TESTONLY( unsigned int nPage = 0; )  /* To assert pCache->nPage is correct */
   437    485     unsigned int h;
   438         -  assert( sqlite3_mutex_held(pcache1.mutex) );
          486  +  assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
   439    487     for(h=0; h<pCache->nHash; h++){
   440    488       PgHdr1 **pp = &pCache->apHash[h]; 
   441    489       PgHdr1 *pPage;
   442    490       while( (pPage = *pp)!=0 ){
   443    491         if( pPage->iKey>=iLimit ){
   444    492           pCache->nPage--;
   445    493           *pp = pPage->pNext;
................................................................................
   461    509   ** Implementation of the sqlite3_pcache.xInit method.
   462    510   */
   463    511   static int pcache1Init(void *NotUsed){
   464    512     UNUSED_PARAMETER(NotUsed);
   465    513     assert( pcache1.isInit==0 );
   466    514     memset(&pcache1, 0, sizeof(pcache1));
   467    515     if( sqlite3GlobalConfig.bCoreMutex ){
   468         -    pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
          516  +    pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
          517  +    pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
   469    518     }
   470    519     pcache1.isInit = 1;
   471    520     return SQLITE_OK;
   472    521   }
   473    522   
   474    523   /*
   475    524   ** Implementation of the sqlite3_pcache.xShutdown method.
................................................................................
   484    533   
   485    534   /*
   486    535   ** Implementation of the sqlite3_pcache.xCreate method.
   487    536   **
   488    537   ** Allocate a new cache.
   489    538   */
   490    539   static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){
   491         -  PCache1 *pCache;
          540  +  PCache1 *pCache;      /* The newly created page cache */
          541  +  PGroup *pGroup;       /* The group the new page cache will belong to */
          542  +  int sz;               /* Bytes of memory required to allocate the new cache */
   492    543   
   493         -  pCache = (PCache1 *)sqlite3_malloc(sizeof(PCache1));
          544  +  /*
          545  +  ** The seperateCache variable is true if each PCache has its own private
          546  +  ** PGroup.  In other words, separateCache is true for mode (1) where no
          547  +  ** mutexing is required.
          548  +  **
          549  +  **   *  Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT
          550  +  **
          551  +  **   *  Always use a unified cache in single-threaded applications
          552  +  **
          553  +  **   *  Otherwise (if multi-threaded and ENABLE_MEMORY_MANAGEMENT is off)
          554  +  **      use separate caches (mode-1)
          555  +  */
          556  +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0
          557  +  const int separateCache = 0;
          558  +#else
          559  +  int separateCache = sqlite3GlobalConfig.bCoreMutex>0;
          560  +#endif
          561  +
          562  +  sz = sizeof(PCache1) + sizeof(PGroup)*separateCache;
          563  +  pCache = (PCache1 *)sqlite3_malloc(sz);
   494    564     if( pCache ){
   495         -    memset(pCache, 0, sizeof(PCache1));
          565  +    memset(pCache, 0, sz);
          566  +    if( separateCache ){
          567  +      pGroup = (PGroup*)&pCache[1];
          568  +    }else{
          569  +      pGroup = &pcache1_g.grp;
          570  +    }
          571  +    pCache->pGroup = pGroup;
   496    572       pCache->szPage = szPage;
   497    573       pCache->bPurgeable = (bPurgeable ? 1 : 0);
   498    574       if( bPurgeable ){
   499    575         pCache->nMin = 10;
   500         -      pcache1EnterMutex();
   501         -      pcache1.nMinPage += pCache->nMin;
   502         -      pcache1LeaveMutex();
          576  +      pcache1EnterMutex(pGroup);
          577  +      pGroup->nMinPage += pCache->nMin;
          578  +      pcache1LeaveMutex(pGroup);
   503    579       }
   504    580     }
   505    581     return (sqlite3_pcache *)pCache;
   506    582   }
   507    583   
   508    584   /*
   509    585   ** Implementation of the sqlite3_pcache.xCachesize method. 
   510    586   **
   511    587   ** Configure the cache_size limit for a cache.
   512    588   */
   513    589   static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
   514    590     PCache1 *pCache = (PCache1 *)p;
   515    591     if( pCache->bPurgeable ){
   516         -    pcache1EnterMutex();
   517         -    pcache1.nMaxPage += (nMax - pCache->nMax);
          592  +    PGroup *pGroup = pCache->pGroup;
          593  +    pcache1EnterMutex(pGroup);
          594  +    pGroup->nMaxPage += (nMax - pCache->nMax);
   518    595       pCache->nMax = nMax;
   519         -    pcache1EnforceMaxPage();
   520         -    pcache1LeaveMutex();
          596  +    pcache1EnforceMaxPage(pGroup);
          597  +    pcache1LeaveMutex(pGroup);
   521    598     }
   522    599   }
   523    600   
   524    601   /*
   525    602   ** Implementation of the sqlite3_pcache.xPagecount method. 
   526    603   */
   527    604   static int pcache1Pagecount(sqlite3_pcache *p){
   528    605     int n;
   529         -  pcache1EnterMutex();
   530         -  n = ((PCache1 *)p)->nPage;
   531         -  pcache1LeaveMutex();
          606  +  PCache1 *pCache = (PCache1*)p;
          607  +  pcache1EnterMutex(pCache->pGroup);
          608  +  n = pCache->nPage;
          609  +  pcache1LeaveMutex(pCache->pGroup);
   532    610     return n;
   533    611   }
   534    612   
   535    613   /*
   536    614   ** Implementation of the sqlite3_pcache.xFetch method. 
   537    615   **
   538    616   ** Fetch a page by key value.
................................................................................
   585    663   **      proceed to step 5. 
   586    664   **
   587    665   **   5. Otherwise, allocate and return a new page buffer.
   588    666   */
   589    667   static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
   590    668     unsigned int nPinned;
   591    669     PCache1 *pCache = (PCache1 *)p;
          670  +  PGroup *pGroup = pCache->pGroup;
   592    671     PgHdr1 *pPage = 0;
   593    672   
   594    673     assert( pCache->bPurgeable || createFlag!=1 );
   595         -  pcache1EnterMutex();
          674  +  pcache1EnterMutex(pGroup);
   596    675     if( createFlag==1 ) sqlite3BeginBenignMalloc();
   597    676   
   598    677     /* Search the hash table for an existing entry. */
   599    678     if( pCache->nHash>0 ){
   600    679       unsigned int h = iKey % pCache->nHash;
   601    680       for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext);
   602    681     }
................................................................................
   605    684       pcache1PinPage(pPage);
   606    685       goto fetch_out;
   607    686     }
   608    687   
   609    688     /* Step 3 of header comment. */
   610    689     nPinned = pCache->nPage - pCache->nRecyclable;
   611    690     if( createFlag==1 && (
   612         -        nPinned>=(pcache1.nMaxPage+pCache->nMin-pcache1.nMinPage)
          691  +        nPinned>=(pGroup->nMaxPage+pCache->nMin-pGroup->nMinPage)
   613    692        || nPinned>=(pCache->nMax * 9 / 10)
   614    693        || pcache1UnderMemoryPressure(pCache)
   615    694     )){
   616    695       goto fetch_out;
   617    696     }
   618    697   
   619    698     if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
   620    699       goto fetch_out;
   621    700     }
   622    701   
   623    702     /* Step 4. Try to recycle a page buffer if appropriate. */
   624         -  if( pCache->bPurgeable && pcache1.pLruTail && (
          703  +  if( pCache->bPurgeable && pGroup->pLruTail && (
   625    704            (pCache->nPage+1>=pCache->nMax)
   626         -      || pcache1.nCurrentPage>=pcache1.nMaxPage
          705  +      || pGroup->nCurrentPage>=pGroup->nMaxPage
   627    706         || pcache1UnderMemoryPressure(pCache)
   628    707     )){
   629         -    pPage = pcache1.pLruTail;
          708  +    pPage = pGroup->pLruTail;
   630    709       pcache1RemoveFromHash(pPage);
   631    710       pcache1PinPage(pPage);
   632    711       if( pPage->pCache->szPage!=pCache->szPage ){
   633    712         pcache1FreePage(pPage);
   634    713         pPage = 0;
   635    714       }else{
   636         -      pcache1.nCurrentPage -= (pPage->pCache->bPurgeable - pCache->bPurgeable);
          715  +      pGroup->nCurrentPage -= 
          716  +               (pPage->pCache->bPurgeable - pCache->bPurgeable);
   637    717       }
   638    718     }
   639    719   
   640    720     /* Step 5. If a usable page buffer has still not been found, 
   641    721     ** attempt to allocate a new one. 
   642    722     */
   643    723     if( !pPage ){
          724  +    pcache1LeaveMutex(pGroup);
   644    725       pPage = pcache1AllocPage(pCache);
          726  +    pcache1EnterMutex(pGroup);
   645    727     }
   646    728   
   647    729     if( pPage ){
   648    730       unsigned int h = iKey % pCache->nHash;
   649    731       pCache->nPage++;
   650    732       pPage->iKey = iKey;
   651    733       pPage->pNext = pCache->apHash[h];
................................................................................
   657    739     }
   658    740   
   659    741   fetch_out:
   660    742     if( pPage && iKey>pCache->iMaxKey ){
   661    743       pCache->iMaxKey = iKey;
   662    744     }
   663    745     if( createFlag==1 ) sqlite3EndBenignMalloc();
   664         -  pcache1LeaveMutex();
          746  +  pcache1LeaveMutex(pGroup);
   665    747     return (pPage ? PGHDR1_TO_PAGE(pPage) : 0);
   666    748   }
   667    749   
   668    750   
   669    751   /*
   670    752   ** Implementation of the sqlite3_pcache.xUnpin method.
   671    753   **
   672    754   ** Mark a page as unpinned (eligible for asynchronous recycling).
   673    755   */
   674    756   static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){
   675    757     PCache1 *pCache = (PCache1 *)p;
   676    758     PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg);
          759  +  PGroup *pGroup = pCache->pGroup;
   677    760    
   678    761     assert( pPage->pCache==pCache );
   679         -  pcache1EnterMutex();
          762  +  pcache1EnterMutex(pGroup);
   680    763   
   681    764     /* It is an error to call this function if the page is already 
   682         -  ** part of the global LRU list.
          765  +  ** part of the PGroup LRU list.
   683    766     */
   684    767     assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
   685         -  assert( pcache1.pLruHead!=pPage && pcache1.pLruTail!=pPage );
          768  +  assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
   686    769   
   687         -  if( reuseUnlikely || pcache1.nCurrentPage>pcache1.nMaxPage ){
          770  +  if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
   688    771       pcache1RemoveFromHash(pPage);
   689    772       pcache1FreePage(pPage);
   690    773     }else{
   691         -    /* Add the page to the global LRU list. */
   692         -    if( pcache1.pLruHead ){
   693         -      pcache1.pLruHead->pLruPrev = pPage;
   694         -      pPage->pLruNext = pcache1.pLruHead;
   695         -      pcache1.pLruHead = pPage;
          774  +    /* Add the page to the PGroup LRU list. */
          775  +    if( pGroup->pLruHead ){
          776  +      pGroup->pLruHead->pLruPrev = pPage;
          777  +      pPage->pLruNext = pGroup->pLruHead;
          778  +      pGroup->pLruHead = pPage;
   696    779       }else{
   697         -      pcache1.pLruTail = pPage;
   698         -      pcache1.pLruHead = pPage;
          780  +      pGroup->pLruTail = pPage;
          781  +      pGroup->pLruHead = pPage;
   699    782       }
   700    783       pCache->nRecyclable++;
   701    784     }
   702    785   
   703         -  pcache1LeaveMutex();
          786  +  pcache1LeaveMutex(pCache->pGroup);
   704    787   }
   705    788   
   706    789   /*
   707    790   ** Implementation of the sqlite3_pcache.xRekey method. 
   708    791   */
   709    792   static void pcache1Rekey(
   710    793     sqlite3_pcache *p,
................................................................................
   715    798     PCache1 *pCache = (PCache1 *)p;
   716    799     PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg);
   717    800     PgHdr1 **pp;
   718    801     unsigned int h; 
   719    802     assert( pPage->iKey==iOld );
   720    803     assert( pPage->pCache==pCache );
   721    804   
   722         -  pcache1EnterMutex();
          805  +  pcache1EnterMutex(pCache->pGroup);
   723    806   
   724    807     h = iOld%pCache->nHash;
   725    808     pp = &pCache->apHash[h];
   726    809     while( (*pp)!=pPage ){
   727    810       pp = &(*pp)->pNext;
   728    811     }
   729    812     *pp = pPage->pNext;
................................................................................
   732    815     pPage->iKey = iNew;
   733    816     pPage->pNext = pCache->apHash[h];
   734    817     pCache->apHash[h] = pPage;
   735    818     if( iNew>pCache->iMaxKey ){
   736    819       pCache->iMaxKey = iNew;
   737    820     }
   738    821   
   739         -  pcache1LeaveMutex();
          822  +  pcache1LeaveMutex(pCache->pGroup);
   740    823   }
   741    824   
   742    825   /*
   743    826   ** Implementation of the sqlite3_pcache.xTruncate method. 
   744    827   **
   745    828   ** Discard all unpinned pages in the cache with a page number equal to
   746    829   ** or greater than parameter iLimit. Any pinned pages with a page number
   747    830   ** equal to or greater than iLimit are implicitly unpinned.
   748    831   */
   749    832   static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
   750    833     PCache1 *pCache = (PCache1 *)p;
   751         -  pcache1EnterMutex();
          834  +  pcache1EnterMutex(pCache->pGroup);
   752    835     if( iLimit<=pCache->iMaxKey ){
   753    836       pcache1TruncateUnsafe(pCache, iLimit);
   754    837       pCache->iMaxKey = iLimit-1;
   755    838     }
   756         -  pcache1LeaveMutex();
          839  +  pcache1LeaveMutex(pCache->pGroup);
   757    840   }
   758    841   
   759    842   /*
   760    843   ** Implementation of the sqlite3_pcache.xDestroy method. 
   761    844   **
   762    845   ** Destroy a cache allocated using pcache1Create().
   763    846   */
   764    847   static void pcache1Destroy(sqlite3_pcache *p){
   765    848     PCache1 *pCache = (PCache1 *)p;
          849  +  PGroup *pGroup = pCache->pGroup;
   766    850     assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) );
   767         -  pcache1EnterMutex();
          851  +  pcache1EnterMutex(pGroup);
   768    852     pcache1TruncateUnsafe(pCache, 0);
   769         -  pcache1.nMaxPage -= pCache->nMax;
   770         -  pcache1.nMinPage -= pCache->nMin;
   771         -  pcache1EnforceMaxPage();
   772         -  pcache1LeaveMutex();
          853  +  pGroup->nMaxPage -= pCache->nMax;
          854  +  pGroup->nMinPage -= pCache->nMin;
          855  +  pcache1EnforceMaxPage(pGroup);
          856  +  pcache1LeaveMutex(pGroup);
   773    857     sqlite3_free(pCache->apHash);
   774    858     sqlite3_free(pCache);
   775    859   }
   776    860   
   777    861   /*
   778    862   ** This function is called during initialization (sqlite3_initialize()) to
   779    863   ** install the default pluggable cache module, assuming the user has not
................................................................................
   804    888   **
   805    889   ** nReq is the number of bytes of memory required. Once this much has
   806    890   ** been released, the function returns. The return value is the total number 
   807    891   ** of bytes of memory released.
   808    892   */
   809    893   int sqlite3PcacheReleaseMemory(int nReq){
   810    894     int nFree = 0;
          895  +  assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
          896  +  assert( sqlite3_mutex_notheld(pcache1.mutex) );
   811    897     if( pcache1.pStart==0 ){
   812    898       PgHdr1 *p;
   813         -    pcache1EnterMutex();
   814         -    while( (nReq<0 || nFree<nReq) && ((p=pcache1.pLruTail)!=0) ){
          899  +    pcache1EnterMutex(&pcache1.grp);
          900  +    while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
   815    901         nFree += pcache1MemSize(PGHDR1_TO_PAGE(p));
   816    902         pcache1PinPage(p);
   817    903         pcache1RemoveFromHash(p);
   818    904         pcache1FreePage(p);
   819    905       }
   820         -    pcache1LeaveMutex();
          906  +    pcache1LeaveMutex(&pcache1.grp);
   821    907     }
   822    908     return nFree;
   823    909   }
   824    910   #endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
   825    911   
   826    912   #ifdef SQLITE_TEST
   827    913   /*
................................................................................
   832    918     int *pnCurrent,      /* OUT: Total number of pages cached */
   833    919     int *pnMax,          /* OUT: Global maximum cache size */
   834    920     int *pnMin,          /* OUT: Sum of PCache1.nMin for purgeable caches */
   835    921     int *pnRecyclable    /* OUT: Total number of pages available for recycling */
   836    922   ){
   837    923     PgHdr1 *p;
   838    924     int nRecyclable = 0;
   839         -  for(p=pcache1.pLruHead; p; p=p->pLruNext){
          925  +  for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
   840    926       nRecyclable++;
   841    927     }
   842         -  *pnCurrent = pcache1.nCurrentPage;
   843         -  *pnMax = pcache1.nMaxPage;
   844         -  *pnMin = pcache1.nMinPage;
          928  +  *pnCurrent = pcache1.grp.nCurrentPage;
          929  +  *pnMax = pcache1.grp.nMaxPage;
          930  +  *pnMin = pcache1.grp.nMinPage;
   845    931     *pnRecyclable = nRecyclable;
   846    932   }
   847    933   #endif