/ Check-in [80299eeb]
Login

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

Overview
Comment:Clarify the conditions under which homegrown recursive mutexes work (they require a coherent cache) and only enable them if there is an explicit #define so as to avoid accidental use on platforms that do not meet the constraints. Ticket #2805. (CVS 4575)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 80299eebddba9aac4c1bc36ffa2b440bffbf1751
User & Date: drh 2007-11-28 13:55:55
Context
2007-11-28
14:04
Reorganize the code for the homegrown recursive mutexes. Fix a place in the previous check-in where the #ifdef label was incorrect. Ticket #2804. (CVS 4576) check-in: 542e11f9 user: drh tags: trunk
13:55
Clarify the conditions under which homegrown recursive mutexes work (they require a coherent cache) and only enable them if there is an explicit #define so as to avoid accidental use on platforms that do not meet the constraints. Ticket #2805. (CVS 4575) check-in: 80299eeb user: drh tags: trunk
13:43
Preset the legacy_file_format pragma to the value of the primary database so that a VACUUM will not unknowingly alter the setting. Ticket #2804. (CVS 4574) check-in: f731fa6b user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/mutex_unix.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173




174
175
176
177
178
179
180
...
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
...
209
210
211
212
213
214
215




216
217
218
219
220
221
222
**    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.
**
*************************************************************************
** This file contains the C functions that implement mutexes for pthreads
**
** $Id: mutex_unix.c,v 1.3 2007/11/28 00:51:35 drh Exp $
*/
#include "sqliteInt.h"

/*
** The code in this file is only used if we are compiling threadsafe
** under unix with pthreads.
**
................................................................................
    { PTHREAD_MUTEX_INITIALIZER, },
  };
  sqlite3_mutex *p;
  switch( iType ){
    case SQLITE_MUTEX_RECURSIVE: {
      p = sqlite3MallocZero( sizeof(*p) );
      if( p ){
#ifdef PTHREAD_MUTEX_RECURSIVE
        /* Use a recursive mutex if it is available */
        pthread_mutexattr_t recursiveAttr;
        pthread_mutexattr_init(&recursiveAttr);
        pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&p->mutex, &recursiveAttr);
        pthread_mutexattr_destroy(&recursiveAttr);
#else
................................................................................
** 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) );

#ifdef PTHREAD_MUTEX_RECURSIVE
  /* Use the built-in recursive mutexes if they are available.
  ** That they are not available on all systems.
  */
  pthread_mutex_lock(&p->mutex);
  p->owner = pthread_self();
  p->nRef++;
#else
  /* If recursive mutexes are not available, then we have to grow
  ** our own.  This implementation assumes that pthread_equal()
  ** is atomic - that it cannot be deceived into thinking self
  ** and p->owner are equal if p->owner changes between two values
  ** that are not equal to self while the comparison is taking place.




  */
  {
    pthread_t self = pthread_self();
    if( p->nRef>0 && pthread_equal(p->owner, self) ){
      p->nRef++;
    }else{
      pthread_mutex_lock(&p->mutex);
................................................................................
#endif
}
int sqlite3_mutex_try(sqlite3_mutex *p){
  int rc;
  assert( p );
  assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );

#ifdef PTHREAD_MUTEX_RECURSIVE
  /* Use the built-in recursive mutexes if they are available.
  ** That they are not available on all systems.
  */
  if( pthread_mutex_trylock(&p->mutex)==0 ){
    p->owner = pthread_self();
    p->nRef++;
    rc = SQLITE_OK;
  }else{
    rc = SQLITE_BUSY;
................................................................................
  }
#else
  /* If recursive mutexes are not available, then we have to grow
  ** our own.  This implementation assumes that pthread_equal()
  ** is atomic - that it cannot be deceived into thinking self
  ** and p->owner are equal if p->owner changes between two values
  ** that are not equal to self while the comparison is taking place.




  */
  {
    pthread_t self = pthread_self();
    if( p->nRef>0 && pthread_equal(p->owner, self) ){
      p->nRef++;
      rc = SQLITE_OK;
    }else if( pthread_mutex_lock(&p->mutex)==0 ){







|







 







|







 







|

<










>
>
>
>







 







|

<







 







>
>
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
...
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
...
195
196
197
198
199
200
201
202
203

204
205
206
207
208
209
210
...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
**    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.
**
*************************************************************************
** This file contains the C functions that implement mutexes for pthreads
**
** $Id: mutex_unix.c,v 1.4 2007/11/28 13:55:55 drh Exp $
*/
#include "sqliteInt.h"

/*
** The code in this file is only used if we are compiling threadsafe
** under unix with pthreads.
**
................................................................................
    { PTHREAD_MUTEX_INITIALIZER, },
  };
  sqlite3_mutex *p;
  switch( iType ){
    case SQLITE_MUTEX_RECURSIVE: {
      p = sqlite3MallocZero( sizeof(*p) );
      if( p ){
#ifndef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
        /* Use a recursive mutex if it is available */
        pthread_mutexattr_t recursiveAttr;
        pthread_mutexattr_init(&recursiveAttr);
        pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&p->mutex, &recursiveAttr);
        pthread_mutexattr_destroy(&recursiveAttr);
#else
................................................................................
** 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) );

#ifndef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
  /* Use the built-in recursive mutexes if they are available.

  */
  pthread_mutex_lock(&p->mutex);
  p->owner = pthread_self();
  p->nRef++;
#else
  /* If recursive mutexes are not available, then we have to grow
  ** our own.  This implementation assumes that pthread_equal()
  ** is atomic - that it cannot be deceived into thinking self
  ** and p->owner are equal if p->owner changes between two values
  ** that are not equal to self while the comparison is taking place.
  ** This implementation also assumes a coherent cache - that 
  ** separate processes cannot read different values from the same
  ** address at the same time.  If either of these two conditions
  ** are not met, then the mutexes will fail and problems will result.
  */
  {
    pthread_t self = pthread_self();
    if( p->nRef>0 && pthread_equal(p->owner, self) ){
      p->nRef++;
    }else{
      pthread_mutex_lock(&p->mutex);
................................................................................
#endif
}
int sqlite3_mutex_try(sqlite3_mutex *p){
  int rc;
  assert( p );
  assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );

#ifndef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
  /* Use the built-in recursive mutexes if they are available.

  */
  if( pthread_mutex_trylock(&p->mutex)==0 ){
    p->owner = pthread_self();
    p->nRef++;
    rc = SQLITE_OK;
  }else{
    rc = SQLITE_BUSY;
................................................................................
  }
#else
  /* If recursive mutexes are not available, then we have to grow
  ** our own.  This implementation assumes that pthread_equal()
  ** is atomic - that it cannot be deceived into thinking self
  ** and p->owner are equal if p->owner changes between two values
  ** that are not equal to self while the comparison is taking place.
  ** This implementation also assumes a coherent cache - that 
  ** separate processes cannot read different values from the same
  ** address at the same time.  If either of these two conditions
  ** are not met, then the mutexes will fail and problems will result.
  */
  {
    pthread_t self = pthread_self();
    if( p->nRef>0 && pthread_equal(p->owner, self) ){
      p->nRef++;
      rc = SQLITE_OK;
    }else if( pthread_mutex_lock(&p->mutex)==0 ){