--- a/engine/sqlite/src/btmutex.cpp Wed Apr 28 13:20:05 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,315 +0,0 @@
-/*
-** 2007 August 27
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** $Id: btmutex.cpp 1282 2008-11-13 09:31:33Z LarsPson $
-**
-** This file contains code used to implement mutexes on Btree objects.
-** This code really belongs in btree.c. But btree.c is getting too
-** big and we want to break it down some. This packaged seemed like
-** a good breakout.
-*/
-#include "btreeInt.h"
-#if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE)
-
-
-/*
-** Enter a mutex on the given BTree object.
-**
-** If the object is not sharable, then no mutex is ever required
-** and this routine is a no-op. The underlying mutex is non-recursive.
-** But we keep a reference count in Btree.wantToLock so the behavior
-** of this interface is recursive.
-**
-** To avoid deadlocks, multiple Btrees are locked in the same order
-** by all database connections. The p->pNext is a list of other
-** Btrees belonging to the same database connection as the p Btree
-** which need to be locked after p. If we cannot get a lock on
-** p, then first unlock all of the others on p->pNext, then wait
-** for the lock to become available on p, then relock all of the
-** subsequent Btrees that desire a lock.
-*/
-void sqlite3BtreeEnter(Btree *p){
- Btree *pLater;
-
- /* Some basic sanity checking on the Btree. The list of Btrees
- ** connected by pNext and pPrev should be in sorted order by
- ** Btree.pBt value. All elements of the list should belong to
- ** the same connection. Only shared Btrees are on the list. */
- assert( p->pNext==0 || p->pNext->pBt>p->pBt );
- assert( p->pPrev==0 || p->pPrev->pBt<p->pBt );
- assert( p->pNext==0 || p->pNext->db==p->db );
- assert( p->pPrev==0 || p->pPrev->db==p->db );
- assert( p->sharable || (p->pNext==0 && p->pPrev==0) );
-
- /* Check for locking consistency */
- assert( !p->locked || p->wantToLock>0 );
- assert( p->sharable || p->wantToLock==0 );
-
- /* We should already hold a lock on the database connection */
- assert( sqlite3_mutex_held(p->db->mutex) );
-
- if( !p->sharable ) return;
- p->wantToLock++;
- if( p->locked ) return;
-
- /* In most cases, we should be able to acquire the lock we
- ** want without having to go throught the ascending lock
- ** procedure that follows. Just be sure not to block.
- */
- if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){
- p->locked = 1;
- return;
- }
-
- /* To avoid deadlock, first release all locks with a larger
- ** BtShared address. Then acquire our lock. Then reacquire
- ** the other BtShared locks that we used to hold in ascending
- ** order.
- */
- for(pLater=p->pNext; pLater; pLater=pLater->pNext){
- assert( pLater->sharable );
- assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt );
- assert( !pLater->locked || pLater->wantToLock>0 );
- if( pLater->locked ){
- sqlite3_mutex_leave(pLater->pBt->mutex);
- pLater->locked = 0;
- }
- }
- sqlite3_mutex_enter(p->pBt->mutex);
- p->locked = 1;
- for(pLater=p->pNext; pLater; pLater=pLater->pNext){
- if( pLater->wantToLock ){
- sqlite3_mutex_enter(pLater->pBt->mutex);
- pLater->locked = 1;
- }
- }
-}
-
-/*
-** Exit the recursive mutex on a Btree.
-*/
-void sqlite3BtreeLeave(Btree *p){
- if( p->sharable ){
- assert( p->wantToLock>0 );
- p->wantToLock--;
- if( p->wantToLock==0 ){
- assert( p->locked );
- sqlite3_mutex_leave(p->pBt->mutex);
- p->locked = 0;
- }
- }
-}
-
-#ifndef NDEBUG
-/*
-** Return true if the BtShared mutex is held on the btree.
-**
-** This routine makes no determination one why or another if the
-** database connection mutex is held.
-**
-** This routine is used only from within assert() statements.
-*/
-int sqlite3BtreeHoldsMutex(Btree *p){
- return (p->sharable==0 ||
- (p->locked && p->wantToLock && sqlite3_mutex_held(p->pBt->mutex)));
-}
-#endif
-
-
-#ifndef SQLITE_OMIT_INCRBLOB
-/*
-** Enter and leave a mutex on a Btree given a cursor owned by that
-** Btree. These entry points are used by incremental I/O and can be
-** omitted if that module is not used.
-*/
-void sqlite3BtreeEnterCursor(BtCursor *pCur){
- sqlite3BtreeEnter(pCur->pBtree);
-}
-void sqlite3BtreeLeaveCursor(BtCursor *pCur){
- sqlite3BtreeLeave(pCur->pBtree);
-}
-#endif /* SQLITE_OMIT_INCRBLOB */
-
-
-/*
-** Enter the mutex on every Btree associated with a database
-** connection. This is needed (for example) prior to parsing
-** a statement since we will be comparing table and column names
-** against all schemas and we do not want those schemas being
-** reset out from under us.
-**
-** There is a corresponding leave-all procedures.
-**
-** Enter the mutexes in accending order by BtShared pointer address
-** to avoid the possibility of deadlock when two threads with
-** two or more btrees in common both try to lock all their btrees
-** at the same instant.
-*/
-void sqlite3BtreeEnterAll(sqlite3 *db){
- int i;
- Btree *p, *pLater;
- assert( sqlite3_mutex_held(db->mutex) );
- for(i=0; i<db->nDb; i++){
- p = db->aDb[i].pBt;
- if( p && p->sharable ){
- p->wantToLock++;
- if( !p->locked ){
- assert( p->wantToLock==1 );
- while( p->pPrev ) p = p->pPrev;
- while( p->locked && p->pNext ) p = p->pNext;
- for(pLater = p->pNext; pLater; pLater=pLater->pNext){
- if( pLater->locked ){
- sqlite3_mutex_leave(pLater->pBt->mutex);
- pLater->locked = 0;
- }
- }
- while( p ){
- sqlite3_mutex_enter(p->pBt->mutex);
- p->locked++;
- p = p->pNext;
- }
- }
- }
- }
-}
-void sqlite3BtreeLeaveAll(sqlite3 *db){
- int i;
- Btree *p;
- assert( sqlite3_mutex_held(db->mutex) );
- for(i=0; i<db->nDb; i++){
- p = db->aDb[i].pBt;
- if( p && p->sharable ){
- assert( p->wantToLock>0 );
- p->wantToLock--;
- if( p->wantToLock==0 ){
- assert( p->locked );
- sqlite3_mutex_leave(p->pBt->mutex);
- p->locked = 0;
- }
- }
- }
-}
-
-#ifndef NDEBUG
-/*
-** Return true if the current thread holds the database connection
-** mutex and all required BtShared mutexes.
-**
-** This routine is used inside assert() statements only.
-*/
-int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
- int i;
- if( !sqlite3_mutex_held(db->mutex) ){
- return 0;
- }
- for(i=0; i<db->nDb; i++){
- Btree *p;
- p = db->aDb[i].pBt;
- if( p && p->sharable &&
- (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){
- return 0;
- }
- }
- return 1;
-}
-#endif /* NDEBUG */
-
-/*
-** Potentially dd a new Btree pointer to a BtreeMutexArray.
-** Really only add the Btree if it can possibly be shared with
-** another database connection.
-**
-** The Btrees are kept in sorted order by pBtree->pBt. That
-** way when we go to enter all the mutexes, we can enter them
-** in order without every having to backup and retry and without
-** worrying about deadlock.
-**
-** The number of shared btrees will always be small (usually 0 or 1)
-** so an insertion sort is an adequate algorithm here.
-*/
-void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){
- int i, j;
- BtShared *pBt;
- if( pBtree==0 || pBtree->sharable==0 ) return;
-#ifndef NDEBUG
- {
- for(i=0; i<pArray->nMutex; i++){
- assert( pArray->aBtree[i]!=pBtree );
- }
- }
-#endif
- assert( pArray->nMutex>=0 );
- assert( pArray->nMutex<sizeof(pArray->aBtree)/sizeof(pArray->aBtree[0])-1 );
- pBt = pBtree->pBt;
- for(i=0; i<pArray->nMutex; i++){
- assert( pArray->aBtree[i]!=pBtree );
- if( pArray->aBtree[i]->pBt>pBt ){
- for(j=pArray->nMutex; j>i; j--){
- pArray->aBtree[j] = pArray->aBtree[j-1];
- }
- pArray->aBtree[i] = pBtree;
- pArray->nMutex++;
- return;
- }
- }
- pArray->aBtree[pArray->nMutex++] = pBtree;
-}
-
-/*
-** Enter the mutex of every btree in the array. This routine is
-** called at the beginning of sqlite3VdbeExec(). The mutexes are
-** exited at the end of the same function.
-*/
-void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){
- int i;
- for(i=0; i<pArray->nMutex; i++){
- Btree *p = pArray->aBtree[i];
- /* Some basic sanity checking */
- assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
- assert( !p->locked || p->wantToLock>0 );
-
- /* We should already hold a lock on the database connection */
- assert( sqlite3_mutex_held(p->db->mutex) );
-
- p->wantToLock++;
- if( !p->locked && p->sharable ){
- sqlite3_mutex_enter(p->pBt->mutex);
- p->locked = 1;
- }
- }
-}
-
-/*
-** Leave the mutex of every btree in the group.
-*/
-void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){
- int i;
- for(i=0; i<pArray->nMutex; i++){
- Btree *p = pArray->aBtree[i];
- /* Some basic sanity checking */
- assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
- assert( p->locked || !p->sharable );
- assert( p->wantToLock>0 );
-
- /* We should already hold a lock on the database connection */
- assert( sqlite3_mutex_held(p->db->mutex) );
-
- p->wantToLock--;
- if( p->wantToLock==0 && p->locked ){
- sqlite3_mutex_leave(p->pBt->mutex);
- p->locked = 0;
- }
- }
-}
-
-
-#endif /* SQLITE_THREADSAFE && !SQLITE_OMIT_SHARED_CACHE */