/ 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 Unified Diffs Show Whitespace Changes Patch

Changes to src/mutex.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
...
270
271
272
273
274
275
276
277



















278
279
280
281
282
283
284
285
...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340


341
342
343
344
345
346
347
348
349
...
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
...
489
490
491
492
493
494
495


496
497
498
499
500
501


502
503
504
505
506
507
508
**    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
** use by the SQLite core.
**
** $Id: mutex.c,v 1.10 2007/08/25 03:59:09 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.
*/
#ifndef SQLITE_MUTEX_APPDEF
................................................................................
  return p==0 || p->cnt==0;
}
#endif /* SQLITE_MUTEX_NOOP_DEBUG */



#ifdef SQLITE_MUTEX_PTHREAD
/**************** Non-recursive Pthread Mutex Implementation *****************
**
** This implementation of mutexes is built using a version of pthreads that
** does not have native support for recursive mutexes.
*/
#include <pthread.h>

/*
** Each recursive mutex is an instance of the following structure.
*/
struct sqlite3_mutex {
................................................................................
    { PTHREAD_MUTEX_INITIALIZER, },
    { PTHREAD_MUTEX_INITIALIZER, },
    { PTHREAD_MUTEX_INITIALIZER, },
    { PTHREAD_MUTEX_INITIALIZER, },
  };
  sqlite3_mutex *p;
  switch( iType ){
    case SQLITE_MUTEX_FAST:



















    case SQLITE_MUTEX_RECURSIVE: {
      p = sqlite3MallocZero( sizeof(*p) );
      if( p ){
        p->id = iType;
        pthread_mutex_init(&p->mutex, 0);
      }
      break;
    }
................................................................................
** 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){
  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;
  }
}
int sqlite3_mutex_try(sqlite3_mutex *p){
  pthread_t self = pthread_self();
  int rc;
  if( p->nRef>0 && pthread_equal(p->owner, 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;
}

................................................................................
/*
** 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( pthread_equal(p->owner, pthread_self()) );
  assert( p->nRef>0 );
  p->nRef--;
  if( p->nRef==0 ){
    pthread_mutex_unlock(&p->mutex);
  }
}

/*
** 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->nRef!=0 && pthread_equal(p->owner, pthread_self()));
................................................................................
** 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){


  EnterCriticalSection(&p->mutex);
  p->owner = GetCurrentThreadId(); 
  p->nRef++;
}
int sqlite3_mutex_try(sqlite3_mutex *p){
  int rc;


  if( TryEnterCriticalSection(&p->mutex) ){
    p->owner = GetCurrentThreadId();
    p->nRef++;
    rc = SQLITE_OK;
  }else{
    rc = SQLITE_BUSY;
  }







|







 







|


|







 







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







 







|
|
<
<
|
<
|
|
|
<

<

<
<
<
<
|
>
>
|
|







 







|
|

<
|
|
<







 







>
>






>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
...
335
336
337
338
339
340
341
342
343


344

345
346
347

348

349




350
351
352
353
354
355
356
357
358
359
360
361
...
362
363
364
365
366
367
368
369
370
371

372
373

374
375
376
377
378
379
380
...
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
**    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
** use by the SQLite core.
**
** $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.
*/
#ifndef SQLITE_MUTEX_APPDEF
................................................................................
  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_INITIALIZER, },
    { PTHREAD_MUTEX_INITIALIZER, },
    { PTHREAD_MUTEX_INITIALIZER, },
    { PTHREAD_MUTEX_INITIALIZER, },
  };
  sqlite3_mutex *p;
  switch( iType ){
    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);
      }
      break;
    }
................................................................................
** 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--;

  pthread_mutex_unlock(&p->mutex);
}


/*
** 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->nRef!=0 && pthread_equal(p->owner, pthread_self()));
................................................................................
** 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;
  }

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
**    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.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.599 2007/08/24 08:15:54 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
#include "sqliteLimit.h"



#if defined(SQLITE_TCL) || defined(TCLSH)
# include <tcl.h>
#endif

/*
** Many people are failing to set -DNDEBUG=1 when compiling SQLite.







|





>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
**    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.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $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>
#endif

/*
** Many people are failing to set -DNDEBUG=1 when compiling SQLite.