diff options
-rw-r--r-- | Makefile.in | 14 | ||||
-rw-r--r-- | main.mk | 26 | ||||
-rw-r--r-- | manifest | 22 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/mutex.c | 471 | ||||
-rw-r--r-- | src/mutex.h | 82 | ||||
-rw-r--r-- | src/mutex_os2.c | 124 | ||||
-rw-r--r-- | src/mutex_unix.c | 205 | ||||
-rw-r--r-- | src/mutex_w32.c | 181 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 |
10 files changed, 651 insertions, 479 deletions
diff --git a/Makefile.in b/Makefile.in index 558e54322..6591af250 100644 --- a/Makefile.in +++ b/Makefile.in @@ -124,6 +124,7 @@ LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btmutex.lo btree.lo build.lo \ callback.lo complete.lo date.lo \ delete.lo expr.lo func.lo hash.lo journal.lo insert.lo loadext.lo \ main.lo malloc.lo mem1.lo mem2.lo mutex.lo \ + mutex_os2.lo mutex_unix.lo mutex_w32.lo \ opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \ pager.lo parse.lo pragma.lo prepare.lo printf.lo random.lo \ select.lo table.lo tokenize.lo trigger.lo update.lo \ @@ -159,6 +160,9 @@ SRC = \ $(TOP)/src/mem1.c \ $(TOP)/src/mem2.c \ $(TOP)/src/mutex.c \ + $(TOP)/src/mutex_os2.c \ + $(TOP)/src/mutex_unix.c \ + $(TOP)/src/mutex_w32.c \ $(TOP)/src/os.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ @@ -253,6 +257,7 @@ HDR = \ $(TOP)/src/btreeInt.h \ $(TOP)/src/hash.h \ $(TOP)/src/sqliteLimit.h \ + $(TOP)/src/mutex.h \ opcodes.h \ $(TOP)/src/os.h \ $(TOP)/src/os_common.h \ @@ -398,6 +403,15 @@ mem2.lo: $(TOP)/src/mem2.c $(HDR) mutex.lo: $(TOP)/src/mutex.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex.c +mutex_os2.lo: $(TOP)/src/mutex_os2.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_os2.c + +mutex_unix.lo: $(TOP)/src/mutex_unix.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_unix.c + +mutex_w32.lo: $(TOP)/src/mutex_w32.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_w32.c + pager.lo: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h $(LTCOMPILE) -c $(TOP)/src/pager.c @@ -58,7 +58,8 @@ TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src LIBOBJ+= alter.o analyze.o attach.o auth.o btmutex.o btree.o build.o \ callback.o complete.o date.o delete.o \ expr.o func.o hash.o insert.o journal.o loadext.o \ - main.o malloc.o mem1.o mem2.o mutex.o \ + main.o malloc.o mem1.o mem2.o mutex.o mutex_os2.o \ + mutex_unix.o mutex_w32.o \ opcodes.o os.o os_os2.o os_unix.o os_win.o \ pager.o parse.o pragma.o prepare.o printf.o random.o \ select.o table.o tclsqlite.o tokenize.o trigger.o \ @@ -112,6 +113,9 @@ SRC = \ $(TOP)/src/mem1.c \ $(TOP)/src/mem2.c \ $(TOP)/src/mutex.c \ + $(TOP)/src/mutex_os2.c \ + $(TOP)/src/mutex_unix.c \ + $(TOP)/src/mutex_w32.c \ $(TOP)/src/os.c \ $(TOP)/src/os_os2.c \ $(TOP)/src/os_unix.c \ @@ -195,15 +199,10 @@ SRC += \ # Source code to the test files. # TESTSRC = \ - $(TOP)/src/btmutex.c \ $(TOP)/src/btree.c \ $(TOP)/src/date.c \ $(TOP)/src/func.c \ $(TOP)/src/insert.c \ - $(TOP)/src/malloc.c \ - $(TOP)/src/mem1.c \ - $(TOP)/src/mem2.c \ - $(TOP)/src/mutex.c \ $(TOP)/src/os.c \ $(TOP)/src/os_os2.c \ $(TOP)/src/os_unix.c \ @@ -211,6 +210,7 @@ TESTSRC = \ $(TOP)/src/pager.c \ $(TOP)/src/pragma.c \ $(TOP)/src/printf.c \ + $(TOP)/src/select.c \ $(TOP)/src/test1.c \ $(TOP)/src/test2.c \ $(TOP)/src/test3.c \ @@ -241,16 +241,17 @@ TESTSRC += $(TOP)/ext/fts3/fts3_tokenizer.c # Header files used by all library source files. # HDR = \ - sqlite3.h \ $(TOP)/src/btree.h \ $(TOP)/src/btreeInt.h \ $(TOP)/src/hash.h \ - $(TOP)/src/sqliteLimit.h \ + $(TOP)/src/mutex.h \ opcodes.h \ $(TOP)/src/os.h \ $(TOP)/src/os_common.h \ + sqlite3.h \ $(TOP)/src/sqlite3ext.h \ $(TOP)/src/sqliteInt.h \ + $(TOP)/src/sqliteLimit.h \ $(TOP)/src/vdbe.h \ parse.h @@ -399,6 +400,15 @@ mem2.o: $(TOP)/src/mem2.c $(HDR) mutex.o: $(TOP)/src/mutex.c $(HDR) $(TCCX) -c $(TOP)/src/mutex.c +mutex_os2.o: $(TOP)/src/mutex_os2.c $(HDR) + $(TCCX) -c $(TOP)/src/mutex_os2.c + +mutex_unix.o: $(TOP)/src/mutex_unix.c $(HDR) + $(TCCX) -c $(TOP)/src/mutex_unix.c + +mutex_w32.o: $(TOP)/src/mutex_w32.c $(HDR) + $(TCCX) -c $(TOP)/src/mutex_w32.c + pager.o: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h $(TCCX) -c $(TOP)/src/pager.c @@ -1,6 +1,6 @@ -C Updates\sto\sthe\ssqlite3_open()\sdocumentation.\s\sMethod\sthe\smagic\n:memory:\sfilename.\s\sTicket\s#2591.\s(CVS\s4311) -D 2007-08-28T15:47:45 -F Makefile.in e8296e112b8942a96c0ed504398bd0d43e3c67ce +C Break\sup\sthe\smutex\simplementation\sinto\sseparate\ssource\sfiles,\sone\neach\sfor\sunix,\sw32,\sand\sos2.\s(CVS\s4312) +D 2007-08-28T16:34:43 +F Makefile.in bfcc303429a5d9dcd552d807ee016c77427418c3 F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 F VERSION 6200589421a0dfe968cd39c431fc62277b963540 @@ -63,7 +63,7 @@ F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33 F ext/icu/icu.c 61a345d8126686aa3487aa8d2d0f68abd655f7a4 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 56abb507100ed2d4261f6dd1653dec3cf4066387 -F main.mk 6b817f36cdfe3c1846cf6bac96afe8f73add5fe5 +F main.mk 6c8e14bbe8c52df32a5468e556df258ef563b4f2 F mkdll.sh 37fa8a7412e51b5ab2bc6d4276135f022a0feffb F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextw.sh 1a866b53637dab137191341cc875575a5ca110fb @@ -104,7 +104,11 @@ F src/malloc.c d4282f50964ab1ca31f504c97b7cf2fdb4d4195d F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217 F src/mem1.c afe2fbf6d7e8247c6c9f69c1481358b1cad60c08 F src/mem2.c 1a2ca756a285b5365d667841508cc1f98938b8d8 -F src/mutex.c adbad5e138e8caef8d3763280c75bfe2167812f6 +F src/mutex.c 40e5ba09d56863895882a0204d93832e9960ea78 +F src/mutex.h 4d3babe3a691533ac980967d394da512140b5143 +F src/mutex_os2.c d47e9bd495583dd31263d8fe55160a31eb600a3c +F src/mutex_unix.c 84ae0344b0bd6591e3bfea2cb6d375233d39f8a4 +F src/mutex_w32.c 8716478c5f1829b27fd2c9a0759230a9dc3aa9e3 F src/os.c a8ed3c495161475dbce255f7003144144fb425f1 F src/os.h 2bfbbad126a775e4d8c7d59eb4d9585a5fd7dfb5 F src/os_common.h 98862f120ca6bf7a48ce8b16f158b77d00bc9d2f @@ -128,7 +132,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c ac29402b538515fa4697282387be9c1205e6e9eb F src/sqlite.h.in 679cfc7927f843cd30a7b7a0fa17173752939a36 F src/sqlite3ext.h 9a26028378c288af500d8b94ed079666fed5806b -F src/sqliteInt.h e681df44a19ffb6750d129802f124132ae240c83 +F src/sqliteInt.h 8225c78e94177fa4f1052c4cf0f779838bf56c19 F src/sqliteLimit.h 1bcbbdfa856f8b71b561abb31edb864b0eca1d12 F src/table.c c725e47f6f3092b9a7b569fc58e408e2173ee008 F src/tclsqlite.c d76af53f45c9e9f7f7d39531fa4c7bee7d0adad6 @@ -563,7 +567,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P e7a98b48384ea581d98dad5118ee33468d526c62 -R 79b1204662164ac9dfde3b22f0e8e0d8 +P 5f55b2fc4ecdfc1bb68f479751b8642926fd8833 +R 51f416da38767e7822a0835f98d9ee97 U drh -Z 512659d0af1bbd911b2ca09d7e649b66 +Z 49f77ee210b93cd481f8532fcc9bb445 diff --git a/manifest.uuid b/manifest.uuid index db8cce754..771e6f537 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5f55b2fc4ecdfc1bb68f479751b8642926fd8833
\ No newline at end of file +fc5cd71aef5ac194f51d73350d773d532020967e
\ No newline at end of file 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) */ diff --git a/src/mutex.h b/src/mutex.h new file mode 100644 index 000000000..d5fa02237 --- /dev/null +++ b/src/mutex.h @@ -0,0 +1,82 @@ +/* +** 2007 August 28 +** +** 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 common header for all mutex implementations. +** The sqliteInt.h header #includes this file so that it is available +** to all source files. We break it out in an effort to keep the code +** better organized. +** +** NOTE: source files should *not* #include this header file directly. +** Source files should #include the sqliteInt.h file and let that file +** include this one indirectly. +** +** $Id: mutex.h,v 1.1 2007/08/28 16:34:43 drh Exp $ +*/ + + +#ifdef SQLITE_MUTEX_APPDEF +/* +** 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. +*/ +#else +/* +** 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. +** +** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix. +** +** SQLITE_MUTEX_WIN For multi-threaded applications on Win32. +** +** SQLITE_MUTEX_OS2 For multi-threaded applications on OS/2. +*/ +#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_PTHREADS +#endif +#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && OS_WIN +# undef SQLITE_MUTEX_NOOP +# define SQLITE_MUTEX_WIN +#endif +#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && OS_OS2 +# undef SQLITE_MUTEX_NOOP +# define SQLITE_MUTEX_OS2 +#endif + +#ifdef SQLITE_MUTEX_NOOP +/* +** If this is a no-op implementation, implement everything as macros. +*/ +#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) +#define sqlite3_mutex_free(X) +#define sqlite3_mutex_enter(X) +#define sqlite3_mutex_try(X) SQLITE_OK +#define sqlite3_mutex_leave(X) +#define sqlite3_mutex_held(X) 1 +#define sqlite3_mutex_notheld(X) 1 +#endif + +#endif /* SQLITE_MUTEX_APPDEF */ diff --git a/src/mutex_os2.c b/src/mutex_os2.c new file mode 100644 index 000000000..b598f5d90 --- /dev/null +++ b/src/mutex_os2.c @@ -0,0 +1,124 @@ +/* +** 2007 August 28 +** +** 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 OS/2 +** +** $Id: mutex_os2.c,v 1.1 2007/08/28 16:34:43 drh Exp $ +*/ +#include "sqliteInt.h" + + +/* +** The code in this file is only used if SQLITE_MUTEX_OS2 is defined. +** See the mutex.h file for details. +*/ +#ifdef SQLITE_MUTEX_OS2 + +/**** FIX ME: +***** This is currently a no-op implementation suitable for use +***** in single-threaded applications only. Somebody please replace +***** this with a real mutex implementation for OS/2. +****/ + +/* +** The mutex object +*/ +struct sqlite3_mutex { + int id; /* The mutex type */ + int cnt; /* Number of entries without a matching leave */ +}; + +/* +** 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[4]; + 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: { + assert( id-2 >= 0 ); + assert( id-2 < sizeof(aStatic)/sizeof(aStatic[0]) ); + pNew = &aStatic[id-2]; + 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->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); + p->cnt++; +} +int sqlite3_mutex_try(sqlite3_mutex *p){ + assert( p ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); + 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 ); + 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; +} +#endif /* SQLITE_MUTEX_OS2 */ diff --git a/src/mutex_unix.c b/src/mutex_unix.c new file mode 100644 index 000000000..287a173c5 --- /dev/null +++ b/src/mutex_unix.c @@ -0,0 +1,205 @@ +/* +** 2007 August 28 +** +** 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 pthreads +** +** $Id: mutex_unix.c,v 1.1 2007/08/28 16:34:43 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** The code in this file is only used if we are compiling threadsafe +** under unix with pthreads. +** +** Note that this implementation requires a version of pthreads that +** supports recursive mutexes. +*/ +#ifdef SQLITE_MUTEX_PTHREADS + +#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 */ diff --git a/src/mutex_w32.c b/src/mutex_w32.c new file mode 100644 index 000000000..e0fbe50df --- /dev/null +++ b/src/mutex_w32.c @@ -0,0 +1,181 @@ +/* +** 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 win32 +** +** $Id: mutex_w32.c,v 1.1 2007/08/28 16:34:43 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** The code in this file is only used if we are compiling multithreaded +** on a win32 system. +*/ +#ifdef SQLITE_MUTEX_WIN32 + +/* +** 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 */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index bc0e8aab1..ef69cb639 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.603 2007/08/28 02:27:52 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.604 2007/08/28 16:34:43 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -73,6 +73,7 @@ #include "sqlite3.h" #include "hash.h" #include "parse.h" +#include "mutex.h" #include <stdio.h> #include <stdlib.h> #include <string.h> |