/ Check-in [1668284d]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment: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)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1668284d151e78d16b0d83bf55dfd9d349a452a7
User & Date: drh 2007-08-25 14:39:46
Context
2007-08-25
14:49
Clarification in the documentation of the sqlite3_mutex_held() and sqlite3_mutex_notheld() interfaces. Make it clear that these routines are only for use inside assert(). (CVS 4298) check-in: a6bbf6ea user: drh tags: trunk
14:39
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) check-in: 1668284d user: drh tags: trunk
13:37
Update the rest of the malloc failure test scripts to use the new interface. (CVS 4296) check-in: b076e165 user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/mutex.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains the C functions that implement mutexes for
    13     13   ** use by the SQLite core.
    14     14   **
    15         -** $Id: mutex.c,v 1.10 2007/08/25 03:59:09 drh Exp $
           15  +** $Id: mutex.c,v 1.11 2007/08/25 14:39:46 drh Exp $
    16     16   */
    17     17   /*
    18     18   ** If SQLITE_MUTEX_APPDEF is defined, then this whole module is
    19     19   ** omitted and equivalent functionality must be provided by the
    20     20   ** application that links against the SQLite library.
    21     21   */
    22     22   #ifndef SQLITE_MUTEX_APPDEF
................................................................................
   204    204     return p==0 || p->cnt==0;
   205    205   }
   206    206   #endif /* SQLITE_MUTEX_NOOP_DEBUG */
   207    207   
   208    208   
   209    209   
   210    210   #ifdef SQLITE_MUTEX_PTHREAD
   211         -/**************** Non-recursive Pthread Mutex Implementation *****************
          211  +/******************** Pthread Mutex Implementation *********************
   212    212   **
   213    213   ** This implementation of mutexes is built using a version of pthreads that
   214         -** does not have native support for recursive mutexes.
          214  +** has native support for recursive mutexes.
   215    215   */
   216    216   #include <pthread.h>
   217    217   
   218    218   /*
   219    219   ** Each recursive mutex is an instance of the following structure.
   220    220   */
   221    221   struct sqlite3_mutex {
................................................................................
   270    270       { PTHREAD_MUTEX_INITIALIZER, },
   271    271       { PTHREAD_MUTEX_INITIALIZER, },
   272    272       { PTHREAD_MUTEX_INITIALIZER, },
   273    273       { PTHREAD_MUTEX_INITIALIZER, },
   274    274     };
   275    275     sqlite3_mutex *p;
   276    276     switch( iType ){
   277         -    case SQLITE_MUTEX_FAST:
   278    277       case SQLITE_MUTEX_RECURSIVE: {
          278  +      static pthread_mutex_t initMutex = PTHREAD_MUTEX_INITIALIZER;
          279  +      static int isInit = 0;
          280  +      static pthread_mutexattr_t recursiveAttr;
          281  +      if( !isInit ){
          282  +        pthread_mutex_lock(&initMutex);
          283  +        if( !isInit ){
          284  +          pthread_mutexattr_init(&recursiveAttr);
          285  +          pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
          286  +        }
          287  +        isInit = 1;
          288  +        pthread_mutex_unlock(&initMutex);
          289  +      }
          290  +      p = sqlite3MallocZero( sizeof(*p) );
          291  +      if( p ){
          292  +        p->id = iType;
          293  +        pthread_mutex_init(&p->mutex, &recursiveAttr);
          294  +      }
          295  +      break;
          296  +    }
          297  +    case SQLITE_MUTEX_FAST: {
   279    298         p = sqlite3MallocZero( sizeof(*p) );
   280    299         if( p ){
   281    300           p->id = iType;
   282    301           pthread_mutex_init(&p->mutex, 0);
   283    302         }
   284    303         break;
   285    304       }
................................................................................
   316    335   ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
   317    336   ** be entered multiple times by the same thread.  In such cases the,
   318    337   ** mutex must be exited an equal number of times before another thread
   319    338   ** can enter.  If the same thread tries to enter any other kind of mutex
   320    339   ** more than once, the behavior is undefined.
   321    340   */
   322    341   void sqlite3_mutex_enter(sqlite3_mutex *p){
   323         -  pthread_t self = pthread_self();
   324         -  if( p->nRef>0 && pthread_equal(p->owner, self) ){
   325         -    p->nRef++;
   326         -  }else{
   327         -    pthread_mutex_lock(&p->mutex);
   328         -    assert( p->nRef==0 );
   329         -    p->owner = self;
   330         -    p->nRef = 1;
   331         -  }
          342  +  assert( p );
          343  +  assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
          344  +  pthread_mutex_lock(&p->mutex);
          345  +  p->owner = pthread_self();
          346  +  p->nRef++;
   332    347   }
   333    348   int sqlite3_mutex_try(sqlite3_mutex *p){
   334         -  pthread_t self = pthread_self();
   335    349     int rc;
   336         -  if( p->nRef>0 && pthread_equal(p->owner, self) ){
          350  +  assert( p );
          351  +  assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
          352  +  if( pthread_mutex_trylock(&p->mutex)==0 ){
          353  +    p->owner = pthread_self();
   337    354       p->nRef++;
   338         -    rc = SQLITE_OK;
   339         -  }else if( pthread_mutex_lock(&p->mutex)==0 ){
   340         -    assert( p->nRef==0 );
   341         -    p->owner = self;
   342         -    p->nRef = 1;
   343    355       rc = SQLITE_OK;
   344    356     }else{
   345    357       rc = SQLITE_BUSY;
   346    358     }
   347    359     return rc;
   348    360   }
   349    361   
................................................................................
   350    362   /*
   351    363   ** The sqlite3_mutex_leave() routine exits a mutex that was
   352    364   ** previously entered by the same thread.  The behavior
   353    365   ** is undefined if the mutex is not currently entered or
   354    366   ** is not currently allocated.  SQLite will never do either.
   355    367   */
   356    368   void sqlite3_mutex_leave(sqlite3_mutex *p){
   357         -  assert( pthread_equal(p->owner, pthread_self()) );
   358         -  assert( p->nRef>0 );
          369  +  assert( p );
          370  +  assert( sqlite3_mutex_held(p) );
   359    371     p->nRef--;
   360         -  if( p->nRef==0 ){
   361         -    pthread_mutex_unlock(&p->mutex);
   362         -  }
          372  +  pthread_mutex_unlock(&p->mutex);
   363    373   }
   364    374   
   365    375   /*
   366    376   ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
   367    377   ** intended for use inside assert() statements.
   368    378   */
   369    379   int sqlite3_mutex_held(sqlite3_mutex *p){
................................................................................
   489    499   ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
   490    500   ** be entered multiple times by the same thread.  In such cases the,
   491    501   ** mutex must be exited an equal number of times before another thread
   492    502   ** can enter.  If the same thread tries to enter any other kind of mutex
   493    503   ** more than once, the behavior is undefined.
   494    504   */
   495    505   void sqlite3_mutex_enter(sqlite3_mutex *p){
          506  +  assert( p );
          507  +  assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
   496    508     EnterCriticalSection(&p->mutex);
   497    509     p->owner = GetCurrentThreadId(); 
   498    510     p->nRef++;
   499    511   }
   500    512   int sqlite3_mutex_try(sqlite3_mutex *p){
   501    513     int rc;
          514  +  assert( p );
          515  +  assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
   502    516     if( TryEnterCriticalSection(&p->mutex) ){
   503    517       p->owner = GetCurrentThreadId();
   504    518       p->nRef++;
   505    519       rc = SQLITE_OK;
   506    520     }else{
   507    521       rc = SQLITE_BUSY;
   508    522     }

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.599 2007/08/24 08:15:54 danielk1977 Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.600 2007/08/25 14:39:46 drh Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   #include "sqliteLimit.h"
    19     19   
           20  +#define _XOPEN_SOURCE 500  /* Needed to enable pthread recursive mutexes */
    20     21   
    21     22   #if defined(SQLITE_TCL) || defined(TCLSH)
    22     23   # include <tcl.h>
    23     24   #endif
    24     25   
    25     26   /*
    26     27   ** Many people are failing to set -DNDEBUG=1 when compiling SQLite.