]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Change the design of the mutex interface to allow for
authordrh <drh@noemail.net>
Thu, 16 Aug 2007 19:40:16 +0000 (19:40 +0000)
committerdrh <drh@noemail.net>
Thu, 16 Aug 2007 19:40:16 +0000 (19:40 +0000)
both "fast" and "recursive" mutexes. (CVS 4238)

FossilOrigin-Name: 160593dcc5690af715b775c81137c6e09cca6454

manifest
manifest.uuid
src/mem1.c
src/mem2.c
src/mutex.c
src/sqlite.h.in

index f36c30f9cde3d4b3644b4dfdba2042a7f1ebbc4b..b1b531801dd4524b48c47c2658bff6e9e5413d3d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Remove\sthe\sthread\sspecific\sdata\ssubsystem\sfrom\sthe\sunix\sbuild.\s\sRemove\nlegacy\scruft\sfrom\ssqliteInt.h.\s\sUse\sthe\snew\smutex\ssubsystem\sin\sthe\sPRNG.\s(CVS\s4237)
-D 2007-08-16T13:01:45
+C Change\sthe\sdesign\sof\sthe\s\smutex\sinterface\sto\sallow\sfor\nboth\s"fast"\sand\s"recursive"\smutexes.\s(CVS\s4238)
+D 2007-08-16T19:40:17
 F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe
 F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -88,9 +88,9 @@ F src/loadext.c aa1c6e584d39cc241226ec9390387bc2d4a23e8f
 F src/main.c 996df547489d4826f70629b16623d7408f55ecd7
 F src/malloc.c 613c65f12ff0ee4edd017aa458209ab7a23cd7b1
 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
-F src/mem1.c 08c4ee16393835b2d24ad39ce7b64c0f8c5b1df7
-F src/mem2.c d0ba3b23da2e95bced1818ade8a8a2dc9526111c
-F src/mutex.c b4f963ebdcb0622b3026937826afefd8a05884e1
+F src/mem1.c 2c6a6e3b2c9c7cb8d398a8468095032407c3e0b7
+F src/mem2.c 661ca7ebf6e4b964fecc95d24e8c89dbcfc9dfea
+F src/mutex.c 679d5d9c99bd302c0c43ee3eba61348c44aea366
 F src/os.c e2faefbe0f5a8ca5e3b1c49ee1b5c6cfa0f0e279
 F src/os.h 8eff07babf74e5bc3f895f8a6c7c294dad5ff997
 F src/os_common.h a5c446d3b93f09f369d13bf217de4bed3437dd1c
@@ -112,7 +112,7 @@ F src/random.c 6119474a6f6917f708c1dee25b9a8e519a620e88
 F src/select.c 98c367bce3f38c5adfcc97de9ab5c79b0e5dc2b2
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c ac29402b538515fa4697282387be9c1205e6e9eb
-F src/sqlite.h.in 1fb6748ebd4c36b8476c03791009585fd5cfcf3b
+F src/sqlite.h.in 8efd7d5aca057a793d221973da1f22a22e69f4db
 F src/sqlite3ext.h 647a6b8a8f76ff6c9611e4a071531d8e63ff2d6b
 F src/sqliteInt.h fa9baff32aef7ca1ecebcd014b3bd75c981829d0
 F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa
@@ -529,7 +529,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P ba80ee59a72afe36817997de705ef81d876b6f35
-R 4dbfd96f907def879d1b3bfd1f2c5bd5
+P 3d60c14a32955b69e714a73372924d421899f83b
+R 79bf1accc56116075f09cd253592694c
 U drh
-Z 6248f8cb69e3663b94e130d7ac9b903a
+Z e40cc1b0395242393945aa35a1600f4d
index 7c4e7ae2a65f1ccf8274a53f9268050f609149dd..fc8a7b88057436a81530435f736d3d6c8ecb4af1 100644 (file)
@@ -1 +1 @@
-3d60c14a32955b69e714a73372924d421899f83b
\ No newline at end of file
+160593dcc5690af715b775c81137c6e09cca6454
\ No newline at end of file
index 5767d8424af79c714ad1048f3e6c12463e3a4c24..4fc77b04fec718a0c4f925a04b7c8f4180849a29 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains the C functions that implement a memory
 ** allocation subsystem for use by SQLite.  
 **
-** $Id: mem1.c,v 1.4 2007/08/16 13:01:45 drh Exp $
+** $Id: mem1.c,v 1.5 2007/08/16 19:40:17 drh Exp $
 */
 
 /*
@@ -81,9 +81,9 @@ static struct {
 sqlite3_uint64 sqlite3_memory_used(void){
   sqlite3_uint64 n;
   if( mem.mutex==0 ){
-    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_MEM);
+    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
   }
-  sqlite3_mutex_enter(mem.mutex, 1);
+  sqlite3_mutex_enter(mem.mutex);
   n = mem.nowUsed;
   sqlite3_mutex_leave(mem.mutex);  
   return n;
@@ -97,9 +97,9 @@ sqlite3_uint64 sqlite3_memory_used(void){
 sqlite3_uint64 sqlite3_memory_highwater(int resetFlag){
   sqlite3_uint64 n;
   if( mem.mutex==0 ){
-    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_MEM);
+    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
   }
-  sqlite3_mutex_enter(mem.mutex, 1);
+  sqlite3_mutex_enter(mem.mutex);
   n = mem.mxUsed;
   if( resetFlag ){
     mem.mxUsed = mem.nowUsed;
@@ -117,9 +117,9 @@ int sqlite3_memory_alarm(
   sqlite3_uint64 iThreshold
 ){
   if( mem.mutex==0 ){
-    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_MEM);
+    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
   }
-  sqlite3_mutex_enter(mem.mutex, 1);
+  sqlite3_mutex_enter(mem.mutex);
   mem.alarmCallback = xCallback;
   mem.alarmArg = pArg;
   mem.alarmThreshold = iThreshold;
@@ -131,9 +131,17 @@ int sqlite3_memory_alarm(
 ** Trigger the alarm 
 */
 static void sqlite3MemsysAlarm(unsigned nByte){
+  void (*xCallback)(void*,sqlite3_uint64,unsigned);
+  sqlite3_uint64 nowUsed;
+  void *pArg;
   if( mem.alarmCallback==0 || mem.alarmBusy  ) return;
   mem.alarmBusy = 1;
-  mem.alarmCallback(mem.alarmArg, mem.nowUsed, nByte);
+  xCallback = mem.alarmCallback;
+  nowUsed = mem.nowUsed;
+  pArg = mem.alarmArg;
+  sqlite3_mutex_leave(mem.mutex);
+  xCallback(pArg, nowUsed, nByte);
+  sqlite3_mutex_enter(mem.mutex);
   mem.alarmBusy = 0;
 }
 
@@ -143,9 +151,9 @@ static void sqlite3MemsysAlarm(unsigned nByte){
 void *sqlite3_malloc(unsigned int nBytes){
   sqlite3_uint64 *p;
   if( mem.mutex==0 ){
-    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_MEM);
+    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
   }
-  sqlite3_mutex_enter(mem.mutex, 1);
+  sqlite3_mutex_enter(mem.mutex);
   if( mem.nowUsed+nBytes>=mem.alarmThreshold ){
     sqlite3MemsysAlarm(nBytes);
   }
@@ -179,7 +187,7 @@ void sqlite3_free(void *pPrior){
   p = pPrior;
   p--;
   nByte = (unsigned int)*p;
-  sqlite3_mutex_enter(mem.mutex, 1);
+  sqlite3_mutex_enter(mem.mutex);
   mem.nowUsed -= nByte;
   free(p);
   sqlite3_mutex_leave(mem.mutex);  
@@ -202,7 +210,7 @@ void *sqlite3_realloc(void *pPrior, unsigned int nBytes){
   p--;
   nOld = (unsigned int)p[0];
   assert( mem.mutex!=0 );
-  sqlite3_mutex_enter(mem.mutex, 1);
+  sqlite3_mutex_enter(mem.mutex);
   if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){
     sqlite3MemsysAlarm(nBytes-nOld);
   }
index 5135096b9615fae43fe3a0144444d029c31c53fc..f9cd933b5a25d76c3973fe9da7f0cbcadc6879c5 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains the C functions that implement a memory
 ** allocation subsystem for use by SQLite.  
 **
-** $Id: mem2.c,v 1.3 2007/08/15 20:41:29 drh Exp $
+** $Id: mem2.c,v 1.4 2007/08/16 19:40:17 drh Exp $
 */
 
 /*
@@ -147,9 +147,9 @@ static struct {
 sqlite3_uint64 sqlite3_memory_used(void){
   sqlite3_uint64 n;
   if( mem.mutex==0 ){
-    mem.mutex = sqlite3_mutex_alloc(1);
+    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
   }
-  sqlite3_mutex_enter(mem.mutex, 1);
+  sqlite3_mutex_enter(mem.mutex);
   n = mem.nowUsed;
   sqlite3_mutex_leave(mem.mutex);  
   return n;
@@ -163,9 +163,9 @@ sqlite3_uint64 sqlite3_memory_used(void){
 sqlite3_uint64 sqlite3_memory_highwater(int resetFlag){
   sqlite3_uint64 n;
   if( mem.mutex==0 ){
-    mem.mutex = sqlite3_mutex_alloc(1);
+    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
   }
-  sqlite3_mutex_enter(mem.mutex, 1);
+  sqlite3_mutex_enter(mem.mutex);
   n = mem.mxUsed;
   if( resetFlag ){
     mem.mxUsed = mem.nowUsed;
@@ -183,9 +183,9 @@ int sqlite3_memory_alarm(
   sqlite3_uint64 iThreshold
 ){
   if( mem.mutex==0 ){
-    mem.mutex = sqlite3_mutex_alloc(1);
+    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
   }
-  sqlite3_mutex_enter(mem.mutex, 1);
+  sqlite3_mutex_enter(mem.mutex);
   mem.alarmCallback = xCallback;
   mem.alarmArg = pArg;
   mem.alarmThreshold = iThreshold;
@@ -197,9 +197,17 @@ int sqlite3_memory_alarm(
 ** Trigger the alarm 
 */
 static void sqlite3MemsysAlarm(unsigned nByte){
+  void (*xCallback)(void*,sqlite3_uint64,unsigned);
+  sqlite3_uint64 nowUsed;
+  void *pArg;
   if( mem.alarmCallback==0 || mem.alarmBusy  ) return;
   mem.alarmBusy = 1;
-  mem.alarmCallback(mem.alarmArg, mem.nowUsed, nByte);
+  xCallback = mem.alarmCallback;
+  nowUsed = mem.nowUsed;
+  pArg = mem.alarmArg;
+  sqlite3_mutex_leave(mem.mutex);
+  xCallback(pArg, nowUsed, nByte);
+  sqlite3_mutex_enter(mem.mutex);
   mem.alarmBusy = 0;
 }
 
@@ -243,9 +251,9 @@ void *sqlite3_malloc(unsigned int nByte){
   unsigned int totalSize;
 
   if( mem.mutex==0 ){
-    mem.mutex = sqlite3_mutex_alloc(1);
+    mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM);
   }
-  sqlite3_mutex_enter(mem.mutex, 1);
+  sqlite3_mutex_enter(mem.mutex);
   if( mem.nowUsed+nByte>=mem.alarmThreshold ){
     sqlite3MemsysAlarm(nByte);
   }
@@ -318,7 +326,7 @@ void sqlite3_free(void *pPrior){
   pHdr = sqlite3MemsysGetHeader(pPrior);
   pBt = (void**)pHdr;
   pBt -= pHdr->nBacktraceSlots;
-  sqlite3_mutex_enter(mem.mutex, 1);
+  sqlite3_mutex_enter(mem.mutex);
   mem.nowUsed -= pHdr->iSize;
   if( pHdr->pPrev ){
     assert( pHdr->pPrev->pNext==pHdr );
index f347de4f4887d4112a3192d83681e1a5f1ab0e68..13e15b5c7b789c59bfe8186dcb42c1ef1734cc10 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains the C functions that implement mutexes for
 ** use by the SQLite core.
 **
-** $Id: mutex.c,v 1.2 2007/08/16 10:09:03 danielk1977 Exp $
+** $Id: mutex.c,v 1.3 2007/08/16 19:40:17 drh Exp $
 */
 
 /*
 /*
 ** 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 usually zero, which causes
-** any space required for the mutex to be obtained from
-** sqlite3_malloc().  However if the argument is a positive
-** integer less than SQLITE_NUM_STATIC_MUTEX, then a pointer
-** to a static mutex is returned.  There are a finite number
-** of static mutexes.  Static mutexes should not be passed
-** to sqlite3_mutex_free().  The allocation of a static
-** mutex cannot fail.
+** that means that a mutex could not be allocated. 
 */
 sqlite3_mutex *sqlite3_mutex_alloc(int idNotUsed){
   return (sqlite3_mutex*)sqlite3_mutex_alloc;
 }
 
 /*
-** This routine deallocates a previously
-** allocated mutex.  SQLite is careful to deallocate every
-** mutex that it allocates.
+** This routine deallocates a previously allocated mutex.
 */
 void sqlite3_mutex_free(sqlite3_mutex *pNotUsed){}
 
 /*
-** The sqlite3_mutex_enter() routine attempts to enter a
-** mutex.  If another thread is already within the mutex,
-** sqlite3_mutex_enter() will return SQLITE_BUSY if blockFlag
-** is zero, or it will block and wait for the other thread to
-** exit if blockFlag is non-zero.  Mutexes are recursive.  The
-** same thread can enter a single mutex multiple times.  Each
-** entrance must be matched with a corresponding exit before
-** another thread is able to enter the mutex.
+** 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.
 */
-int sqlite3_mutex_enter(sqlite3_mutex *pNotUsed, int blockFlag){
-  return SQLITE_OK;
-}
+void sqlite3_mutex_enter(sqlite3_mutex *pNotUsed){}
+int sqlite3_mutex_try(sqlite3_mutex *pNotUsed){ return SQLITE_OK; }
 
 /*
 ** The sqlite3_mutex_exit() routine exits a mutex that was
@@ -80,20 +69,7 @@ int sqlite3_mutex_enter(sqlite3_mutex *pNotUsed, int blockFlag){
 ** 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){
-  return;
-}
-
-/*
-** The sqlite3_mutex_serialize() routine is used to serialize 
-** execution of a subroutine.  The subroutine given in the argument
-** is invoked.  But only one thread at a time is allowed to be
-** running a subroutine using sqlite3_mutex_serialize().
-*/
-int sqlite3_mutex_serialize(void (*xCallback)(void*), void *pArg){
-  xCallback(pArg);
-  return SQLITE_OK;
-}
+void sqlite3_mutex_leave(sqlite3_mutex *pNotUsed){}
 
 #if 0
 /**************** Non-recursive Pthread Mutex Implementation *****************
@@ -106,6 +82,7 @@ int sqlite3_mutex_serialize(void (*xCallback)(void*), void *pArg){
 ** Each recursive mutex is an instance of the following structure.
 */
 struct RMutex {
+  int recursiveMagic;         /* Magic number identifying this as recursive */
   int nRef;                   /* Number of entrances */
   pthread_mutex_t auxMutex;   /* Mutex controlling access to nRef and owner */
   pthread_mutex_t mainMutex;  /* Mutex controlling the lock */
@@ -113,98 +90,185 @@ struct RMutex {
 };
 
 /*
-** Static mutexes
+** Each fast mutex is an instance of the following structure
 */
-static struct RMutex rmutexes[] = {
-  { 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, },
-  { 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, },
-  { 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, },
+struct FMutex {
+  int fastMagic;          /* Identifies this as a fast mutex */
+  pthread_mutex_t mutex;  /* The actual underlying mutex */
 };
 
 /*
-** A mutex used for serialization.
+** Either of the above
+*/
+union AnyMutex {
+  struct RMutex r;
+  struct FMutex f;
+};
+
+/*
+** Magic numbers
+*/
+#define SQLITE_MTX_RECURSIVE   0x4ED886ED
+#define SQLITE_MTX_STATIC      0x56FCE1B4
+#define SQLITE_MTX_FAST        0x245BFD4F
+
+/*
+** Static mutexes
 */
-static RMutex serialMutex =
-   {0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, };
 
 /*
 ** 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 usually zero, which causes
-** any space required for the mutex to be obtained from
-** sqlite3_malloc().  However if the argument is a positive
-** integer less than SQLITE_NUM_STATIC_MUTEX, then a pointer
-** to a static mutex is returned.  There are a finite number
-** of static mutexes.  Static mutexes should not be passed
-** to sqlite3_mutex_free().  The allocation of a static
-** mutex cannot fail.
-*/
-sqlite3_mutex *sqlite3_mutex_alloc(int id){
-  struct RMutex *p;
-  if( id>0 ){
-    if( id>sizeof(rmutexes)/sizeof(rmutexes[0]) ){
-      p = 0;
-    }else{
-      p = &rmutexes[id-1];
+** 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){
+  static struct FMutex staticMutexes[] = {
+    { SQLITE_MTX_STATIC, PTHREAD_MUTEX_INITIALIZER },
+    { SQLITE_MTX_STATIC, PTHREAD_MUTEX_INITIALIZER },
+    { SQLITE_MTX_STATIC, PTHREAD_MUTEX_INITIALIZER },
+  };
+  sqlite3_mutex *p;
+  switch( iType ){
+    case SQLITE_MUTEX_FAST: {
+      struct FMutex *px = sqlite3_malloc( sizeof(*px) );
+      if( px ){
+        px->fastMagic = SQLITE_MTX_FAST;
+        pthread_mutex_init(&px->mutex, 0);
+      }
+      p = (sqlite3_mutex*)px;
+      break;
     }
-  }else{
-    p = sqlite3_malloc( sizeof(*p) );
-    if( p ){
-      p->nRef = 0;
-      pthread_mutex_init(&p->mutex, 0);
+    case SQLITE_MUTEX_RECURSIVE: {
+      struct RMutex *px = sqlite3_malloc( sizeof(*px) );
+      if( px ){
+        px->recursiveMagic = SQLITE_MTX_RECURSIVE;
+        pthread_mutex_init(&px->auxMutex, 0);
+        pthread_mutex_init(&px->mainMutex, 0);
+        px->nRef = 0;
+      }
+      p = (sqlite3_mutex*)px;
+      break;
+    }
+    default: {
+      p = &staticMutexes[iType-2];
+      break;
     }
   }
-  return (sqlite3_mutex*)p;
+  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 *pMutex){
-  struct RMutex *p = (struct RMutex*)pMutex;
-  assert( p->nRef==0 );
-  pthread_mutex_destroy(&p->mutex);
-  sqlite3_free(p);
+  int iType = *(int*)pMutex;
+  if( iType==SQLITE_MTX_FAST ){
+    struct FMutex *p = (struct FMutex*)pMutex;
+    pthread_mutex_destroy(&p->mutex);
+    sqlite3_free(p);
+  }else if( iType==SQLITE_MTX_RECURSIVE ){
+    struct RMutex *p = (struct RMutex*)pMutex;
+    pthread_mutex_destroy(&p->auxMutex);
+    pthread_mutex_destroy(&p->mainMutex);
+    sqlite3_free(p);
+  }
 }
 
 /*
-** The sqlite3_mutex_enter() routine attempts to enter a
-** mutex.  If another thread is already within the mutex,
-** sqlite3_mutex_enter() will return SQLITE_BUSY if blockFlag
-** is zero, or it will block and wait for the other thread to
-** exit if blockFlag is non-zero.  Mutexes are recursive.  The
-** same thread can enter a single mutex multiple times.  Each
-** entrance must be matched with a corresponding exit before
-** another thread is able to enter the mutex.
+** 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.
 */
-int sqlite3_mutex_enter(sqlite3_mutex *pMutex, int blockFlag){
-  struct RMutex *p = (struct RMutex*)pMutex;
-  while(1){
+void sqlite3_mutex_enter(sqlite3_mutex *pMutex){
+  if( SQLITE_MTX_FAST == *(int*)pMutex ){
+    struct FMutex *p = (struct FMutex*)pMutex;
+    pthread_mutex_lock(&p->mutex);
+  }else{
+    struct RMutex *p = (struct RMutex*)pMutex;
     pthread_mutex_lock(&p->auxMutex);
     if( p->nRef==0 ){
       p->nRef++;
       p->owner = pthread_self();
       pthread_mutex_lock(&p->mainMutex);
       pthread_mutex_unlock(&p->auxMutex);
-      return SQLITE_OK;
     }else if( pthread_equal(p->owner, pthread_self()) ){
       p->nRef++;
       pthread_mutex_unlock(&p->auxMutex);
-      return SQLITE_OK;
-    }else if( !blockFlag ){
-      pthread_mutex_unlock(&p->auxMutex);
+    }else{
+      while( p->nRef ){
+        pthread_mutex_unlock(&p->auxMutex);
+        pthread_mutex_lock(&p->mainMutex);
+        pthread_mutex_unlock(&p->mainMutex);
+      }
+    }
+  }
+}
+int sqlite3_mutex_try(sqlite3_mutex *pMutex){
+  if( SQLITE_MTX_FAST == *(int*)pMutex ){
+    struct FMutex *p = (struct FMutex*)pMutex;
+    if( pthread_mutex_trylock(&p->mutex) ){
       return SQLITE_BUSY;
+    }
+  }else{
+    struct RMutex *p = (struct RMutex*)pMutex;
+    pthread_mutex_lock(&p->auxMutex);
+    if( p->nRef==0 ){
+      p->nRef++;
+      p->owner = pthread_self();
+      pthread_mutex_lock(&p->mainMutex);
+      pthread_mutex_unlock(&p->auxMutex);
+    }else if( pthread_equal(p->owner, pthread_self()) ){
+      p->nRef++;
+      pthread_mutex_unlock(&p->auxMutex);
     }else{
       pthread_mutex_unlock(&p->auxMutex);
-      pthread_mutex_lock(&p->mainMutex);
-      pthread_mutex_unlock(&p->mainMutex);
+      return SQLITE_BUSY;
     }
   }
-  /* NOTREACHED */
+  return SQLITE_OK;
 }
 
 /*
@@ -214,25 +278,18 @@ int sqlite3_mutex_enter(sqlite3_mutex *pMutex, int blockFlag){
 ** is not currently allocated.  SQLite will never do either.
 */
 void sqlite3_mutex_leave(sqlite3_mutex *pMutex){
-  struct RMutex *p = (struct RMutex*)pMutex;
-  pthread_mutex_lock(&p->auxMutex);
-  p->nRef--;
-  if( p->nRef<=0 ){
-    pthread_mutex_unlock(&p->mainMutex);
+  if( SQLITE_MTX_FAST == *(int*)pMutex ){
+    struct FMutex *p = (struct FMutex*)pMutex;
+    pthread_mutex_unlock(&p->mutex);
+  }else{
+    struct RMutex *p = (struct RMutex*)pMutex;
+    pthread_mutex_lock(&p->auxMutex);
+    p->nRef--;
+    if( p->nRef<=0 ){
+      pthread_mutex_unlock(&p->mainMutex);
+    }
+    pthread_mutex_unlock(&p->auxMutex);
   }
-  pthread_mutex_unlock(&p->auxMutex);
-}
-
-/*
-** The sqlite3_mutex_serialize() routine is used to serialize 
-** execution of a subroutine.  The subroutine given in the argument
-** is invoked.  But only one thread at a time is allowed to be
-** running a subroutine using sqlite3_mutex_serialize().
-*/
-int sqlite3_mutex_serialize(void (*xCallback)(void*), void *pArg){
-  sqlite3_mutex_enter(&serialMutex, 1);
-  xCallback(pArg);
-  sqlite3_mutex_leave(&serialMutex);
 }
 #endif /* non-recursive pthreads */
 
index 4789cc6697144b8a23f0cc14b55fc995b2f3f8a7..872a0f26e7faf969ad526938730918aec6dabe9c 100644 (file)
@@ -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.225 2007/08/16 13:01:45 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.226 2007/08/16 19:40:17 drh Exp $
 */
 #ifndef _SQLITE3_H_
 #define _SQLITE3_H_
@@ -508,6 +508,8 @@ struct sqlite3_io_methods {
 ** abstract type for a mutex object.  The SQLite core never looks
 ** at the internal representation of an [sqlite3_mutex].  It only
 ** deals with pointers to the [sqlite3_mutex] object.
+**
+** Mutexes are created using [sqlite3_mutex_alloc()].
 */
 typedef struct sqlite3_mutex sqlite3_mutex;
 
@@ -519,19 +521,24 @@ typedef struct sqlite3_mutex sqlite3_mutex;
 ** in the name of the object stands for "virtual file system".
 **
 ** The iVersion field is initially 1 but may be larger for future
-** versions.  szOsFile is the size of the subclassed sqlite3_file
+** versions of SQLite.  Additional fields may be appended to this
+** object when the iVersion value is increased.
+**
+** The szOsFile field is the size of the subclassed sqlite3_file
 ** structure used by this VFS.  mxPathname is the maximum length of
 ** a pathname in this VFS.
 **
 ** The nRef field is incremented and decremented by SQLite to keep
 ** count of the number of users of the VFS.  This field and
 ** vfsMutex, pNext, and pPrev are the only fields in the sqlite3_vfs 
-** structure that SQLite will ever modify.  These fields are modified 
-** within an sqlite3_mutex_serialize() call so that updates are threadsafe.
+** structure that SQLite will ever modify.  SQLite will only access
+** or modify these fields while holding a particular static mutex.
+** The application should never modify any fields of the sqlite3_vfs
+** object once the object has been registered.
 ** 
 ** The sqlite3_vfs.vfsMutex is a mutex used by the OS interface.
 ** It should initially be NULL.  SQLite will initialize this field
-** using sqlite3_mutex_allocate() upon first use of the adaptor
+** using sqlite3_mutex_alloc() upon first use of the adaptor
 ** by sqlite3_open_v2() and will deallocate the mutex when the
 ** last user closes.  In other words, vfsMutex will be allocated
 ** when nRef transitions from 0 to 1 and will be deallocated when
@@ -3190,43 +3197,72 @@ int sqlite3_unregister_vfs(sqlite3_vfs*);
 ** 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 usually zero, which causes
-** any space required for the mutex to be obtained from
-** sqlite3_malloc().  However if the argument is a positive
-** integer less than or equal to SQLITE_MUTEX_STATIC_MAX, then a pointer
-** to a static mutex is returned.  There are a finite number
-** of static mutexes.  Static mutexes should not be passed
-** to sqlite3_mutex_free().  Static mutexes are used internally
-** by the SQLite core and should not be used by the application.
+** 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_PRNG
+** </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.
 **
 ** The sqlite3_mutex_free() routine deallocates a previously
-** allocated mutex.  SQLite is careful to deallocate every
-** mutex that it allocates.
-**
-** The sqlite3_mutex_enter() routine attempts to enter a
-** mutex.  If another thread is already within the mutex,
-** sqlite3_mutex_enter() will return SQLITE_BUSY if blockFlag
-** is zero, or it will block and wait for the other thread to
-** exit if blockFlag is non-zero.  Mutexes are recursive.  The
-** same thread can enter a single mutex multiple times.  Each
-** entrance must be matched with a corresponding exit before
-** another thread is able to enter the mutex.
+** allocated dynamic mutex.  SQLite is careful to deallocate every
+** dynamic mutex that it allocates.  The dynamic mutexes must not be in 
+** use when they are deallocated.  Static mutexes do not need to be
+** deallocated and SQLite never bothers to do so.
+**
+** 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.   SQLite will never exhibit
+** such behavior in its own use of mutexes.
 **
 ** The sqlite3_mutex_exit() 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.
-**
-** The sqlite3_mutex_serialize() routine is used to serialize 
-** a subroutine.  The subroutine given in the argument is invoked
-** while holding a static mutex.  This ensures that no other
-** thread is running this same subroutine at the same time.
 */
 sqlite3_mutex *sqlite3_mutex_alloc(int);
 void sqlite3_mutex_free(sqlite3_mutex*);
-int sqlite3_mutex_enter(sqlite3_mutex*, int blockFlag);
+void sqlite3_mutex_enter(sqlite3_mutex*);
+int sqlite3_mutex_try(sqlite3_mutex*);
 void sqlite3_mutex_leave(sqlite3_mutex*);
-int sqlite3_mutex_serialize(void(*)(void*), void*);
+#define SQLITE_MUTEX_FAST             0
+#define SQLITE_MUTEX_RECURSIVE        1
+#define SQLITE_MUTEX_STATIC_MASTER    2
+#define SQLITE_MUTEX_STATIC_MEM       3
+#define SQLITE_MUTEX_STATIC_PRNG      4
 
 
 /*