/ Check-in [2fb9a5dd]
Login

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

Overview
Comment:Enhancments to Win32 mutex debugging.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | mutexDbg
Files: files | file ages | folders
SHA1:2fb9a5dd40662b6d3c7dfa4cdac47cb2401a289e
User & Date: mistachkin 2016-10-17 18:59:52
Context
2016-10-17
19:00
Escape non-ASCII character from an ICU extension comment. Cherrypick of [5ec02ecf3d20ce7e]. Leaf check-in: a3a96c4d user: mistachkin tags: mutexDbg
18:59
Enhancments to Win32 mutex debugging. check-in: 2fb9a5dd user: mistachkin tags: mutexDbg
2016-09-12
18:50
Version 3.14.2 Leaf check-in: 29dbef4b user: drh tags: release, branch-3.14, version-3.14.2
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/mutex.h.

46
47
48
49
50
51
52







53
54
55
56
57
58
59
#  elif SQLITE_OS_WIN
#    define SQLITE_MUTEX_W32
#  else
#    define SQLITE_MUTEX_NOOP
#  endif
#endif








#ifdef SQLITE_MUTEX_OMIT
/*
** If this is a no-op implementation, implement everything as macros.
*/
#define sqlite3_mutex_alloc(X)    ((sqlite3_mutex*)8)
#define sqlite3_mutex_free(X)
#define sqlite3_mutex_enter(X)    







>
>
>
>
>
>
>







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#  elif SQLITE_OS_WIN
#    define SQLITE_MUTEX_W32
#  else
#    define SQLITE_MUTEX_NOOP
#  endif
#endif

/*
** Allowed values for sqlite3_mutex.magic
*/
#define SQLITE_MUTEXMAGIC_NORMAL  0x1f7a8074
#define SQLITE_MUTEXMAGIC_TRACE   0x1f7a8075
#define SQLITE_MUTEXMAGIC_DEAD    0x4b0844f6

#ifdef SQLITE_MUTEX_OMIT
/*
** If this is a no-op implementation, implement everything as macros.
*/
#define sqlite3_mutex_alloc(X)    ((sqlite3_mutex*)8)
#define sqlite3_mutex_free(X)
#define sqlite3_mutex_enter(X)    

Changes to src/mutex_w32.c.

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
...
217
218
219
220
221
222
223
224


225
226
227
228
229
230
231
...
239
240
241
242
243
244
245
246


247
248
249
250
251
252
253
...
256
257
258
259
260
261
262

263
264
265
266
267
268
269
...
282
283
284
285
286
287
288
289
290


291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313


314

315
316
317
318
319
320
321
...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
...
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
381
382
*/
struct sqlite3_mutex {
  CRITICAL_SECTION mutex;    /* Mutex controlling the lock */
  int id;                    /* Mutex type */
#ifdef SQLITE_DEBUG
  volatile int nRef;         /* Number of enterances */
  volatile DWORD owner;      /* Thread holding this mutex */
  volatile int trace;        /* True to trace changes */
#endif
};

/*
** These are the initializer values used when declaring a "static" mutex
** on Win32.  It should be noted that all mutexes require initialization
** on the Win32 platform.
................................................................................
    case SQLITE_MUTEX_FAST:
    case SQLITE_MUTEX_RECURSIVE: {
      p = sqlite3MallocZero( sizeof(*p) );
      if( p ){
        p->id = iType;
#ifdef SQLITE_DEBUG
#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC
        p->trace = 1;


#endif
#endif
#if SQLITE_OS_WINRT
        InitializeCriticalSectionEx(&p->mutex, 0, 0);
#else
        InitializeCriticalSection(&p->mutex);
#endif
................................................................................
        return 0;
      }
#endif
      p = &winMutex_staticMutexes[iType-2];
      p->id = iType;
#ifdef SQLITE_DEBUG
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
      p->trace = 1;


#endif
#endif
      break;
    }
  }
  return p;
}
................................................................................
/*
** This routine deallocates a previously
** allocated mutex.  SQLite is careful to deallocate every
** mutex that it allocates.
*/
static void winMutexFree(sqlite3_mutex *p){
  assert( p );

  assert( p->nRef==0 && p->owner==0 );
  if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){
    DeleteCriticalSection(&p->mutex);
    sqlite3_free(p);
  }else{
#ifdef SQLITE_ENABLE_API_ARMOR
    (void)SQLITE_MISUSE_BKPT;
................................................................................
** can enter.  If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
static void winMutexEnter(sqlite3_mutex *p){
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  DWORD tid = GetCurrentThreadId();
#endif
#ifdef SQLITE_DEBUG
  assert( p );


  assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
#else
  assert( p );
#endif
  assert( winMutex_isInit==1 );
  EnterCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
  assert( p->nRef>0 || p->owner==0 );
  p->owner = tid;
  p->nRef++;
  if( p->trace ){
    OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
             tid, p, p->trace, p->nRef));
  }
#endif
}

static int winMutexTry(sqlite3_mutex *p){
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  DWORD tid = GetCurrentThreadId();
#endif
  int rc = SQLITE_BUSY;
  assert( p );


  assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );

  /*
  ** The sqlite3_mutex_try() routine is very rarely used, and when it
  ** is used it is merely an optimization.  So it is OK for it to always
  ** fail.
  **
  ** The TryEnterCriticalSection() interface is only available on WinNT.
  ** And some windows compilers complain if you try to use it without
................................................................................
#endif
    rc = SQLITE_OK;
  }
#else
  UNUSED_PARAMETER(p);
#endif
#ifdef SQLITE_DEBUG
  if( p->trace ){
    OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
             tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
  }
#endif
  return rc;
}

/*
** The sqlite3_mutex_leave() routine exits a mutex that was
................................................................................
** is not currently allocated.  SQLite will never do either.
*/
static void winMutexLeave(sqlite3_mutex *p){
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  DWORD tid = GetCurrentThreadId();
#endif
  assert( p );

#ifdef SQLITE_DEBUG
  assert( p->nRef>0 );
  assert( p->owner==tid );
  p->nRef--;
  if( p->nRef==0 ) p->owner = 0;
  assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
#endif
  assert( winMutex_isInit==1 );
  LeaveCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
  if( p->trace ){
    OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
             tid, p, p->trace, p->nRef));
  }
#endif
}

sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
  static const sqlite3_mutex_methods sMutex = {
    winMutexInit,







|







 







|
>
>







 







|
>
>







 







>







 







<

>
>

<
<







|
|
|










>
>

>







 







|
|
|







 







>










|
|
|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
...
287
288
289
290
291
292
293

294
295
296
297


298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
...
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
*/
struct sqlite3_mutex {
  CRITICAL_SECTION mutex;    /* Mutex controlling the lock */
  int id;                    /* Mutex type */
#ifdef SQLITE_DEBUG
  volatile int nRef;         /* Number of enterances */
  volatile DWORD owner;      /* Thread holding this mutex */
  volatile u32 magic;        /* True to trace changes */
#endif
};

/*
** These are the initializer values used when declaring a "static" mutex
** on Win32.  It should be noted that all mutexes require initialization
** on the Win32 platform.
................................................................................
    case SQLITE_MUTEX_FAST:
    case SQLITE_MUTEX_RECURSIVE: {
      p = sqlite3MallocZero( sizeof(*p) );
      if( p ){
        p->id = iType;
#ifdef SQLITE_DEBUG
#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC
        p->magic = SQLITE_MUTEXMAGIC_TRACE;
#else
        p->magic = SQLITE_MUTEXMAGIC_NORMAL;
#endif
#endif
#if SQLITE_OS_WINRT
        InitializeCriticalSectionEx(&p->mutex, 0, 0);
#else
        InitializeCriticalSection(&p->mutex);
#endif
................................................................................
        return 0;
      }
#endif
      p = &winMutex_staticMutexes[iType-2];
      p->id = iType;
#ifdef SQLITE_DEBUG
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
      p->magic = SQLITE_MUTEXMAGIC_TRACE;
#else
      p->magic = SQLITE_MUTEXMAGIC_NORMAL;
#endif
#endif
      break;
    }
  }
  return p;
}
................................................................................
/*
** This routine deallocates a previously
** allocated mutex.  SQLite is careful to deallocate every
** mutex that it allocates.
*/
static void winMutexFree(sqlite3_mutex *p){
  assert( p );
  assert( (p->magic&~1)==SQLITE_MUTEXMAGIC_NORMAL );
  assert( p->nRef==0 && p->owner==0 );
  if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){
    DeleteCriticalSection(&p->mutex);
    sqlite3_free(p);
  }else{
#ifdef SQLITE_ENABLE_API_ARMOR
    (void)SQLITE_MISUSE_BKPT;
................................................................................
** can enter.  If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
static void winMutexEnter(sqlite3_mutex *p){
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  DWORD tid = GetCurrentThreadId();
#endif

  assert( p );
  assert( (p->magic&~1)==SQLITE_MUTEXMAGIC_NORMAL );
#ifdef SQLITE_DEBUG
  assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );


#endif
  assert( winMutex_isInit==1 );
  EnterCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
  assert( p->nRef>0 || p->owner==0 );
  p->owner = tid;
  p->nRef++;
  if( p->magic&1 ){
    OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%lu), nRef=%d\n",
             tid, p, p->magic, p->nRef));
  }
#endif
}

static int winMutexTry(sqlite3_mutex *p){
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  DWORD tid = GetCurrentThreadId();
#endif
  int rc = SQLITE_BUSY;
  assert( p );
  assert( (p->magic&~1)==SQLITE_MUTEXMAGIC_NORMAL );
#ifdef SQLITE_DEBUG
  assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
#endif
  /*
  ** The sqlite3_mutex_try() routine is very rarely used, and when it
  ** is used it is merely an optimization.  So it is OK for it to always
  ** fail.
  **
  ** The TryEnterCriticalSection() interface is only available on WinNT.
  ** And some windows compilers complain if you try to use it without
................................................................................
#endif
    rc = SQLITE_OK;
  }
#else
  UNUSED_PARAMETER(p);
#endif
#ifdef SQLITE_DEBUG
  if( p->magic&1 ){
    OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%lu), owner=%lu, nRef=%d, rc=%s\n",
             tid, p, p->magic, p->owner, p->nRef, sqlite3ErrName(rc)));
  }
#endif
  return rc;
}

/*
** The sqlite3_mutex_leave() routine exits a mutex that was
................................................................................
** is not currently allocated.  SQLite will never do either.
*/
static void winMutexLeave(sqlite3_mutex *p){
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  DWORD tid = GetCurrentThreadId();
#endif
  assert( p );
  assert( (p->magic&~1)==SQLITE_MUTEXMAGIC_NORMAL );
#ifdef SQLITE_DEBUG
  assert( p->nRef>0 );
  assert( p->owner==tid );
  p->nRef--;
  if( p->nRef==0 ) p->owner = 0;
  assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
#endif
  assert( winMutex_isInit==1 );
  LeaveCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
  if( p->magic&1 ){
    OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%lu), nRef=%d\n",
             tid, p, p->magic, p->nRef));
  }
#endif
}

sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
  static const sqlite3_mutex_methods sMutex = {
    winMutexInit,