xref: /sqlite-3.40.0/src/btmutex.c (revision bdaec52c)
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