4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
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.
11 *************************************************************************
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
19 #ifndef SQLITE_OMIT_SHARED_CACHE
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.
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
) );
32 sqlite3_mutex_enter(p
->pBt
->mutex
);
38 ** Release the BtShared mutex associated with B-Tree handle p and
39 ** clear the p->locked boolean.
41 static void SQLITE_NOINLINE
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
);
48 sqlite3_mutex_leave(pBt
->mutex
);
52 /* Forward reference */
53 static void SQLITE_NOINLINE
btreeLockCarefully(Btree
*p
);
56 ** Enter a mutex on the given BTree object.
58 ** If the object is not sharable, then no mutex is ever required
59 ** and this routine is a no-op. The underlying mutex is non-recursive.
60 ** But we keep a reference count in Btree.wantToLock so the behavior
61 ** of this interface is recursive.
63 ** To avoid deadlocks, multiple Btrees are locked in the same order
64 ** by all database connections. The p->pNext is a list of other
65 ** Btrees belonging to the same database connection as the p Btree
66 ** which need to be locked after p. If we cannot get a lock on
67 ** p, then first unlock all of the others on p->pNext, then wait
68 ** for the lock to become available on p, then relock all of the
69 ** subsequent Btrees that desire a lock.
71 void sqlite3BtreeEnter(Btree
*p
){
72 /* Some basic sanity checking on the Btree. The list of Btrees
73 ** connected by pNext and pPrev should be in sorted order by
74 ** Btree.pBt value. All elements of the list should belong to
75 ** the same connection. Only shared Btrees are on the list. */
76 assert( p
->pNext
==0 || p
->pNext
->pBt
>p
->pBt
);
77 assert( p
->pPrev
==0 || p
->pPrev
->pBt
<p
->pBt
);
78 assert( p
->pNext
==0 || p
->pNext
->db
==p
->db
);
79 assert( p
->pPrev
==0 || p
->pPrev
->db
==p
->db
);
80 assert( p
->sharable
|| (p
->pNext
==0 && p
->pPrev
==0) );
82 /* Check for locking consistency */
83 assert( !p
->locked
|| p
->wantToLock
>0 );
84 assert( p
->sharable
|| p
->wantToLock
==0 );
86 /* We should already hold a lock on the database connection */
87 assert( sqlite3_mutex_held(p
->db
->mutex
) );
89 /* Unless the database is sharable and unlocked, then BtShared.db
90 ** should already be set correctly. */
91 assert( (p
->locked
==0 && p
->sharable
) || p
->pBt
->db
==p
->db
);
93 if( !p
->sharable
) return;
95 if( p
->locked
) return;
96 btreeLockCarefully(p
);
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.
105 static void SQLITE_NOINLINE
btreeLockCarefully(Btree
*p
){
108 /* In most cases, we should be able to acquire the lock we
109 ** want without having to go through the ascending lock
110 ** procedure that follows. Just be sure not to block.
112 if( sqlite3_mutex_try(p
->pBt
->mutex
)==SQLITE_OK
){
118 /* To avoid deadlock, first release all locks with a larger
119 ** BtShared address. Then acquire our lock. Then reacquire
120 ** the other BtShared locks that we used to hold in ascending
123 for(pLater
=p
->pNext
; pLater
; pLater
=pLater
->pNext
){
124 assert( pLater
->sharable
);
125 assert( pLater
->pNext
==0 || pLater
->pNext
->pBt
>pLater
->pBt
);
126 assert( !pLater
->locked
|| pLater
->wantToLock
>0 );
127 if( pLater
->locked
){
128 unlockBtreeMutex(pLater
);
132 for(pLater
=p
->pNext
; pLater
; pLater
=pLater
->pNext
){
133 if( pLater
->wantToLock
){
134 lockBtreeMutex(pLater
);
141 ** Exit the recursive mutex on a Btree.
143 void sqlite3BtreeLeave(Btree
*p
){
144 assert( sqlite3_mutex_held(p
->db
->mutex
) );
146 assert( p
->wantToLock
>0 );
148 if( p
->wantToLock
==0 ){
156 ** Return true if the BtShared mutex is held on the btree, or if the
157 ** B-Tree is not marked as sharable.
159 ** This routine is used only from within assert() statements.
161 int sqlite3BtreeHoldsMutex(Btree
*p
){
162 assert( p
->sharable
==0 || p
->locked
==0 || p
->wantToLock
>0 );
163 assert( p
->sharable
==0 || p
->locked
==0 || p
->db
==p
->pBt
->db
);
164 assert( p
->sharable
==0 || p
->locked
==0 || sqlite3_mutex_held(p
->pBt
->mutex
) );
165 assert( p
->sharable
==0 || p
->locked
==0 || sqlite3_mutex_held(p
->db
->mutex
) );
167 return (p
->sharable
==0 || p
->locked
);
173 ** Enter the mutex on every Btree associated with a database
174 ** connection. This is needed (for example) prior to parsing
175 ** a statement since we will be comparing table and column names
176 ** against all schemas and we do not want those schemas being
177 ** reset out from under us.
179 ** There is a corresponding leave-all procedures.
181 ** Enter the mutexes in accending order by BtShared pointer address
182 ** to avoid the possibility of deadlock when two threads with
183 ** two or more btrees in common both try to lock all their btrees
184 ** at the same instant.
186 static void SQLITE_NOINLINE
btreeEnterAll(sqlite3
*db
){
190 assert( sqlite3_mutex_held(db
->mutex
) );
191 for(i
=0; i
<db
->nDb
; i
++){
193 if( p
&& p
->sharable
){
194 sqlite3BtreeEnter(p
);
198 db
->skipBtreeMutex
= skipOk
;
200 void sqlite3BtreeEnterAll(sqlite3
*db
){
201 if( db
->skipBtreeMutex
==0 ) btreeEnterAll(db
);
203 static void SQLITE_NOINLINE
btreeLeaveAll(sqlite3
*db
){
206 assert( sqlite3_mutex_held(db
->mutex
) );
207 for(i
=0; i
<db
->nDb
; i
++){
209 if( p
) sqlite3BtreeLeave(p
);
212 void sqlite3BtreeLeaveAll(sqlite3
*db
){
213 if( db
->skipBtreeMutex
==0 ) btreeLeaveAll(db
);
218 ** Return true if the current thread holds the database connection
219 ** mutex and all required BtShared mutexes.
221 ** This routine is used inside assert() statements only.
223 int sqlite3BtreeHoldsAllMutexes(sqlite3
*db
){
225 if( !sqlite3_mutex_held(db
->mutex
) ){
228 for(i
=0; i
<db
->nDb
; i
++){
231 if( p
&& p
->sharable
&&
232 (p
->wantToLock
==0 || !sqlite3_mutex_held(p
->pBt
->mutex
)) ){
242 ** Return true if the correct mutexes are held for accessing the
243 ** db->aDb[iDb].pSchema structure. The mutexes required for schema
246 ** (1) The mutex on db
247 ** (2) if iDb!=1, then the mutex on db->aDb[iDb].pBt.
249 ** If pSchema is not NULL, then iDb is computed from pSchema and
250 ** db using sqlite3SchemaToIndex().
252 int sqlite3SchemaMutexHeld(sqlite3
*db
, int iDb
, Schema
*pSchema
){
255 if( pSchema
) iDb
= sqlite3SchemaToIndex(db
, pSchema
);
256 assert( iDb
>=0 && iDb
<db
->nDb
);
257 if( !sqlite3_mutex_held(db
->mutex
) ) return 0;
258 if( iDb
==1 ) return 1;
259 p
= db
->aDb
[iDb
].pBt
;
261 return p
->sharable
==0 || p
->locked
==1;
265 #else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */
267 ** The following are special cases for mutex enter routines for use
268 ** in single threaded applications that use shared cache. Except for
269 ** these two routines, all mutex operations are no-ops in that case and
270 ** are null #defines in btree.h.
272 ** If shared cache is disabled, then all btree mutex routines, including
273 ** the ones below, are no-ops and are null #defines in btree.h.
276 void sqlite3BtreeEnter(Btree
*p
){
279 void sqlite3BtreeEnterAll(sqlite3
*db
){
281 for(i
=0; i
<db
->nDb
; i
++){
282 Btree
*p
= db
->aDb
[i
].pBt
;
288 #endif /* if SQLITE_THREADSAFE */
290 #ifndef SQLITE_OMIT_INCRBLOB
292 ** Enter a mutex on a Btree given a cursor owned by that Btree.
294 ** These entry points are used by incremental I/O only. Enter() is required
295 ** any time OMIT_SHARED_CACHE is not defined, regardless of whether or not
296 ** the build is threadsafe. Leave() is only required by threadsafe builds.
298 void sqlite3BtreeEnterCursor(BtCursor
*pCur
){
299 sqlite3BtreeEnter(pCur
->pBtree
);
301 # if SQLITE_THREADSAFE
302 void sqlite3BtreeLeaveCursor(BtCursor
*pCur
){
303 sqlite3BtreeLeave(pCur
->pBtree
);
306 #endif /* ifndef SQLITE_OMIT_INCRBLOB */
308 #endif /* ifndef SQLITE_OMIT_SHARED_CACHE */