Index: src/mutex.c ================================================================== --- src/mutex.c +++ src/mutex.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains the C functions that implement mutexes for ** use by the SQLite core. ** -** $Id: mutex.c,v 1.10 2007/08/25 03:59:09 drh Exp $ +** $Id: mutex.c,v 1.11 2007/08/25 14:39:46 drh Exp $ */ /* ** If SQLITE_MUTEX_APPDEF is defined, then this whole module is ** omitted and equivalent functionality must be provided by the ** application that links against the SQLite library. @@ -206,14 +206,14 @@ #endif /* SQLITE_MUTEX_NOOP_DEBUG */ #ifdef SQLITE_MUTEX_PTHREAD -/**************** Non-recursive Pthread Mutex Implementation ***************** +/******************** Pthread Mutex Implementation ********************* ** ** This implementation of mutexes is built using a version of pthreads that -** does not have native support for recursive mutexes. +** has native support for recursive mutexes. */ #include /* ** Each recursive mutex is an instance of the following structure. @@ -272,12 +272,31 @@ { PTHREAD_MUTEX_INITIALIZER, }, { PTHREAD_MUTEX_INITIALIZER, }, }; sqlite3_mutex *p; switch( iType ){ - case SQLITE_MUTEX_FAST: case SQLITE_MUTEX_RECURSIVE: { + static pthread_mutex_t initMutex = PTHREAD_MUTEX_INITIALIZER; + static int isInit = 0; + static pthread_mutexattr_t recursiveAttr; + if( !isInit ){ + pthread_mutex_lock(&initMutex); + if( !isInit ){ + pthread_mutexattr_init(&recursiveAttr); + pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE); + } + isInit = 1; + pthread_mutex_unlock(&initMutex); + } + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ + p->id = iType; + pthread_mutex_init(&p->mutex, &recursiveAttr); + } + break; + } + case SQLITE_MUTEX_FAST: { p = sqlite3MallocZero( sizeof(*p) ); if( p ){ p->id = iType; pthread_mutex_init(&p->mutex, 0); } @@ -318,30 +337,23 @@ ** 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){ - pthread_t self = pthread_self(); - if( p->nRef>0 && pthread_equal(p->owner, self) ){ - p->nRef++; - }else{ - pthread_mutex_lock(&p->mutex); - assert( p->nRef==0 ); - p->owner = self; - p->nRef = 1; - } + 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){ - pthread_t self = pthread_self(); int rc; - if( p->nRef>0 && pthread_equal(p->owner, self) ){ + 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 if( pthread_mutex_lock(&p->mutex)==0 ){ - assert( p->nRef==0 ); - p->owner = self; - p->nRef = 1; rc = SQLITE_OK; }else{ rc = SQLITE_BUSY; } return rc; @@ -352,16 +364,14 @@ ** 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( pthread_equal(p->owner, pthread_self()) ); - assert( p->nRef>0 ); + assert( p ); + assert( sqlite3_mutex_held(p) ); p->nRef--; - if( p->nRef==0 ){ - pthread_mutex_unlock(&p->mutex); - } + pthread_mutex_unlock(&p->mutex); } /* ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use inside assert() statements. @@ -491,16 +501,20 @@ ** 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{ Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -9,16 +9,17 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.599 2007/08/24 08:15:54 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.600 2007/08/25 14:39:46 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ #include "sqliteLimit.h" +#define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */ #if defined(SQLITE_TCL) || defined(TCLSH) # include #endif