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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 assert( p->sharable==0 || p->locked==0 || p->wantToLock>0 ); | 162 assert( p->sharable==0 || p->locked==0 || p->wantToLock>0 ); |
163 assert( p->sharable==0 || p->locked==0 || p->db==p->pBt->db ); | 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) ); | 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) ); | 165 assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->db->mutex) ); |
166 | 166 |
167 return (p->sharable==0 || p->locked); | 167 return (p->sharable==0 || p->locked); |
168 } | 168 } |
169 #endif | 169 #endif |
170 | 170 |
171 | 171 |
172 #ifndef SQLITE_OMIT_INCRBLOB | |
173 /* | |
174 ** Enter and leave a mutex on a Btree given a cursor owned by that | |
175 ** Btree. These entry points are used by incremental I/O and can be | |
176 ** omitted if that module is not used. | |
177 */ | |
178 void sqlite3BtreeEnterCursor(BtCursor *pCur){ | |
179 sqlite3BtreeEnter(pCur->pBtree); | |
180 } | |
181 void sqlite3BtreeLeaveCursor(BtCursor *pCur){ | |
182 sqlite3BtreeLeave(pCur->pBtree); | |
183 } | |
184 #endif /* SQLITE_OMIT_INCRBLOB */ | |
185 | |
186 | |
187 /* | 172 /* |
188 ** Enter the mutex on every Btree associated with a database | 173 ** Enter the mutex on every Btree associated with a database |
189 ** connection. This is needed (for example) prior to parsing | 174 ** connection. This is needed (for example) prior to parsing |
190 ** a statement since we will be comparing table and column names | 175 ** a statement since we will be comparing table and column names |
191 ** against all schemas and we do not want those schemas being | 176 ** against all schemas and we do not want those schemas being |
192 ** reset out from under us. | 177 ** reset out from under us. |
193 ** | 178 ** |
194 ** There is a corresponding leave-all procedures. | 179 ** There is a corresponding leave-all procedures. |
195 ** | 180 ** |
196 ** Enter the mutexes in accending order by BtShared pointer address | 181 ** Enter the mutexes in accending order by BtShared pointer address |
197 ** to avoid the possibility of deadlock when two threads with | 182 ** to avoid the possibility of deadlock when two threads with |
198 ** two or more btrees in common both try to lock all their btrees | 183 ** two or more btrees in common both try to lock all their btrees |
199 ** at the same instant. | 184 ** at the same instant. |
200 */ | 185 */ |
201 void sqlite3BtreeEnterAll(sqlite3 *db){ | 186 static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){ |
202 int i; | 187 int i; |
| 188 int skipOk = 1; |
203 Btree *p; | 189 Btree *p; |
204 assert( sqlite3_mutex_held(db->mutex) ); | 190 assert( sqlite3_mutex_held(db->mutex) ); |
205 for(i=0; i<db->nDb; i++){ | 191 for(i=0; i<db->nDb; i++){ |
206 p = db->aDb[i].pBt; | 192 p = db->aDb[i].pBt; |
207 if( p ) sqlite3BtreeEnter(p); | 193 if( p && p->sharable ){ |
| 194 sqlite3BtreeEnter(p); |
| 195 skipOk = 0; |
| 196 } |
208 } | 197 } |
| 198 db->skipBtreeMutex = skipOk; |
209 } | 199 } |
210 void sqlite3BtreeLeaveAll(sqlite3 *db){ | 200 void sqlite3BtreeEnterAll(sqlite3 *db){ |
| 201 if( db->skipBtreeMutex==0 ) btreeEnterAll(db); |
| 202 } |
| 203 static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){ |
211 int i; | 204 int i; |
212 Btree *p; | 205 Btree *p; |
213 assert( sqlite3_mutex_held(db->mutex) ); | 206 assert( sqlite3_mutex_held(db->mutex) ); |
214 for(i=0; i<db->nDb; i++){ | 207 for(i=0; i<db->nDb; i++){ |
215 p = db->aDb[i].pBt; | 208 p = db->aDb[i].pBt; |
216 if( p ) sqlite3BtreeLeave(p); | 209 if( p ) sqlite3BtreeLeave(p); |
217 } | 210 } |
218 } | 211 } |
219 | 212 void sqlite3BtreeLeaveAll(sqlite3 *db){ |
220 /* | 213 if( db->skipBtreeMutex==0 ) btreeLeaveAll(db); |
221 ** Return true if a particular Btree requires a lock. Return FALSE if | |
222 ** no lock is ever required since it is not sharable. | |
223 */ | |
224 int sqlite3BtreeSharable(Btree *p){ | |
225 return p->sharable; | |
226 } | 214 } |
227 | 215 |
228 #ifndef NDEBUG | 216 #ifndef NDEBUG |
229 /* | 217 /* |
230 ** Return true if the current thread holds the database connection | 218 ** Return true if the current thread holds the database connection |
231 ** mutex and all required BtShared mutexes. | 219 ** mutex and all required BtShared mutexes. |
232 ** | 220 ** |
233 ** This routine is used inside assert() statements only. | 221 ** This routine is used inside assert() statements only. |
234 */ | 222 */ |
235 int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ | 223 int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 void sqlite3BtreeEnterAll(sqlite3 *db){ | 279 void sqlite3BtreeEnterAll(sqlite3 *db){ |
292 int i; | 280 int i; |
293 for(i=0; i<db->nDb; i++){ | 281 for(i=0; i<db->nDb; i++){ |
294 Btree *p = db->aDb[i].pBt; | 282 Btree *p = db->aDb[i].pBt; |
295 if( p ){ | 283 if( p ){ |
296 p->pBt->db = p->db; | 284 p->pBt->db = p->db; |
297 } | 285 } |
298 } | 286 } |
299 } | 287 } |
300 #endif /* if SQLITE_THREADSAFE */ | 288 #endif /* if SQLITE_THREADSAFE */ |
| 289 |
| 290 #ifndef SQLITE_OMIT_INCRBLOB |
| 291 /* |
| 292 ** Enter a mutex on a Btree given a cursor owned by that Btree. |
| 293 ** |
| 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. |
| 297 */ |
| 298 void sqlite3BtreeEnterCursor(BtCursor *pCur){ |
| 299 sqlite3BtreeEnter(pCur->pBtree); |
| 300 } |
| 301 # if SQLITE_THREADSAFE |
| 302 void sqlite3BtreeLeaveCursor(BtCursor *pCur){ |
| 303 sqlite3BtreeLeave(pCur->pBtree); |
| 304 } |
| 305 # endif |
| 306 #endif /* ifndef SQLITE_OMIT_INCRBLOB */ |
| 307 |
301 #endif /* ifndef SQLITE_OMIT_SHARED_CACHE */ | 308 #endif /* ifndef SQLITE_OMIT_SHARED_CACHE */ |
OLD | NEW |