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 *************************************************************************
15 ** This file contains code used to implement mutexes on Btree objects.
16 ** This code really belongs in btree.c. But btree.c is getting too
17 ** big and we want to break it down some. This packaged seemed like
21 #if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE)
25 ** Enter a mutex on the given BTree object.
27 ** If the object is not sharable, then no mutex is ever required
28 ** and this routine is a no-op. The underlying mutex is non-recursive.
29 ** But we keep a reference count in Btree.wantToLock so the behavior
30 ** of this interface is recursive.
32 ** To avoid deadlocks, multiple Btrees are locked in the same order
33 ** by all database connections. The p->pNext is a list of other
34 ** Btrees belonging to the same database connection as the p Btree
35 ** which need to be locked after p. If we cannot get a lock on
36 ** p, then first unlock all of the others on p->pNext, then wait
37 ** for the lock to become available on p, then relock all of the
38 ** subsequent Btrees that desire a lock.
40 void sqlite3BtreeEnter(Btree *p){
43 /* Some basic sanity checking on the Btree. The list of Btrees
44 ** connected by pNext and pPrev should be in sorted order by
45 ** Btree.pBt value. All elements of the list should belong to
46 ** the same connection. Only shared Btrees are on the list. */
47 assert( p->pNext==0 || p->pNext->pBt>p->pBt );
48 assert( p->pPrev==0 || p->pPrev->pBt<p->pBt );
49 assert( p->pNext==0 || p->pNext->pSqlite==p->pSqlite );
50 assert( p->pPrev==0 || p->pPrev->pSqlite==p->pSqlite );
51 assert( p->sharable || (p->pNext==0 && p->pPrev==0) );
53 /* Check for locking consistency */
54 assert( !p->locked || p->wantToLock>0 );
55 assert( p->sharable || p->wantToLock==0 );
57 /* We should already hold a lock on the database connection */
58 assert( sqlite3_mutex_held(p->pSqlite->mutex) );
60 if( !p->sharable ) return;
62 if( p->locked ) return;
64 /* In most cases, we should be able to acquire the lock we
65 ** want without having to go throught the ascending lock
66 ** procedure that follows. Just be sure not to block.
68 if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){
73 /* To avoid deadlock, first release all locks with a larger
74 ** BtShared address. Then acquire our lock. Then reacquire
75 ** the other BtShared locks that we used to hold in ascending
78 for(pLater=p->pNext; pLater; pLater=pLater->pNext){
79 assert( pLater->sharable );
80 assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt );
81 assert( !pLater->locked || pLater->wantToLock>0 );
83 sqlite3_mutex_leave(pLater->pBt->mutex);
87 sqlite3_mutex_enter(p->pBt->mutex);
89 for(pLater=p->pNext; pLater; pLater=pLater->pNext){
90 if( pLater->wantToLock ){
91 sqlite3_mutex_enter(pLater->pBt->mutex);
98 ** Exit the recursive mutex on a Btree.
100 void sqlite3BtreeLeave(Btree *p){
102 assert( p->wantToLock>0 );
104 if( p->wantToLock==0 ){
106 sqlite3_mutex_leave(p->pBt->mutex);
114 ** Return true if the BtShared mutex is held on the btree.
116 ** This routine makes no determination one why or another if the
117 ** database connection mutex is held.
119 ** This routine is used only from within assert() statements.
121 int sqlite3BtreeHoldsMutex(Btree *p){
122 return (p->sharable==0 ||
123 (p->locked && p->wantToLock && sqlite3_mutex_held(p->pBt->mutex)));
128 #ifndef SQLITE_OMIT_INCRBLOB
130 ** Enter and leave a mutex on a Btree given a cursor owned by that
131 ** Btree. These entry points are used by incremental I/O and can be
132 ** omitted if that module is not used.
134 void sqlite3BtreeEnterCursor(BtCursor *pCur){
135 sqlite3BtreeEnter(pCur->pBtree);
137 void sqlite3BtreeLeaveCursor(BtCursor *pCur){
138 sqlite3BtreeLeave(pCur->pBtree);
140 #endif /* SQLITE_OMIT_INCRBLOB */
144 ** Enter the mutex on every Btree associated with a database
145 ** connection. This is needed (for example) prior to parsing
146 ** a statement since we will be comparing table and column names
147 ** against all schemas and we do not want those schemas being
148 ** reset out from under us.
150 ** There is a corresponding leave-all procedures.
152 ** Enter the mutexes in accending order by BtShared pointer address
153 ** to avoid the possibility of deadlock when two threads with
154 ** two or more btrees in common both try to lock all their btrees
155 ** at the same instant.
157 void sqlite3BtreeEnterAll(sqlite3 *db){
160 assert( sqlite3_mutex_held(db->mutex) );
161 for(i=0; i<db->nDb; i++){
163 if( p && p->sharable ){
166 assert( p->wantToLock==1 );
167 while( p->pPrev ) p = p->pPrev;
168 while( p->locked && p->pNext ) p = p->pNext;
169 for(pLater = p->pNext; pLater; pLater=pLater->pNext){
170 if( pLater->locked ){
171 sqlite3_mutex_leave(pLater->pBt->mutex);
176 sqlite3_mutex_enter(p->pBt->mutex);
184 void sqlite3BtreeLeaveAll(sqlite3 *db){
187 assert( sqlite3_mutex_held(db->mutex) );
188 for(i=0; i<db->nDb; i++){
190 if( p && p->sharable ){
191 assert( p->wantToLock>0 );
193 if( p->wantToLock==0 ){
195 sqlite3_mutex_leave(p->pBt->mutex);
204 ** Return true if the current thread holds the database connection
205 ** mutex and all required BtShared mutexes.
207 ** This routine is used inside assert() statements only.
209 int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
211 if( !sqlite3_mutex_held(db->mutex) ){
214 for(i=0; i<db->nDb; i++){
217 if( p && p->sharable &&
218 (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){
227 ** Potentially dd a new Btree pointer to a BtreeMutexArray.
228 ** Really only add the Btree if it can possibly be shared with
229 ** another database connection.
231 ** The Btrees are kept in sorted order by pBtree->pBt. That
232 ** way when we go to enter all the mutexes, we can enter them
233 ** in order without every having to backup and retry and without
234 ** worrying about deadlock.
236 ** The number of shared btrees will always be small (usually 0 or 1)
237 ** so an insertion sort is an adequate algorithm here.
239 void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){
242 if( pBtree==0 || pBtree->sharable==0 ) return;
245 for(i=0; i<pArray->nMutex; i++){
246 assert( pArray->aBtree[i]!=pBtree );
250 assert( pArray->nMutex>=0 );
251 assert( pArray->nMutex<sizeof(pArray->aBtree)/sizeof(pArray->aBtree[0])-1 );
253 for(i=0; i<pArray->nMutex; i++){
254 assert( pArray->aBtree[i]!=pBtree );
255 if( pArray->aBtree[i]->pBt>pBt ){
256 for(j=pArray->nMutex; j>i; j--){
257 pArray->aBtree[j] = pArray->aBtree[j-1];
259 pArray->aBtree[i] = pBtree;
264 pArray->aBtree[pArray->nMutex++] = pBtree;
268 ** Enter the mutex of every btree in the array. This routine is
269 ** called at the beginning of sqlite3VdbeExec(). The mutexes are
270 ** exited at the end of the same function.
272 void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){
274 for(i=0; i<pArray->nMutex; i++){
275 Btree *p = pArray->aBtree[i];
276 /* Some basic sanity checking */
277 assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
278 assert( !p->locked || p->wantToLock>0 );
280 /* We should already hold a lock on the database connection */
281 assert( sqlite3_mutex_held(p->pSqlite->mutex) );
284 if( !p->locked && p->sharable ){
285 sqlite3_mutex_enter(p->pBt->mutex);
292 ** Leave the mutex of every btree in the group.
294 void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){
296 for(i=0; i<pArray->nMutex; i++){
297 Btree *p = pArray->aBtree[i];
298 /* Some basic sanity checking */
299 assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
300 assert( p->locked || !p->sharable );
301 assert( p->wantToLock>0 );
303 /* We should already hold a lock on the database connection */
304 assert( sqlite3_mutex_held(p->pSqlite->mutex) );
307 if( p->wantToLock==0 && p->locked ){
308 sqlite3_mutex_leave(p->pBt->mutex);
315 #endif /* SQLITE_THREADSAFE && !SQLITE_OMIT_SHARED_CACHE */