Use recursive mutexes in pthreads. If the pthreads implementation does not
support recursive mutexes, then you cannot compile SQLite with
SQLITE_THREADSAFE=1. Ticket #2588. (CVS 4297)
FossilOrigin-Name: 1668284d151e78d16b0d83bf55dfd9d349a452a7
diff --git a/src/mutex.c b/src/mutex.c
index 7bf6694..731469a 100644
--- a/src/mutex.c
+++ b/src/mutex.c
@@ -12,7 +12,7 @@
** 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
@@ -208,10 +208,10 @@
#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 <pthread.h>
@@ -274,8 +274,27 @@
};
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;
@@ -320,27 +339,20 @@
** 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;
}
@@ -354,12 +366,10 @@
** 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);
}
/*
@@ -493,12 +503,16 @@
** 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++;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 1719199..7e0c59f 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,12 +11,13 @@
*************************************************************************
** 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 <tcl.h>