diff options
author | danielk1977 <danielk1977@noemail.net> | 2008-06-17 17:21:18 +0000 |
---|---|---|
committer | danielk1977 <danielk1977@noemail.net> | 2008-06-17 17:21:18 +0000 |
commit | 6d2ab0e4318e293000c42fb667bf0a16a198ce0e (patch) | |
tree | 07aca844bf442b2efbae6de14ec2cfc3daa81d8b /src | |
parent | facf0307921bd08c3b60b1293bcc5859eee2db10 (diff) | |
download | sqlite-6d2ab0e4318e293000c42fb667bf0a16a198ce0e.tar.gz sqlite-6d2ab0e4318e293000c42fb667bf0a16a198ce0e.zip |
Change the mutex interface to be pluggable. This is an incremental checkin, there are still changes to come. (CVS 5227)
FossilOrigin-Name: 597283637bcdc2398bf249b2bbc6ded47ad2de22
Diffstat (limited to 'src')
-rw-r--r-- | src/mem2.c | 4 | ||||
-rw-r--r-- | src/mutex.c | 177 | ||||
-rw-r--r-- | src/mutex_unix.c | 97 | ||||
-rw-r--r-- | src/mutex_w32.c | 59 | ||||
-rw-r--r-- | src/sqlite.h.in | 16 | ||||
-rw-r--r-- | src/sqliteInt.h | 5 |
6 files changed, 259 insertions, 99 deletions
diff --git a/src/mem2.c b/src/mem2.c index 311f02dbd..4f97ba2ce 100644 --- a/src/mem2.c +++ b/src/mem2.c @@ -19,7 +19,7 @@ ** This file contains implementations of the low-level memory allocation ** routines specified in the sqlite3_mem_methods object. ** -** $Id: mem2.c,v 1.30 2008/06/17 15:12:01 drh Exp $ +** $Id: mem2.c,v 1.31 2008/06/17 17:21:18 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -321,7 +321,7 @@ void sqlite3MemSetDefault(void){ /* ** Set the number of backtrace levels kept for each allocation. -** A value of zero turns of backtracing. The number is always rounded +** A value of zero turns off backtracing. The number is always rounded ** up to a multiple of 2. */ void sqlite3MemdebugBacktrace(int depth){ diff --git a/src/mutex.c b/src/mutex.c index 23c0422f6..3eded653b 100644 --- a/src/mutex.c +++ b/src/mutex.c @@ -19,10 +19,115 @@ ** implementation is suitable for testing. ** debugging purposes ** -** $Id: mutex.c,v 1.20 2008/06/15 02:51:48 drh Exp $ +** $Id: mutex.c,v 1.21 2008/06/17 17:21:18 danielk1977 Exp $ */ #include "sqliteInt.h" +#ifndef SQLITE_MUTEX_NOOP +/* +** Initialize the mutex system. +*/ +int sqlite3_mutex_init(void){ + int rc; + if( !sqlite3Config.mutex.xMutexAlloc ){ + sqlite3_mutex_methods *p = sqlite3DefaultMutex(); + sqlite3_mutex *pMaster; + + rc = p->xMutexInit(); + if( rc==SQLITE_OK ){ + pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER); + p->xMutexEnter(pMaster); + assert( sqlite3Config.mutex.xMutexAlloc==0 + || sqlite3Config.mutex.xMutexAlloc==p->xMutexAlloc + ); + if( !sqlite3Config.mutex.xMutexAlloc ){ + sqlite3Config.mutex = *p; + } + p->xMutexLeave(pMaster); + } + + }else{ + rc = sqlite3Config.mutex.xMutexInit(); + } + + return rc; +} + +/* +** Shutdown the mutex system. This call frees resources allocated by +** sqlite3_mutex_init(). +*/ +int sqlite3_mutex_end(void){ + int rc = SQLITE_OK; + rc = sqlite3Config.mutex.xMutexEnd(); + return rc; +} + +/* +** Retrieve a pointer to a static mutex or allocate a new dynamic one. +*/ +sqlite3_mutex *sqlite3_mutex_alloc(int id){ + return sqlite3Config.mutex.xMutexAlloc(id); +} + +/* +** Free a dynamic mutex. +*/ +void sqlite3_mutex_free(sqlite3_mutex *p){ + if( p ){ + sqlite3Config.mutex.xMutexFree(p); + } +} + +/* +** Obtain the mutex p. If some other thread already has the mutex, block +** until it can be obtained. +*/ +void sqlite3_mutex_enter(sqlite3_mutex *p){ + if( p ){ + sqlite3Config.mutex.xMutexEnter(p); + } +} + +/* +** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another +** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. +*/ +int sqlite3_mutex_try(sqlite3_mutex *p){ + int rc = SQLITE_OK; + if( p ){ + return sqlite3Config.mutex.xMutexTry(p); + } + 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. If a NULL pointer is passed as an argument +** this function is a no-op. +*/ +void sqlite3_mutex_leave(sqlite3_mutex *p){ + if( p ){ + sqlite3Config.mutex.xMutexLeave(p); + } +} + +#ifndef NDEBUG +/* +** 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 || sqlite3Config.mutex.xMutexHeld(p); +} +int sqlite3_mutex_notheld(sqlite3_mutex *p){ + return p==0 || sqlite3Config.mutex.xMutexNotheld(p); +} +#endif + +#endif + #ifdef SQLITE_MUTEX_NOOP_DEBUG /* ** In this implementation, mutexes do not provide any mutual exclusion. @@ -39,17 +144,28 @@ struct sqlite3_mutex { }; /* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use inside assert() statements. +*/ +static int noopMutexHeld(sqlite3_mutex *p){ + return p==0 || p->cnt>0; +} +static int noopMutexNotheld(sqlite3_mutex *p){ + return p==0 || p->cnt==0; +} + +/* ** Initialize and deinitialize the mutex subsystem. */ -int sqlite3_mutex_init(void){ return SQLITE_OK; } -int sqlite3_mutex_end(void){ return SQLITE_OK; } +static int noopMutexInit(void){ return SQLITE_OK; } +static int noopMutexEnd(void){ return SQLITE_OK; } /* ** 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 *noopMutexAlloc(int id){ static sqlite3_mutex aStatic[6]; sqlite3_mutex *pNew = 0; switch( id ){ @@ -76,8 +192,7 @@ sqlite3_mutex *sqlite3_mutex_alloc(int id){ /* ** This routine deallocates a previously allocated mutex. */ -void sqlite3_mutex_free(sqlite3_mutex *p){ - if( p==0 ) return; +static void noopMutexFree(sqlite3_mutex *p){ assert( p->cnt==0 ); assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); sqlite3_free(p); @@ -94,17 +209,13 @@ void sqlite3_mutex_free(sqlite3_mutex *p){ ** 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){ - if( p ){ - assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); - p->cnt++; - } +static void noopMutexEnter(sqlite3_mutex *p){ + assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) ); + p->cnt++; } -int sqlite3_mutex_try(sqlite3_mutex *p){ - if( p ){ - assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); - p->cnt++; - } +static int noopMutexTry(sqlite3_mutex *p){ + assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) ); + p->cnt++; return SQLITE_OK; } @@ -114,22 +225,26 @@ int sqlite3_mutex_try(sqlite3_mutex *p){ ** 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){ - if( p ){ - assert( sqlite3_mutex_held(p) ); - p->cnt--; - assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); - } +static void noopMutexLeave(sqlite3_mutex *p){ + assert( sqlite3_mutex_held(p) ); + p->cnt--; + assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); } -/* -** 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; +sqlite3_mutex_methods *sqlite3DefaultMutex(void){ + static sqlite3_mutex_methods sMutex = { + noopMutexInit, + noopMutexAlloc, + noopMutexFree, + noopMutexEnter, + noopMutexTry, + noopMutexLeave, + noopMutexEnd, + + noopMutexHeld, + noopMutexNotheld + }; + + return &sMutex; } #endif /* SQLITE_MUTEX_NOOP_DEBUG */ diff --git a/src/mutex_unix.c b/src/mutex_unix.c index 4639a8427..2ec52a1a9 100644 --- a/src/mutex_unix.c +++ b/src/mutex_unix.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains the C functions that implement mutexes for pthreads ** -** $Id: mutex_unix.c,v 1.8 2008/06/13 18:24:27 drh Exp $ +** $Id: mutex_unix.c,v 1.9 2008/06/17 17:21:18 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -46,10 +46,35 @@ struct sqlite3_mutex { #endif /* +** 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 +static int pthreadMutexHeld(sqlite3_mutex *p){ + return (p->nRef!=0 && pthread_equal(p->owner, pthread_self())); +} +static int pthreadMutexNotheld(sqlite3_mutex *p){ + return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0; +} +#endif + +/* ** Initialize and deinitialize the mutex subsystem. */ -int sqlite3_mutex_init(void){ return SQLITE_OK; } -int sqlite3_mutex_end(void){ return SQLITE_OK; } +static int pthreadMutexInit(void){ return SQLITE_OK; } +static int pthreadMutexEnd(void){ return SQLITE_OK; } /* ** The sqlite3_mutex_alloc() routine allocates a new @@ -92,7 +117,7 @@ int sqlite3_mutex_end(void){ return SQLITE_OK; } ** 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 *pthreadMutexAlloc(int iType){ static sqlite3_mutex staticMutexes[] = { SQLITE3_MUTEX_INITIALIZER, SQLITE3_MUTEX_INITIALIZER, @@ -147,13 +172,11 @@ sqlite3_mutex *sqlite3_mutex_alloc(int iType){ ** allocated mutex. SQLite is careful to deallocate every ** mutex that it allocates. */ -void sqlite3_mutex_free(sqlite3_mutex *p){ - if( p ){ - assert( p->nRef==0 ); - assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); - pthread_mutex_destroy(&p->mutex); - sqlite3_free(p); - } +static void pthreadMutexFree(sqlite3_mutex *p){ + assert( p->nRef==0 ); + assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + pthread_mutex_destroy(&p->mutex); + sqlite3_free(p); } /* @@ -167,9 +190,8 @@ void sqlite3_mutex_free(sqlite3_mutex *p){ ** 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){ - if( p==0 ) return; - assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); +static void pthreadMutexEnter(sqlite3_mutex *p){ + assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) ); #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX /* If recursive mutexes are not available, then we have to grow @@ -207,10 +229,9 @@ void sqlite3_mutex_enter(sqlite3_mutex *p){ } #endif } -int sqlite3_mutex_try(sqlite3_mutex *p){ +static int pthreadMutexTry(sqlite3_mutex *p){ int rc; - if( p==0 ) return SQLITE_OK; - assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) ); #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX /* If recursive mutexes are not available, then we have to grow @@ -263,8 +284,7 @@ int sqlite3_mutex_try(sqlite3_mutex *p){ ** 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){ - if( p==0 ) return; +static void pthreadMutexLeave(sqlite3_mutex *p){ assert( sqlite3_mutex_held(p) ); p->nRef--; assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); @@ -284,28 +304,21 @@ void sqlite3_mutex_leave(sqlite3_mutex *p){ #endif } -/* -** 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; +sqlite3_mutex_methods *sqlite3DefaultMutex(void){ + static sqlite3_mutex_methods sMutex = { + pthreadMutexInit, + pthreadMutexAlloc, + pthreadMutexFree, + pthreadMutexEnter, + pthreadMutexTry, + pthreadMutexLeave, + pthreadMutexEnd, + + pthreadMutexHeld, + pthreadMutexNotheld + }; + + return &sMutex; } -#endif + #endif /* SQLITE_MUTEX_PTHREAD */ diff --git a/src/mutex_w32.c b/src/mutex_w32.c index fcb468aec..fa3f86a08 100644 --- a/src/mutex_w32.c +++ b/src/mutex_w32.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains the C functions that implement mutexes for win32 ** -** $Id: mutex_w32.c,v 1.7 2008/06/13 18:24:27 drh Exp $ +** $Id: mutex_w32.c,v 1.8 2008/06/17 17:21:18 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -57,12 +57,23 @@ struct sqlite3_mutex { } #endif /* OS_WINCE */ +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use only inside assert() statements. +*/ +static int winMutexHeld(sqlite3_mutex *p){ + return p->nRef!=0 && p->owner==GetCurrentThreadId(); +} +static int winMutexNotheld(sqlite3_mutex *p){ + return p->nRef==0 || p->owner!=GetCurrentThreadId(); +} + /* ** Initialize and deinitialize the mutex subsystem. */ -int sqlite3_mutex_init(void){ return SQLITE_OK; } -int sqlite3_mutex_end(void){ return SQLITE_OK; } +static int winMutexInit(void){ return SQLITE_OK; } +static int winMutexEnd(void){ return SQLITE_OK; } /* ** The sqlite3_mutex_alloc() routine allocates a new @@ -103,7 +114,7 @@ int sqlite3_mutex_end(void){ return SQLITE_OK; } ** 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 *winMutexAlloc(int iType){ sqlite3_mutex *p; switch( iType ){ @@ -147,7 +158,7 @@ sqlite3_mutex *sqlite3_mutex_alloc(int iType){ ** allocated mutex. SQLite is careful to deallocate every ** mutex that it allocates. */ -void sqlite3_mutex_free(sqlite3_mutex *p){ +static void winMutexFree(sqlite3_mutex *p){ assert( p ); assert( p->nRef==0 ); assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); @@ -166,17 +177,15 @@ void sqlite3_mutex_free(sqlite3_mutex *p){ ** 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){ - if( p==0 ) return; - assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); +static void winMutexEnter(sqlite3_mutex *p){ + assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) ); EnterCriticalSection(&p->mutex); p->owner = GetCurrentThreadId(); p->nRef++; } -int sqlite3_mutex_try(sqlite3_mutex *p){ +static int winMutexTry(sqlite3_mutex *p){ int rc = SQLITE_BUSY; - if( p==0 ) return SQLITE_OK; - assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) ); /* ** The sqlite3_mutex_try() routine is very rarely used, and when it ** is used it is merely an optimization. So it is OK for it to always @@ -204,8 +213,7 @@ int sqlite3_mutex_try(sqlite3_mutex *p){ ** 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){ - if( p==0 ) return; +static void winMutexLeave(sqlite3_mutex *p){ assert( p->nRef>0 ); assert( p->owner==GetCurrentThreadId() ); p->nRef--; @@ -213,14 +221,21 @@ void sqlite3_mutex_leave(sqlite3_mutex *p){ 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(); +sqlite3_mutex_methods *sqlite3DefaultMutex(void){ + static sqlite3_mutex_methods sMutex = { + winMutexInit, + winMutexAlloc, + winMutexFree, + winMutexEnter, + winMutexTry, + winMutexLeave, + winMutexEnd, + + winMutexHeld, + winMutexNotheld + }; + + return &sMutex; } #endif /* SQLITE_MUTEX_W32 */ + diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 52e7f5537..592b1e174 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.329 2008/06/17 15:12:01 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.330 2008/06/17 17:21:18 danielk1977 Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -5784,6 +5784,20 @@ int sqlite3_mutex_try(sqlite3_mutex*); void sqlite3_mutex_leave(sqlite3_mutex*); int sqlite3_mutex_end(void); +typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; +struct sqlite3_mutex_methods { + int (*xMutexInit)(void); + sqlite3_mutex *(*xMutexAlloc)(int); + void (*xMutexFree)(sqlite3_mutex *); + void (*xMutexEnter)(sqlite3_mutex *); + int (*xMutexTry)(sqlite3_mutex *); + void (*xMutexLeave)(sqlite3_mutex *); + int (*xMutexEnd)(void); + int (*xMutexHeld)(sqlite3_mutex *); + int (*xMutexNotheld)(sqlite3_mutex *); +}; + + /* ** CAPI3REF: Mutex Verifcation Routines {F17080} ** diff --git a/src/sqliteInt.h b/src/sqliteInt.h index e0b9c4c05..8513074ba 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.711 2008/06/17 15:12:01 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.712 2008/06/17 17:21:18 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1739,6 +1739,7 @@ struct Sqlite3Config { int bCoreMutex; /* True to enable core mutexing */ int bFullMutex; /* True to enable full mutexing */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ + sqlite3_mutex_methods mutex; /* Low-level mutex interface */ void *pHeap; /* Heap storage space */ sqlite3_int64 nHeap; /* Size of pHeap[] */ int mnReq, mxReq; /* Min and max memory request sizes */ @@ -1797,6 +1798,8 @@ void *sqlite3PageMalloc(int); void sqlite3PageFree(void*); void sqlite3MemSetDefault(void); +sqlite3_mutex_methods *sqlite3DefaultMutex(void); + int sqlite3IsNaN(double); char *sqlite3MPrintf(sqlite3*,const char*, ...); |