| Index: third_party/sqlite/src/src/btmutex.c
|
| diff --git a/third_party/sqlite/src/src/btmutex.c b/third_party/sqlite/src/src/btmutex.c
|
| index 9b5e0d7d89ed97de71d44406302c79180fd8bb3b..d87d4d5feeb6307aecdc9a83111489ab30c678c3 100644
|
| --- a/third_party/sqlite/src/src/btmutex.c
|
| +++ b/third_party/sqlite/src/src/btmutex.c
|
| @@ -10,8 +10,6 @@
|
| **
|
| *************************************************************************
|
| **
|
| -** $Id: btmutex.c,v 1.17 2009/07/20 12:33:33 drh Exp $
|
| -**
|
| ** This file contains code used to implement mutexes on Btree objects.
|
| ** This code really belongs in btree.c. But btree.c is getting too
|
| ** big and we want to break it down some. This packaged seemed like
|
| @@ -41,12 +39,13 @@ static void lockBtreeMutex(Btree *p){
|
| ** clear the p->locked boolean.
|
| */
|
| static void unlockBtreeMutex(Btree *p){
|
| + BtShared *pBt = p->pBt;
|
| assert( p->locked==1 );
|
| - assert( sqlite3_mutex_held(p->pBt->mutex) );
|
| + assert( sqlite3_mutex_held(pBt->mutex) );
|
| assert( sqlite3_mutex_held(p->db->mutex) );
|
| - assert( p->db==p->pBt->db );
|
| + assert( p->db==pBt->db );
|
|
|
| - sqlite3_mutex_leave(p->pBt->mutex);
|
| + sqlite3_mutex_leave(pBt->mutex);
|
| p->locked = 0;
|
| }
|
|
|
| @@ -187,30 +186,11 @@ void sqlite3BtreeLeaveCursor(BtCursor *pCur){
|
| */
|
| void sqlite3BtreeEnterAll(sqlite3 *db){
|
| int i;
|
| - Btree *p, *pLater;
|
| + Btree *p;
|
| assert( sqlite3_mutex_held(db->mutex) );
|
| for(i=0; i<db->nDb; i++){
|
| p = db->aDb[i].pBt;
|
| - assert( !p || (p->locked==0 && p->sharable) || p->pBt->db==p->db );
|
| - if( p && p->sharable ){
|
| - p->wantToLock++;
|
| - if( !p->locked ){
|
| - assert( p->wantToLock==1 );
|
| - while( p->pPrev ) p = p->pPrev;
|
| - /* Reason for ALWAYS: There must be at least on unlocked Btree in
|
| - ** the chain. Otherwise the !p->locked test above would have failed */
|
| - while( p->locked && ALWAYS(p->pNext) ) p = p->pNext;
|
| - for(pLater = p->pNext; pLater; pLater=pLater->pNext){
|
| - if( pLater->locked ){
|
| - unlockBtreeMutex(pLater);
|
| - }
|
| - }
|
| - while( p ){
|
| - lockBtreeMutex(p);
|
| - p = p->pNext;
|
| - }
|
| - }
|
| - }
|
| + if( p ) sqlite3BtreeEnter(p);
|
| }
|
| }
|
| void sqlite3BtreeLeaveAll(sqlite3 *db){
|
| @@ -219,16 +199,18 @@ void sqlite3BtreeLeaveAll(sqlite3 *db){
|
| assert( sqlite3_mutex_held(db->mutex) );
|
| for(i=0; i<db->nDb; i++){
|
| p = db->aDb[i].pBt;
|
| - if( p && p->sharable ){
|
| - assert( p->wantToLock>0 );
|
| - p->wantToLock--;
|
| - if( p->wantToLock==0 ){
|
| - unlockBtreeMutex(p);
|
| - }
|
| - }
|
| + if( p ) sqlite3BtreeLeave(p);
|
| }
|
| }
|
|
|
| +/*
|
| +** Return true if a particular Btree requires a lock. Return FALSE if
|
| +** no lock is ever required since it is not sharable.
|
| +*/
|
| +int sqlite3BtreeSharable(Btree *p){
|
| + return p->sharable;
|
| +}
|
| +
|
| #ifndef NDEBUG
|
| /*
|
| ** Return true if the current thread holds the database connection
|
| @@ -253,97 +235,42 @@ int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
|
| }
|
| #endif /* NDEBUG */
|
|
|
| +#ifndef NDEBUG
|
| /*
|
| -** Add a new Btree pointer to a BtreeMutexArray.
|
| -** if the pointer can possibly be shared with
|
| -** another database connection.
|
| +** Return true if the correct mutexes are held for accessing the
|
| +** db->aDb[iDb].pSchema structure. The mutexes required for schema
|
| +** access are:
|
| **
|
| -** The pointers are kept in sorted order by pBtree->pBt. That
|
| -** way when we go to enter all the mutexes, we can enter them
|
| -** in order without every having to backup and retry and without
|
| -** worrying about deadlock.
|
| +** (1) The mutex on db
|
| +** (2) if iDb!=1, then the mutex on db->aDb[iDb].pBt.
|
| **
|
| -** The number of shared btrees will always be small (usually 0 or 1)
|
| -** so an insertion sort is an adequate algorithm here.
|
| -*/
|
| -void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){
|
| - int i, j;
|
| - BtShared *pBt;
|
| - if( pBtree==0 || pBtree->sharable==0 ) return;
|
| -#ifndef NDEBUG
|
| - {
|
| - for(i=0; i<pArray->nMutex; i++){
|
| - assert( pArray->aBtree[i]!=pBtree );
|
| - }
|
| - }
|
| -#endif
|
| - assert( pArray->nMutex>=0 );
|
| - assert( pArray->nMutex<ArraySize(pArray->aBtree)-1 );
|
| - pBt = pBtree->pBt;
|
| - for(i=0; i<pArray->nMutex; i++){
|
| - assert( pArray->aBtree[i]!=pBtree );
|
| - if( pArray->aBtree[i]->pBt>pBt ){
|
| - for(j=pArray->nMutex; j>i; j--){
|
| - pArray->aBtree[j] = pArray->aBtree[j-1];
|
| - }
|
| - pArray->aBtree[i] = pBtree;
|
| - pArray->nMutex++;
|
| - return;
|
| - }
|
| - }
|
| - pArray->aBtree[pArray->nMutex++] = pBtree;
|
| -}
|
| -
|
| -/*
|
| -** Enter the mutex of every btree in the array. This routine is
|
| -** called at the beginning of sqlite3VdbeExec(). The mutexes are
|
| -** exited at the end of the same function.
|
| +** If pSchema is not NULL, then iDb is computed from pSchema and
|
| +** db using sqlite3SchemaToIndex().
|
| */
|
| -void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){
|
| - int i;
|
| - for(i=0; i<pArray->nMutex; i++){
|
| - Btree *p = pArray->aBtree[i];
|
| - /* Some basic sanity checking */
|
| - assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
|
| - assert( !p->locked || p->wantToLock>0 );
|
| -
|
| - /* We should already hold a lock on the database connection */
|
| - assert( sqlite3_mutex_held(p->db->mutex) );
|
| -
|
| - /* The Btree is sharable because only sharable Btrees are entered
|
| - ** into the array in the first place. */
|
| - assert( p->sharable );
|
| -
|
| - p->wantToLock++;
|
| - if( !p->locked ){
|
| - lockBtreeMutex(p);
|
| - }
|
| - }
|
| +int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){
|
| + Btree *p;
|
| + assert( db!=0 );
|
| + if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema);
|
| + assert( iDb>=0 && iDb<db->nDb );
|
| + if( !sqlite3_mutex_held(db->mutex) ) return 0;
|
| + if( iDb==1 ) return 1;
|
| + p = db->aDb[iDb].pBt;
|
| + assert( p!=0 );
|
| + return p->sharable==0 || p->locked==1;
|
| }
|
| +#endif /* NDEBUG */
|
|
|
| +#else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */
|
| /*
|
| -** Leave the mutex of every btree in the group.
|
| +** The following are special cases for mutex enter routines for use
|
| +** in single threaded applications that use shared cache. Except for
|
| +** these two routines, all mutex operations are no-ops in that case and
|
| +** are null #defines in btree.h.
|
| +**
|
| +** If shared cache is disabled, then all btree mutex routines, including
|
| +** the ones below, are no-ops and are null #defines in btree.h.
|
| */
|
| -void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){
|
| - int i;
|
| - for(i=0; i<pArray->nMutex; i++){
|
| - Btree *p = pArray->aBtree[i];
|
| - /* Some basic sanity checking */
|
| - assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
|
| - assert( p->locked );
|
| - assert( p->wantToLock>0 );
|
| -
|
| - /* We should already hold a lock on the database connection */
|
| - assert( sqlite3_mutex_held(p->db->mutex) );
|
| -
|
| - p->wantToLock--;
|
| - if( p->wantToLock==0 ){
|
| - unlockBtreeMutex(p);
|
| - }
|
| - }
|
| -}
|
|
|
| -#else
|
| void sqlite3BtreeEnter(Btree *p){
|
| p->pBt->db = p->db;
|
| }
|
|
|