| OLD | NEW |
| 1 /* | 1 /* |
| 2 ** 2007 August 27 | 2 ** 2007 August 27 |
| 3 ** | 3 ** |
| 4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
| 5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
| 6 ** | 6 ** |
| 7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
| 8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
| 9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
| 10 ** | 10 ** |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 | 31 |
| 32 sqlite3_mutex_enter(p->pBt->mutex); | 32 sqlite3_mutex_enter(p->pBt->mutex); |
| 33 p->pBt->db = p->db; | 33 p->pBt->db = p->db; |
| 34 p->locked = 1; | 34 p->locked = 1; |
| 35 } | 35 } |
| 36 | 36 |
| 37 /* | 37 /* |
| 38 ** Release the BtShared mutex associated with B-Tree handle p and | 38 ** Release the BtShared mutex associated with B-Tree handle p and |
| 39 ** clear the p->locked boolean. | 39 ** clear the p->locked boolean. |
| 40 */ | 40 */ |
| 41 static void unlockBtreeMutex(Btree *p){ | 41 static void SQLITE_NOINLINE unlockBtreeMutex(Btree *p){ |
| 42 BtShared *pBt = p->pBt; | 42 BtShared *pBt = p->pBt; |
| 43 assert( p->locked==1 ); | 43 assert( p->locked==1 ); |
| 44 assert( sqlite3_mutex_held(pBt->mutex) ); | 44 assert( sqlite3_mutex_held(pBt->mutex) ); |
| 45 assert( sqlite3_mutex_held(p->db->mutex) ); | 45 assert( sqlite3_mutex_held(p->db->mutex) ); |
| 46 assert( p->db==pBt->db ); | 46 assert( p->db==pBt->db ); |
| 47 | 47 |
| 48 sqlite3_mutex_leave(pBt->mutex); | 48 sqlite3_mutex_leave(pBt->mutex); |
| 49 p->locked = 0; | 49 p->locked = 0; |
| 50 } | 50 } |
| 51 | 51 |
| 52 /* Forward reference */ |
| 53 static void SQLITE_NOINLINE btreeLockCarefully(Btree *p); |
| 54 |
| 52 /* | 55 /* |
| 53 ** Enter a mutex on the given BTree object. | 56 ** Enter a mutex on the given BTree object. |
| 54 ** | 57 ** |
| 55 ** If the object is not sharable, then no mutex is ever required | 58 ** If the object is not sharable, then no mutex is ever required |
| 56 ** and this routine is a no-op. The underlying mutex is non-recursive. | 59 ** and this routine is a no-op. The underlying mutex is non-recursive. |
| 57 ** But we keep a reference count in Btree.wantToLock so the behavior | 60 ** But we keep a reference count in Btree.wantToLock so the behavior |
| 58 ** of this interface is recursive. | 61 ** of this interface is recursive. |
| 59 ** | 62 ** |
| 60 ** To avoid deadlocks, multiple Btrees are locked in the same order | 63 ** To avoid deadlocks, multiple Btrees are locked in the same order |
| 61 ** by all database connections. The p->pNext is a list of other | 64 ** by all database connections. The p->pNext is a list of other |
| 62 ** Btrees belonging to the same database connection as the p Btree | 65 ** Btrees belonging to the same database connection as the p Btree |
| 63 ** which need to be locked after p. If we cannot get a lock on | 66 ** which need to be locked after p. If we cannot get a lock on |
| 64 ** p, then first unlock all of the others on p->pNext, then wait | 67 ** p, then first unlock all of the others on p->pNext, then wait |
| 65 ** for the lock to become available on p, then relock all of the | 68 ** for the lock to become available on p, then relock all of the |
| 66 ** subsequent Btrees that desire a lock. | 69 ** subsequent Btrees that desire a lock. |
| 67 */ | 70 */ |
| 68 void sqlite3BtreeEnter(Btree *p){ | 71 void sqlite3BtreeEnter(Btree *p){ |
| 69 Btree *pLater; | |
| 70 | |
| 71 /* Some basic sanity checking on the Btree. The list of Btrees | 72 /* Some basic sanity checking on the Btree. The list of Btrees |
| 72 ** connected by pNext and pPrev should be in sorted order by | 73 ** connected by pNext and pPrev should be in sorted order by |
| 73 ** Btree.pBt value. All elements of the list should belong to | 74 ** Btree.pBt value. All elements of the list should belong to |
| 74 ** the same connection. Only shared Btrees are on the list. */ | 75 ** the same connection. Only shared Btrees are on the list. */ |
| 75 assert( p->pNext==0 || p->pNext->pBt>p->pBt ); | 76 assert( p->pNext==0 || p->pNext->pBt>p->pBt ); |
| 76 assert( p->pPrev==0 || p->pPrev->pBt<p->pBt ); | 77 assert( p->pPrev==0 || p->pPrev->pBt<p->pBt ); |
| 77 assert( p->pNext==0 || p->pNext->db==p->db ); | 78 assert( p->pNext==0 || p->pNext->db==p->db ); |
| 78 assert( p->pPrev==0 || p->pPrev->db==p->db ); | 79 assert( p->pPrev==0 || p->pPrev->db==p->db ); |
| 79 assert( p->sharable || (p->pNext==0 && p->pPrev==0) ); | 80 assert( p->sharable || (p->pNext==0 && p->pPrev==0) ); |
| 80 | 81 |
| 81 /* Check for locking consistency */ | 82 /* Check for locking consistency */ |
| 82 assert( !p->locked || p->wantToLock>0 ); | 83 assert( !p->locked || p->wantToLock>0 ); |
| 83 assert( p->sharable || p->wantToLock==0 ); | 84 assert( p->sharable || p->wantToLock==0 ); |
| 84 | 85 |
| 85 /* We should already hold a lock on the database connection */ | 86 /* We should already hold a lock on the database connection */ |
| 86 assert( sqlite3_mutex_held(p->db->mutex) ); | 87 assert( sqlite3_mutex_held(p->db->mutex) ); |
| 87 | 88 |
| 88 /* Unless the database is sharable and unlocked, then BtShared.db | 89 /* Unless the database is sharable and unlocked, then BtShared.db |
| 89 ** should already be set correctly. */ | 90 ** should already be set correctly. */ |
| 90 assert( (p->locked==0 && p->sharable) || p->pBt->db==p->db ); | 91 assert( (p->locked==0 && p->sharable) || p->pBt->db==p->db ); |
| 91 | 92 |
| 92 if( !p->sharable ) return; | 93 if( !p->sharable ) return; |
| 93 p->wantToLock++; | 94 p->wantToLock++; |
| 94 if( p->locked ) return; | 95 if( p->locked ) return; |
| 96 btreeLockCarefully(p); |
| 97 } |
| 98 |
| 99 /* This is a helper function for sqlite3BtreeLock(). By moving |
| 100 ** complex, but seldom used logic, out of sqlite3BtreeLock() and |
| 101 ** into this routine, we avoid unnecessary stack pointer changes |
| 102 ** and thus help the sqlite3BtreeLock() routine to run much faster |
| 103 ** in the common case. |
| 104 */ |
| 105 static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){ |
| 106 Btree *pLater; |
| 95 | 107 |
| 96 /* In most cases, we should be able to acquire the lock we | 108 /* In most cases, we should be able to acquire the lock we |
| 97 ** want without having to go throught the ascending lock | 109 ** want without having to go through the ascending lock |
| 98 ** procedure that follows. Just be sure not to block. | 110 ** procedure that follows. Just be sure not to block. |
| 99 */ | 111 */ |
| 100 if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){ | 112 if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){ |
| 101 p->pBt->db = p->db; | 113 p->pBt->db = p->db; |
| 102 p->locked = 1; | 114 p->locked = 1; |
| 103 return; | 115 return; |
| 104 } | 116 } |
| 105 | 117 |
| 106 /* To avoid deadlock, first release all locks with a larger | 118 /* To avoid deadlock, first release all locks with a larger |
| 107 ** BtShared address. Then acquire our lock. Then reacquire | 119 ** BtShared address. Then acquire our lock. Then reacquire |
| 108 ** the other BtShared locks that we used to hold in ascending | 120 ** the other BtShared locks that we used to hold in ascending |
| 109 ** order. | 121 ** order. |
| 110 */ | 122 */ |
| 111 for(pLater=p->pNext; pLater; pLater=pLater->pNext){ | 123 for(pLater=p->pNext; pLater; pLater=pLater->pNext){ |
| 112 assert( pLater->sharable ); | 124 assert( pLater->sharable ); |
| 113 assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt ); | 125 assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt ); |
| 114 assert( !pLater->locked || pLater->wantToLock>0 ); | 126 assert( !pLater->locked || pLater->wantToLock>0 ); |
| 115 if( pLater->locked ){ | 127 if( pLater->locked ){ |
| 116 unlockBtreeMutex(pLater); | 128 unlockBtreeMutex(pLater); |
| 117 } | 129 } |
| 118 } | 130 } |
| 119 lockBtreeMutex(p); | 131 lockBtreeMutex(p); |
| 120 for(pLater=p->pNext; pLater; pLater=pLater->pNext){ | 132 for(pLater=p->pNext; pLater; pLater=pLater->pNext){ |
| 121 if( pLater->wantToLock ){ | 133 if( pLater->wantToLock ){ |
| 122 lockBtreeMutex(pLater); | 134 lockBtreeMutex(pLater); |
| 123 } | 135 } |
| 124 } | 136 } |
| 125 } | 137 } |
| 126 | 138 |
| 139 |
| 127 /* | 140 /* |
| 128 ** Exit the recursive mutex on a Btree. | 141 ** Exit the recursive mutex on a Btree. |
| 129 */ | 142 */ |
| 130 void sqlite3BtreeLeave(Btree *p){ | 143 void sqlite3BtreeLeave(Btree *p){ |
| 131 if( p->sharable ){ | 144 if( p->sharable ){ |
| 132 assert( p->wantToLock>0 ); | 145 assert( p->wantToLock>0 ); |
| 133 p->wantToLock--; | 146 p->wantToLock--; |
| 134 if( p->wantToLock==0 ){ | 147 if( p->wantToLock==0 ){ |
| 135 unlockBtreeMutex(p); | 148 unlockBtreeMutex(p); |
| 136 } | 149 } |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 int i; | 291 int i; |
| 279 for(i=0; i<db->nDb; i++){ | 292 for(i=0; i<db->nDb; i++){ |
| 280 Btree *p = db->aDb[i].pBt; | 293 Btree *p = db->aDb[i].pBt; |
| 281 if( p ){ | 294 if( p ){ |
| 282 p->pBt->db = p->db; | 295 p->pBt->db = p->db; |
| 283 } | 296 } |
| 284 } | 297 } |
| 285 } | 298 } |
| 286 #endif /* if SQLITE_THREADSAFE */ | 299 #endif /* if SQLITE_THREADSAFE */ |
| 287 #endif /* ifndef SQLITE_OMIT_SHARED_CACHE */ | 300 #endif /* ifndef SQLITE_OMIT_SHARED_CACHE */ |
| OLD | NEW |