1 /* 2 ** 2007 August 27 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ************************************************************************* 12 ** 13 ** This file contains code used to implement mutexes on Btree objects. 14 ** This code really belongs in btree.c. But btree.c is getting too 15 ** big and we want to break it down some. This packaged seemed like 16 ** a good breakout. 17 */ 18 #include "btreeInt.h" 19 #ifndef SQLITE_OMIT_SHARED_CACHE 20 #if SQLITE_THREADSAFE 21 22 /* 23 ** Obtain the BtShared mutex associated with B-Tree handle p. Also, 24 ** set BtShared.db to the database handle associated with p and the 25 ** p->locked boolean to true. 26 */ 27 static void lockBtreeMutex(Btree *p){ 28 assert( p->locked==0 ); 29 assert( sqlite3_mutex_notheld(p->pBt->mutex) ); 30 assert( sqlite3_mutex_held(p->db->mutex) ); 31 32 sqlite3_mutex_enter(p->pBt->mutex); 33 p->pBt->db = p->db; 34 p->locked = 1; 35 } 36 37 /* 38 ** Release the BtShared mutex associated with B-Tree handle p and 39 ** clear the p->locked boolean. 40 */ 41 static void unlockBtreeMutex(Btree *p){ 42 BtShared *pBt = p->pBt; 43 assert( p->locked==1 ); 44 assert( sqlite3_mutex_held(pBt->mutex) ); 45 assert( sqlite3_mutex_held(p->db->mutex) ); 46 assert( p->db==pBt->db ); 47 48 pBt->iMutexCounter++; 49 sqlite3_mutex_leave(pBt->mutex); 50 p->locked = 0; 51 } 52 53 #ifdef SQLITE_DEBUG 54 /* 55 ** Return the number of times that the mutex has been exited for 56 ** the given btree. 57 ** 58 ** This is a small circular counter that wraps around to zero on 59 ** overflow. It is used only for sanity checking - to verify that 60 ** mutexes are held continously by asserting that the value of 61 ** this counter at the beginning of a region is the same as at 62 ** the end. 63 */ 64 u32 sqlite3BtreeMutexCounter(Btree *p){ 65 assert( p->locked==1 || p->sharable==0 ); 66 return p->pBt->iMutexCounter; 67 } 68 #endif 69 70 /* 71 ** Enter a mutex on the given BTree object. 72 ** 73 ** If the object is not sharable, then no mutex is ever required 74 ** and this routine is a no-op. The underlying mutex is non-recursive. 75 ** But we keep a reference count in Btree.wantToLock so the behavior 76 ** of this interface is recursive. 77 ** 78 ** To avoid deadlocks, multiple Btrees are locked in the same order 79 ** by all database connections. The p->pNext is a list of other 80 ** Btrees belonging to the same database connection as the p Btree 81 ** which need to be locked after p. If we cannot get a lock on 82 ** p, then first unlock all of the others on p->pNext, then wait 83 ** for the lock to become available on p, then relock all of the 84 ** subsequent Btrees that desire a lock. 85 */ 86 void sqlite3BtreeEnter(Btree *p){ 87 Btree *pLater; 88 89 /* Some basic sanity checking on the Btree. The list of Btrees 90 ** connected by pNext and pPrev should be in sorted order by 91 ** Btree.pBt value. All elements of the list should belong to 92 ** the same connection. Only shared Btrees are on the list. */ 93 assert( p->pNext==0 || p->pNext->pBt>p->pBt ); 94 assert( p->pPrev==0 || p->pPrev->pBt<p->pBt ); 95 assert( p->pNext==0 || p->pNext->db==p->db ); 96 assert( p->pPrev==0 || p->pPrev->db==p->db ); 97 assert( p->sharable || (p->pNext==0 && p->pPrev==0) ); 98 99 /* Check for locking consistency */ 100 assert( !p->locked || p->wantToLock>0 ); 101 assert( p->sharable || p->wantToLock==0 ); 102 103 /* We should already hold a lock on the database connection */ 104 assert( sqlite3_mutex_held(p->db->mutex) ); 105 106 /* Unless the database is sharable and unlocked, then BtShared.db 107 ** should already be set correctly. */ 108 assert( (p->locked==0 && p->sharable) || p->pBt->db==p->db ); 109 110 if( !p->sharable ) return; 111 p->wantToLock++; 112 if( p->locked ) return; 113 114 /* Increment the mutex counter on all locked btrees in the same 115 ** database connection. This simulates the unlocking that would 116 ** occur on a worst-case mutex dead-lock avoidance scenario. 117 */ 118 #ifdef SQLITE_DEBUG 119 { 120 int ii; 121 sqlite3 *db = p->db; 122 Btree *pOther; 123 for(ii=0; ii<db->nDb; ii++){ 124 if( ii==1 ) continue; 125 pOther = db->aDb[ii].pBt; 126 if( pOther==0 || pOther->sharable==0 || pOther->locked==0 ) continue; 127 pOther->pBt->iMutexCounter++; 128 } 129 } 130 #endif 131 132 /* In most cases, we should be able to acquire the lock we 133 ** want without having to go throught the ascending lock 134 ** procedure that follows. Just be sure not to block. 135 */ 136 if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){ 137 p->pBt->db = p->db; 138 p->locked = 1; 139 return; 140 } 141 142 /* To avoid deadlock, first release all locks with a larger 143 ** BtShared address. Then acquire our lock. Then reacquire 144 ** the other BtShared locks that we used to hold in ascending 145 ** order. 146 */ 147 for(pLater=p->pNext; pLater; pLater=pLater->pNext){ 148 assert( pLater->sharable ); 149 assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt ); 150 assert( !pLater->locked || pLater->wantToLock>0 ); 151 if( pLater->locked ){ 152 unlockBtreeMutex(pLater); 153 } 154 } 155 lockBtreeMutex(p); 156 for(pLater=p->pNext; pLater; pLater=pLater->pNext){ 157 if( pLater->wantToLock ){ 158 lockBtreeMutex(pLater); 159 } 160 } 161 } 162 163 /* 164 ** Exit the recursive mutex on a Btree. 165 */ 166 void sqlite3BtreeLeave(Btree *p){ 167 if( p->sharable ){ 168 assert( p->wantToLock>0 ); 169 p->wantToLock--; 170 if( p->wantToLock==0 ){ 171 unlockBtreeMutex(p); 172 } 173 } 174 } 175 176 #ifndef NDEBUG 177 /* 178 ** Return true if the BtShared mutex is held on the btree, or if the 179 ** B-Tree is not marked as sharable. 180 ** 181 ** This routine is used only from within assert() statements. 182 */ 183 int sqlite3BtreeHoldsMutex(Btree *p){ 184 assert( p->sharable==0 || p->locked==0 || p->wantToLock>0 ); 185 assert( p->sharable==0 || p->locked==0 || p->db==p->pBt->db ); 186 assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->pBt->mutex) ); 187 assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->db->mutex) ); 188 189 return (p->sharable==0 || p->locked); 190 } 191 #endif 192 193 194 #ifndef SQLITE_OMIT_INCRBLOB 195 /* 196 ** Enter and leave a mutex on a Btree given a cursor owned by that 197 ** Btree. These entry points are used by incremental I/O and can be 198 ** omitted if that module is not used. 199 */ 200 void sqlite3BtreeEnterCursor(BtCursor *pCur){ 201 sqlite3BtreeEnter(pCur->pBtree); 202 } 203 void sqlite3BtreeLeaveCursor(BtCursor *pCur){ 204 sqlite3BtreeLeave(pCur->pBtree); 205 } 206 #endif /* SQLITE_OMIT_INCRBLOB */ 207 208 209 /* 210 ** Enter the mutex on every Btree associated with a database 211 ** connection. This is needed (for example) prior to parsing 212 ** a statement since we will be comparing table and column names 213 ** against all schemas and we do not want those schemas being 214 ** reset out from under us. 215 ** 216 ** There is a corresponding leave-all procedures. 217 ** 218 ** Enter the mutexes in accending order by BtShared pointer address 219 ** to avoid the possibility of deadlock when two threads with 220 ** two or more btrees in common both try to lock all their btrees 221 ** at the same instant. 222 */ 223 void sqlite3BtreeEnterAll(sqlite3 *db){ 224 int i; 225 Btree *p, *pLater; 226 assert( sqlite3_mutex_held(db->mutex) ); 227 for(i=0; i<db->nDb; i++){ 228 p = db->aDb[i].pBt; 229 assert( !p || (p->locked==0 && p->sharable) || p->pBt->db==p->db ); 230 if( p && p->sharable ){ 231 p->wantToLock++; 232 if( !p->locked ){ 233 assert( p->wantToLock==1 ); 234 while( p->pPrev ) p = p->pPrev; 235 /* Reason for ALWAYS: There must be at least one unlocked Btree in 236 ** the chain. Otherwise the !p->locked test above would have failed */ 237 while( p->locked && ALWAYS(p->pNext) ) p = p->pNext; 238 for(pLater = p->pNext; pLater; pLater=pLater->pNext){ 239 if( pLater->locked ){ 240 unlockBtreeMutex(pLater); 241 } 242 } 243 while( p ){ 244 lockBtreeMutex(p); 245 p = p->pNext; 246 } 247 } 248 } 249 } 250 } 251 void sqlite3BtreeLeaveAll(sqlite3 *db){ 252 int i; 253 Btree *p; 254 assert( sqlite3_mutex_held(db->mutex) ); 255 for(i=0; i<db->nDb; i++){ 256 p = db->aDb[i].pBt; 257 if( p && p->sharable ){ 258 assert( p->wantToLock>0 ); 259 p->wantToLock--; 260 if( p->wantToLock==0 ){ 261 unlockBtreeMutex(p); 262 } 263 } 264 } 265 } 266 267 #ifndef NDEBUG 268 /* 269 ** Return true if the current thread holds the database connection 270 ** mutex and all required BtShared mutexes. 271 ** 272 ** This routine is used inside assert() statements only. 273 */ 274 int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ 275 int i; 276 if( !sqlite3_mutex_held(db->mutex) ){ 277 return 0; 278 } 279 for(i=0; i<db->nDb; i++){ 280 Btree *p; 281 p = db->aDb[i].pBt; 282 if( p && p->sharable && 283 (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){ 284 return 0; 285 } 286 } 287 return 1; 288 } 289 #endif /* NDEBUG */ 290 291 #else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */ 292 /* 293 ** The following are special cases for mutex enter routines for use 294 ** in single threaded applications that use shared cache. Except for 295 ** these two routines, all mutex operations are no-ops in that case and 296 ** are null #defines in btree.h. 297 ** 298 ** If shared cache is disabled, then all btree mutex routines, including 299 ** the ones below, are no-ops and are null #defines in btree.h. 300 */ 301 302 void sqlite3BtreeEnter(Btree *p){ 303 p->pBt->db = p->db; 304 } 305 void sqlite3BtreeEnterAll(sqlite3 *db){ 306 int i; 307 for(i=0; i<db->nDb; i++){ 308 Btree *p = db->aDb[i].pBt; 309 if( p ){ 310 p->pBt->db = p->db; 311 } 312 } 313 } 314 #endif /* if SQLITE_THREADSAFE */ 315 #endif /* ifndef SQLITE_OMIT_SHARED_CACHE */ 316