/* ** 2007 August 14 ** ** 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. ** ************************************************************************* ** This file contains the C functions that implement mutexes for ** use by the SQLite core. ** ** $Id: mutex.c,v 1.6 2007/08/21 10:44:16 drh Exp $ */ /* ** If SQLITE_MUTEX_APPDEF is defined, then this whole module is ** omitted and equivalent functionality must be provided by the ** application that links against the SQLite library. */ #ifndef SQLITE_MUTEX_APPDEF /* This is the beginning of real code */ #include "sqliteInt.h" /* ** Figure out what version of the code to use */ #define SQLITE_MUTEX_NOOP 1 /* The default */ #if 0 #if defined(SQLITE_DEBUG) && !SQLITE_THREADSAFE # undef SQLITE_MUTEX_NOOP # define SQLITE_MUTEX_NOOP_DEBUG #endif #if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && OS_UNIX # undef SQLITE_MUTEX_NOOP # define SQLITE_MUTEX_PTHREAD #endif #if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && OS_WIN # undef SQLITE_MUTEX_NOOP # define SQLITE_MUTEX_WIN #endif #endif #ifdef SQLITE_MUTEX_NOOP /************************ No-op Mutex Implementation ********************** ** ** This first implementation of mutexes is really a no-op. In other words, ** no real locking occurs. This implementation is appropriate for use ** in single threaded applications which do not want the extra overhead ** of thread locking primitives. */ /* ** The sqlite3_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL ** that means that a mutex could not be allocated. */ sqlite3_mutex *sqlite3_mutex_alloc(int idNotUsed){ return (sqlite3_mutex*)8; } /* ** This routine deallocates a previously allocated mutex. */ void sqlite3_mutex_free(sqlite3_mutex *pNotUsed){} /* ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt ** to enter a mutex. If another thread is already within the mutex, ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can ** be entered multiple times by the same thread. In such cases the, ** mutex must be exited an equal number of times before another thread ** can enter. If the same thread tries to enter any other kind of mutex ** more than once, the behavior is undefined. */ void sqlite3_mutex_enter(sqlite3_mutex *pNotUsed){} int sqlite3_mutex_try(sqlite3_mutex *pNotUsed){ return SQLITE_OK; } /* ** The sqlite3_mutex_leave() routine exits a mutex that was ** previously entered by the same thread. The behavior ** is undefined if the mutex is not currently entered or ** is not currently allocated. SQLite will never do either. */ void sqlite3_mutex_leave(sqlite3_mutex *pNotUsed){} /* ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use inside assert() statements. */ int sqlite3_mutex_held(sqlite3_mutex *pNotUsed){ return 1; } int sqlite3_mutex_notheld(sqlite3_mutex *pNotUsed){ return 1; } #endif /* SQLITE_MUTEX_NOOP */ #ifdef SQLITE_MUTEX_NOOP_DEBUG /*************** Error-checking No-op Mutex Implementation ******************* ** ** In this implementation, mutexes do not provide any mutual exclusion. ** But the error checking is provided. This implementation is useful ** for test purposes. */ /* ** The mutex object */ struct sqlite3_mutex { int id; int cnt; }; /* ** The sqlite3_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL ** that means that a mutex could not be allocated. */ sqlite3_mutex *sqlite3_mutex_alloc(int id){ static sqlite3_mutex aStatic[3]; sqlite3_mutex *pNew = 0; switch( id ){ case SQLITE_MUTEX_FAST: case SQLITE_MUTEX_RECURSIVE: { pNew = sqlite3_malloc(sizeof(*pNew)); if( pNew ){ pNew->id = id; pNew->cnt = 0; } break; } default: { pNew = &aStatic[id-SQLITE_MUTEX_STATIC_MASTER]; pNew->id = id; break; } } return pNew; } /* ** This routine deallocates a previously allocated mutex. */ void sqlite3_mutex_free(sqlite3_mutex *p){ assert( p ); assert( p->cnt==0 ); assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); sqlite3_free(p); } /* ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt ** to enter a mutex. If another thread is already within the mutex, ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can ** be entered multiple times by the same thread. In such cases the, ** mutex must be exited an equal number of times before another thread ** can enter. If the same thread tries to enter any other kind of mutex ** more than once, the behavior is undefined. */ void sqlite3_mutex_enter(sqlite3_mutex *p){ assert( p ); assert( p->cnt==0 || p->id==SQLITE_MUTEX_RECURSIVE ); p->cnt++; } int sqlite3_mutex_try(sqlite3_mutex *p){ assert( p ); if( p->cnt>0 && p->id!=SQLITE_MUTEX_RECURSIVE ){ return SQLITE_BUSY; } p->cnt++; return SQLITE_OK; } /* ** The sqlite3_mutex_leave() routine exits a mutex that was ** previously entered by the same thread. The behavior ** is undefined if the mutex is not currently entered or ** is not currently allocated. SQLite will never do either. */ void sqlite3_mutex_leave(sqlite3_mutex *p){ assert( p->cnt>0 ); p->cnt--; } /* ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use inside assert() statements. */ int sqlite3_mutex_held(sqlite3_mutex *p){ return p==0 || p->cnt>0; } int sqlite3_mutex_notheld(sqlite3_mutex *p){ return p==0 || p->cnt==0; } #endif /* SQLITE_MUTEX_NOOP_DEBUG */ #ifdef SQLITE_MUTEX_PTHREAD /**************** Non-recursive Pthread Mutex Implementation ***************** ** ** This implementation of mutexes is built using a version of pthreads that ** does not have native support for recursive mutexes. */ /* ** Each recursive mutex is an instance of the following structure. */ struct sqlite3_mutex { pthread_mutex_t mainMutex; /* Mutex controlling the lock */ pthread_mutex_t auxMutex; /* Mutex controlling access to nRef and owner */ int id; /* Mutex type */ int nRef; /* Number of entrances */ pthread_t owner; /* Thread that is within this mutex */ }; /* ** The sqlite3_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL ** that means that a mutex could not be allocated. SQLite ** will unwind its stack and return an error. The argument ** to sqlite3_mutex_alloc() is one of these integer constants: ** **