aboutsummaryrefslogtreecommitdiff
path: root/src/mutex.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mutex.c')
-rw-r--r--src/mutex.c471
1 files changed, 11 insertions, 460 deletions
diff --git a/src/mutex.c b/src/mutex.c
index 9e0de085f..bb33656a2 100644
--- a/src/mutex.c
+++ b/src/mutex.c
@@ -9,116 +9,22 @@
** 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.
+** This file contains the C functions that implement mutexes.
**
-** $Id: mutex.c,v 1.14 2007/08/27 17:27:49 danielk1977 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 internal implementation of mutexes
-** for SQLite.
-*/
-#include "sqliteInt.h"
-
-/*
-** Figure out what version of the code to use. The choices are
-**
-** SQLITE_MUTEX_NOOP For single-threaded applications that
-** do not desire error checking.
-**
-** SQLITE_MUTEX_NOOP_DEBUG For single-threaded applications with
-** error checking to help verify that mutexes
-** are being used correctly even though they
-** are not needed. Used when SQLITE_DEBUG is
-** defined on single-threaded builds.
+** The implementation in this file does not provide any mutual
+** exclusion and is thus suitable for use only in applications
+** that use SQLite in a single thread. But this implementation
+** does do a lot of error checking on mutexes to make sure they
+** are called correctly and at appropriate times. Hence, this
+** implementation is suitable for testing.
+** debugging purposes
**
-** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix.
-**
-** SQLITE_MUTEX_WIN For multi-threaded applications on Win32.
-*/
-#define SQLITE_MUTEX_NOOP 1 /* The default */
-#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
-
-
-
-#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.
+** $Id: mutex.c,v 1.15 2007/08/28 16:34:43 drh Exp $
*/
-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 */
+#include "sqliteInt.h"
#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.
@@ -218,358 +124,3 @@ int sqlite3_mutex_notheld(sqlite3_mutex *p){
return p==0 || p->cnt==0;
}
#endif /* SQLITE_MUTEX_NOOP_DEBUG */
-
-
-
-#ifdef SQLITE_MUTEX_PTHREAD
-/******************** Pthread Mutex Implementation *********************
-**
-** This implementation of mutexes is built using a version of pthreads that
-** has native support for recursive mutexes.
-*/
-#include <pthread.h>
-
-/*
-** Each recursive mutex is an instance of the following structure.
-*/
-struct sqlite3_mutex {
- pthread_mutex_t mutex; /* Mutex controlling the lock */
- 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:
-**
-** <ul>
-** <li> SQLITE_MUTEX_FAST
-** <li> SQLITE_MUTEX_RECURSIVE
-** <li> SQLITE_MUTEX_STATIC_MASTER
-** <li> SQLITE_MUTEX_STATIC_MEM
-** <li> SQLITE_MUTEX_STATIC_MEM2
-** <li> SQLITE_MUTEX_STATIC_PRNG
-** <li> SQLITE_MUTEX_STATIC_LRU
-** </ul>
-**
-** The first two constants cause sqlite3_mutex_alloc() to create
-** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
-** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
-** The mutex implementation does not need to make a distinction
-** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
-** not want to. But SQLite will only request a recursive mutex in
-** cases where it really needs one. If a faster non-recursive mutex
-** implementation is available on the host platform, the mutex subsystem
-** might return such a mutex in response to SQLITE_MUTEX_FAST.
-**
-** The other allowed parameters to sqlite3_mutex_alloc() each return
-** a pointer to a static preexisting mutex. Three static mutexes are
-** used by the current version of SQLite. Future versions of SQLite
-** may add additional static mutexes. Static mutexes are for internal
-** use by SQLite only. Applications that use SQLite mutexes should
-** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
-** SQLITE_MUTEX_RECURSIVE.
-**
-** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
-** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
-** returns a different mutex on every call. But for the static
-** mutex types, the same mutex is returned on every call that has
-** the same type number.
-*/
-sqlite3_mutex *sqlite3_mutex_alloc(int iType){
- static sqlite3_mutex staticMutexes[] = {
- { PTHREAD_MUTEX_INITIALIZER, },
- { PTHREAD_MUTEX_INITIALIZER, },
- { PTHREAD_MUTEX_INITIALIZER, },
- { PTHREAD_MUTEX_INITIALIZER, },
- { PTHREAD_MUTEX_INITIALIZER, },
- };
- sqlite3_mutex *p;
- switch( iType ){
- case SQLITE_MUTEX_RECURSIVE: {
- p = sqlite3MallocZero( sizeof(*p) );
- if( p ){
- pthread_mutexattr_t recursiveAttr;
- pthread_mutexattr_init(&recursiveAttr);
- pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&p->mutex, &recursiveAttr);
- pthread_mutexattr_destroy(&recursiveAttr);
- p->id = iType;
- }
- break;
- }
- case SQLITE_MUTEX_FAST: {
- p = sqlite3MallocZero( sizeof(*p) );
- if( p ){
- p->id = iType;
- pthread_mutex_init(&p->mutex, 0);
- }
- break;
- }
- default: {
- assert( iType-2 >= 0 );
- assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
- p = &staticMutexes[iType-2];
- p->id = iType;
- break;
- }
- }
- return p;
-}
-
-
-/*
-** This routine deallocates a previously
-** allocated mutex. SQLite is careful to deallocate every
-** mutex that it allocates.
-*/
-void sqlite3_mutex_free(sqlite3_mutex *p){
- assert( p );
- assert( p->nRef==0 );
- assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
- pthread_mutex_destroy(&p->mutex);
- 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->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
- pthread_mutex_lock(&p->mutex);
- p->owner = pthread_self();
- p->nRef++;
-}
-int sqlite3_mutex_try(sqlite3_mutex *p){
- int rc;
- assert( p );
- assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
- if( pthread_mutex_trylock(&p->mutex)==0 ){
- p->owner = pthread_self();
- p->nRef++;
- rc = SQLITE_OK;
- }else{
- rc = SQLITE_BUSY;
- }
- return rc;
-}
-
-/*
-** 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 );
- assert( sqlite3_mutex_held(p) );
- p->nRef--;
- assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
- pthread_mutex_unlock(&p->mutex);
-}
-
-/*
-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
-** intended for use only inside assert() statements. On some platforms,
-** there might be race conditions that can cause these routines to
-** deliver incorrect results. In particular, if pthread_equal() is
-** not an atomic operation, then these routines might delivery
-** incorrect results. On most platforms, pthread_equal() is a
-** comparison of two integers and is therefore atomic. But we are
-** told that HPUX is not such a platform. If so, then these routines
-** will not always work correctly on HPUX.
-**
-** On those platforms where pthread_equal() is not atomic, SQLite
-** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to
-** make sure no assert() statements are evaluated and hence these
-** routines are never called.
-*/
-#ifndef NDEBUG
-int sqlite3_mutex_held(sqlite3_mutex *p){
- return p==0 || (p->nRef!=0 && pthread_equal(p->owner, pthread_self()));
-}
-int sqlite3_mutex_notheld(sqlite3_mutex *p){
- return p==0 || p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
-}
-#endif
-#endif /* SQLITE_MUTEX_PTHREAD */
-
-#ifdef SQLITE_MUTEX_WIN
-/********************** Windows Mutex Implementation **********************
-**
-** This implementation of mutexes is built using the win32 API.
-*/
-
-/*
-** Each recursive mutex is an instance of the following structure.
-*/
-struct sqlite3_mutex {
- CRITICAL_SECTION mutex; /* Mutex controlling the lock */
- int id; /* Mutex type */
- int nRef; /* Number of enterances */
- DWORD owner; /* Thread holding 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:
-**
-** <ul>
-** <li> SQLITE_MUTEX_FAST 0
-** <li> SQLITE_MUTEX_RECURSIVE 1
-** <li> SQLITE_MUTEX_STATIC_MASTER 2
-** <li> SQLITE_MUTEX_STATIC_MEM 3
-** <li> SQLITE_MUTEX_STATIC_PRNG 4
-** </ul>
-**
-** The first two constants cause sqlite3_mutex_alloc() to create
-** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
-** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
-** The mutex implementation does not need to make a distinction
-** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
-** not want to. But SQLite will only request a recursive mutex in
-** cases where it really needs one. If a faster non-recursive mutex
-** implementation is available on the host platform, the mutex subsystem
-** might return such a mutex in response to SQLITE_MUTEX_FAST.
-**
-** The other allowed parameters to sqlite3_mutex_alloc() each return
-** a pointer to a static preexisting mutex. Three static mutexes are
-** used by the current version of SQLite. Future versions of SQLite
-** may add additional static mutexes. Static mutexes are for internal
-** use by SQLite only. Applications that use SQLite mutexes should
-** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
-** SQLITE_MUTEX_RECURSIVE.
-**
-** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
-** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
-** returns a different mutex on every call. But for the static
-** mutex types, the same mutex is returned on every call that has
-** the same type number.
-*/
-sqlite3_mutex *sqlite3_mutex_alloc(int iType){
- sqlite3_mutex *p;
-
- switch( iType ){
- case SQLITE_MUTEX_FAST:
- case SQLITE_MUTEX_RECURSIVE: {
- p = sqlite3MallocZero( sizeof(*p) );
- if( p ){
- p->id = iType;
- InitializeCriticalSection(&p->mutex);
- }
- break;
- }
- default: {
- static sqlite3_mutex staticMutexes[5];
- static int isInit = 0;
- while( !isInit ){
- static long lock = 0;
- if( InterlockedIncrement(&lock)==1 ){
- int i;
- for(i=0; i<sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++){
- InitializeCriticalSection(&staticMutexes[i].mutex);
- }
- isInit = 1;
- }else{
- Sleep(1);
- }
- }
- assert( iType-2 >= 0 );
- assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
- p = &staticMutexes[iType-2];
- p->id = iType;
- break;
- }
- }
- return p;
-}
-
-
-/*
-** This routine deallocates a previously
-** allocated mutex. SQLite is careful to deallocate every
-** mutex that it allocates.
-*/
-void sqlite3_mutex_free(sqlite3_mutex *p){
- assert( p );
- assert( p->nRef==0 );
- assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
- DeleteCriticalSection(&p->mutex);
- 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->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
- EnterCriticalSection(&p->mutex);
- p->owner = GetCurrentThreadId();
- p->nRef++;
-}
-int sqlite3_mutex_try(sqlite3_mutex *p){
- int rc;
- assert( p );
- assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
- if( TryEnterCriticalSection(&p->mutex) ){
- p->owner = GetCurrentThreadId();
- p->nRef++;
- rc = SQLITE_OK;
- }else{
- rc = SQLITE_BUSY;
- }
- return rc;
-}
-
-/*
-** 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->nRef>0 );
- assert( p->owner==GetCurrentThreadId() );
- p->nRef--;
- assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
- LeaveCriticalSection(&p->mutex);
-}
-
-/*
-** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
-** intended for use only inside assert() statements.
-*/
-int sqlite3_mutex_held(sqlite3_mutex *p){
- return p==0 || (p->nRef!=0 && p->owner==GetCurrentThreadId());
-}
-int sqlite3_mutex_notheld(sqlite3_mutex *p){
- return p==0 || p->nRef==0 || p->owner!=GetCurrentThreadId();
-}
-#endif /* SQLITE_MUTEX_WIN */
-
-#endif /* !defined(SQLITE_MUTEX_APPDEF) */