Index: src/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -399,12 +399,12 @@ int nHash; /* Size of the pager hash table */ PgHdr **aHash; /* Hash table to map page number to PgHdr */ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT Pager *pNext; /* Doubly linked list of pagers on which */ Pager *pPrev; /* sqlite3_release_memory() will work */ - int iInUseMM; /* Non-zero if unavailable to MM */ - int iInUseDB; /* Non-zero if in sqlite3_release_memory() */ + volatile int iInUseMM; /* Non-zero if unavailable to MM */ + volatile int iInUseDB; /* Non-zero if in sqlite3_release_memory() */ u8 onPagerList; /* True if part of the sqlite3PagerList */ #endif char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ char dbFileVers[16]; /* Changes whenever database file changes */ }; @@ -525,14 +525,14 @@ sqlite3_mutex *mutex; mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); #endif p->iInUseDB = 0; sqlite3_mutex_enter(mutex); + assert( p->iInUseMM==0 ); p->iInUseDB = 1; sqlite3_mutex_leave(mutex); } - assert( p->iInUseMM==0 ); } static void pagerLeave(Pager *p){ p->iInUseDB--; assert( p->iInUseDB>=0 ); } @@ -704,10 +704,11 @@ return; } sqlite3_free(pPager->aHash); pPager->nHash = N; pPager->aHash = aHash; + pagerMutexHeld(pPager); for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ int h; if( pPg->pgno==0 ){ assert( pPg->pNextHash==0 && pPg->pPrevHash==0 ); continue; @@ -1422,10 +1423,11 @@ rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); } } sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; + pagerMutexHeld(pPager); for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ pPg->inJournal = 0; pPg->dirty = 0; pPg->needSync = 0; pPg->alwaysRollback = 0; @@ -2939,10 +2941,11 @@ /* If the Pager.needSync flag is clear then the PgHdr.needSync ** flag must also be clear for all pages. Verify that this ** invariant is true. */ else{ + pagerMutexHeld(pPager); for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ assert( pPg->needSync==0 ); } assert( pPager->lru.pFirstSynced==pPager->lru.pFirst ); } @@ -3177,11 +3180,11 @@ PgHdr *pPg; *ppPg = 0; /* It is illegal to call this function unless the pager object ** pointed to by pPager has at least one free page (page with nRef==0). - */ + */ assert(!MEMDB); assert(pPager->lru.pFirst); /* Find a page to recycle. Try to locate a page that does not ** require us to do an fsync() on the journal. @@ -3626,13 +3629,16 @@ */ static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){ int rc = SQLITE_OK; PgHdr *pPg; int nByteHdr; + /* Create a new PgHdr if any of the four conditions defined - ** above are met: */ + ** above are met: + */ + pagerMutexHeld(pPager); if( pPager->nPagemxPage || pPager->lru.pFirst==0 || MEMDB || (pPager->lru.pFirstSynced==0 && pPager->doNotSync) ){ @@ -3662,15 +3668,17 @@ goto pager_allocate_out; } memset(pPg, 0, nByteHdr); pPg->pData = pData; pPg->pPager = pPager; + pagerMutexHeld(pPager); pPg->pNextAll = pPager->pAll; pPager->pAll = pPg; pPager->nPage++; }else{ /* Recycle an existing page with a zero ref-count. */ + pagerMutexHeld(pPager); rc = pager_recycle(pPager, &pPg); if( rc==SQLITE_BUSY ){ rc = SQLITE_IOERR_BLOCKED; } if( rc!=SQLITE_OK ){ @@ -4713,10 +4721,11 @@ } } #endif rc = writeMasterJournal(pPager, zMaster); if( rc!=SQLITE_OK ) goto sync_exit; + pagerMutexHeld(pPager); rc = syncJournal(pPager); } if( rc!=SQLITE_OK ) goto sync_exit; #ifndef SQLITE_OMIT_AUTOVACUUM @@ -4840,10 +4849,11 @@ int sqlite3PagerRollback(Pager *pPager){ int rc; PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager)); if( MEMDB ){ PgHdr *p; + pagerMutexHeld(pPager); for(p=pPager->pAll; p; p=p->pNextAll){ PgHistory *pHist; assert( !p->alwaysRollback ); if( !p->dirty ){ assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig );