Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch mutexDbg2 Excluding Merge-Ins
This is equivalent to a diff from ca4f1e49 to 4ca2b2f8
2017-02-15
| ||
01:39 | In the blob test code, avoid crashing on low-memory systems by using Tcl_AttemptAlloc(). (check-in: 1d267757 user: mistachkin tags: trunk) | |
01:02 | Make SQLITE_GET_MUTEX_TIME a proper noop on non-Win32/non-POSIX. (Leaf check-in: 4ca2b2f8 user: mistachkin tags: mutexDbg2) | |
00:52 | Another compilation fix for POSIX. (check-in: 82ef47ea user: mistachkin tags: mutexDbg2) | |
2017-02-14
| ||
23:58 | Experimental enhancements to mutex debugging. (check-in: 80481754 user: mistachkin tags: mutexDbg2) | |
21:47 | Clarification of the help text for the command-line shell. (check-in: ca4f1e49 user: drh tags: trunk) | |
20:00 | Enable the SQLITE_ENABLE_NULL_TRIM option for WITHOUT ROWID tables. (check-in: 54836270 user: drh tags: trunk) | |
Changes to src/mutex.c.
︙ | |||
10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | + + + + + + | ** ************************************************************************* ** This file contains the C functions that implement mutexes. ** ** This file contains code that is common across all mutex implementations. */ #include "sqliteInt.h" #if SQLITE_OS_UNIX # include <sys/time.h> # include <pthread.h> #elif SQLITE_OS_WIN # include "os_win.h" #endif #if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT) /* ** For debugging purposes, record when the mutex subsystem is initialized ** and uninitialized so that we can assert() if there is an attempt to ** allocate a mutex while the system is uninitialized. */ |
︙ | |||
78 79 80 81 82 83 84 85 86 87 88 89 90 91 | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | #ifdef SQLITE_DEBUG GLOBAL(int, mutexIsInit) = 0; #endif return rc; } #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 /* Return a time value for use by the mutex subsystem. */ i64 sqlite3MutexTimeOfDay(void){ #ifdef SQLITE_GET_MUTEX_TIME SQLITE_GET_MUTEX_TIME; #else return 0; #endif } /* ** Calculates the elapsed time, in milliseconds, that a particular mutex ** was held and issues a warning, via the sqlite3_log() interface, if it ** was held for "too long". */ void sqlite3MutexTimeAlert( sqlite3_mutex *p, i64 entered ){ i64 exited = sqlite3MutexTimeOfDay(); i64 elapsed; assert( p!=0 ); assert( exited>=entered ); elapsed = exited - entered; if( elapsed>SQLITE_MUTEX_ALERT_MILLISECONDS ){ void *tid = 0; int mid = -1; #ifdef SQLITE_GET_THREAD_ID tid = SQLITE_GET_THREAD_ID(); #endif #ifdef SQLITE_GET_MUTEX_ID mid = SQLITE_GET_MUTEX_ID(p); #endif sqlite3_log(SQLITE_NOTICE, "thread %p delayed %lldms for mutex %p (%d)", tid, elapsed, p, mid ); } } #endif /* ** Retrieve a pointer to a static mutex or allocate a new dynamic one. */ sqlite3_mutex *sqlite3_mutex_alloc(int id){ #ifndef SQLITE_OMIT_AUTOINIT if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0; |
︙ |
Changes to src/mutex_noop.c.
︙ | |||
76 77 78 79 80 81 82 83 84 85 86 87 88 89 | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | + + + | /* ** The mutex object */ typedef struct sqlite3_debug_mutex { int id; /* The mutex type */ int cnt; /* Number of entries without a matching leave */ #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 i64 entered; /* Time that mutex was entered */ #endif } sqlite3_debug_mutex; /* ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use inside assert() statements. */ static int debugMutexHeld(sqlite3_mutex *pX){ |
︙ | |||
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | + + + + + + + + + | ** can enter. If the same thread tries to enter any other kind of mutex ** more than once, the behavior is undefined. */ static void debugMutexEnter(sqlite3_mutex *pX){ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); p->cnt++; #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 p->entered = sqlite3MutexTimeOfDay(); #endif } static int debugMutexTry(sqlite3_mutex *pX){ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); p->cnt++; #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 p->entered = sqlite3MutexTimeOfDay(); #endif return SQLITE_OK; } /* ** 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. */ static void debugMutexLeave(sqlite3_mutex *pX){ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; assert( debugMutexHeld(pX) ); #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 sqlite3MutexTimeAlert((sqlite3_mutex*)p, p->entered); #endif p->cnt--; assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); } sqlite3_mutex_methods const *sqlite3NoopMutex(void){ static const sqlite3_mutex_methods sMutex = { debugMutexInit, |
︙ |
Changes to src/mutex_unix.c.
︙ | |||
39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | + + + | ** Each recursive mutex is an instance of the following structure. */ struct sqlite3_mutex { pthread_mutex_t mutex; /* Mutex controlling the lock */ #if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) int id; /* Mutex type */ #endif #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 i64 entered; /* Time that mutex was entered */ #endif #if SQLITE_MUTEX_NREF volatile int nRef; /* Number of entrances */ volatile pthread_t owner; /* Thread that is within this mutex */ int trace; /* True to trace changes */ #endif }; #if SQLITE_MUTEX_NREF |
︙ | |||
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | + + + + + + | */ { pthread_t self = pthread_self(); if( p->nRef>0 && pthread_equal(p->owner, self) ){ p->nRef++; }else{ pthread_mutex_lock(&p->mutex); #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 p->entered = sqlite3MutexTimeOfDay(); #endif assert( p->nRef==0 ); p->owner = self; p->nRef = 1; } } #else /* Use the built-in recursive mutexes if they are available. */ pthread_mutex_lock(&p->mutex); #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 p->entered = sqlite3MutexTimeOfDay(); #endif #if SQLITE_MUTEX_NREF assert( p->nRef>0 || p->owner==0 ); p->owner = pthread_self(); p->nRef++; #endif #endif |
︙ | |||
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 | 309 310 311 312 313 314 315 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 | + + + + + + | */ { pthread_t self = pthread_self(); if( p->nRef>0 && pthread_equal(p->owner, self) ){ p->nRef++; rc = SQLITE_OK; }else if( pthread_mutex_trylock(&p->mutex)==0 ){ #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 p->entered = sqlite3MutexTimeOfDay(); #endif assert( p->nRef==0 ); p->owner = self; p->nRef = 1; rc = SQLITE_OK; }else{ rc = SQLITE_BUSY; } } #else /* Use the built-in recursive mutexes if they are available. */ if( pthread_mutex_trylock(&p->mutex)==0 ){ #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 p->entered = sqlite3MutexTimeOfDay(); #endif #if SQLITE_MUTEX_NREF p->owner = pthread_self(); p->nRef++; #endif rc = SQLITE_OK; }else{ rc = SQLITE_BUSY; |
︙ | |||
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 | + + + + + + | p->nRef--; if( p->nRef==0 ) p->owner = 0; #endif assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX if( p->nRef==0 ){ #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 sqlite3MutexTimeAlert(p, p->entered); #endif pthread_mutex_unlock(&p->mutex); } #else #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 sqlite3MutexTimeAlert(p, p->entered); #endif pthread_mutex_unlock(&p->mutex); #endif #ifdef SQLITE_DEBUG if( p->trace ){ printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); } |
︙ |
Changes to src/mutex_w32.c.
︙ | |||
33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | + + + | /* ** Each recursive mutex is an instance of the following structure. */ struct sqlite3_mutex { CRITICAL_SECTION mutex; /* Mutex controlling the lock */ int id; /* Mutex type */ #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 i64 entered; /* Time that mutex was entered */ #endif #ifdef SQLITE_DEBUG volatile int nRef; /* Number of enterances */ volatile DWORD owner; /* Thread holding this mutex */ volatile int trace; /* True to trace changes */ #endif }; |
︙ | |||
289 290 291 292 293 294 295 296 297 298 299 300 301 302 | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | + + + | assert( p ); assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); #else assert( p ); #endif assert( winMutex_isInit==1 ); EnterCriticalSection(&p->mutex); #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 p->entered = sqlite3MutexTimeOfDay(); #endif #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)); |
︙ | |||
326 327 328 329 330 331 332 333 334 335 336 337 338 339 | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | + + + | assert( winMutex_isInit==1 ); assert( winMutex_isNt>=-1 && winMutex_isNt<=1 ); if( winMutex_isNt<0 ){ winMutex_isNt = sqlite3_win32_is_nt(); } assert( winMutex_isNt==0 || winMutex_isNt==1 ); if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){ #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 p->entered = sqlite3MutexTimeOfDay(); #endif #ifdef SQLITE_DEBUG p->owner = tid; p->nRef++; #endif rc = SQLITE_OK; } #else |
︙ | |||
363 364 365 366 367 368 369 370 371 372 373 374 375 376 | 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 | + + + | 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 ); #if SQLITE_MUTEX_ALERT_MILLISECONDS>0 sqlite3MutexTimeAlert(p, p->entered); #endif 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 |
︙ |
Changes to src/sqliteInt.h.
︙ | |||
3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 | 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | #endif #if !defined(SQLITE_MUTEX_OMIT) && !defined(SQLITE_MUTEX_NOOP) void sqlite3MemoryBarrier(void); #else # define sqlite3MemoryBarrier() #endif /* ** When SQLITE_MUTEX_ALERT_MILLISECONDS is greater than zero, extra code ** will be included to issue warnings via the sqlite3_log() interface if ** a mutex is held for longer than the number of milliseconds specified ** by SQLITE_MUTEX_ALERT_MILLISECONDS. */ #ifndef SQLITE_MUTEX_ALERT_MILLISECONDS # define SQLITE_MUTEX_ALERT_MILLISECONDS (0) #endif #if !defined(SQLITE_MUTEX_OMIT) && SQLITE_MUTEX_ALERT_MILLISECONDS>0 i64 sqlite3MutexTimeOfDay(void); void sqlite3MutexTimeAlert(sqlite3_mutex *, i64); /* ** This macro contains code that returns a 64-bit integer time value, ** in milliseconds, or zero if that information is not available. */ # ifndef SQLITE_GET_MUTEX_TIME # if SQLITE_OS_UNIX # define SQLITE_GET_MUTEX_TIME { \ struct timeval sNow; (void)gettimeofday(&sNow, 0); \ return 1000*(i64)sNow.tv_sec + sNow.tv_usec/1000; \ } # elif SQLITE_OS_WIN # define SQLITE_GET_MUTEX_TIME { \ return (i64)GetTickCount(); \ } # else # define SQLITE_GET_MUTEX_TIME { \ return 0; \ } # endif # endif /* ** This macro returns the integer type for the specified mutex or ** negative one if that information is not available. */ # ifndef SQLITE_GET_MUTEX_ID # if SQLITE_OS_UNIX # if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) # define SQLITE_GET_MUTEX_ID(p) \ *((int*)(((unsigned char*)(p))+sizeof(pthread_mutex_t))) # else # define SQLITE_GET_MUTEX_ID(p) (-1) # endif # elif SQLITE_OS_WIN # define SQLITE_GET_MUTEX_ID(p) \ *((int*)(((unsigned char*)(p))+sizeof(CRITICAL_SECTION))) # else # define SQLITE_GET_MUTEX_ID(p) (-1) # endif # endif /* ** This macro returns the integer identifier for the current thread ** or zero if that information is not available. */ # ifndef SQLITE_GET_THREAD_ID # if SQLITE_OS_UNIX # define SQLITE_GET_THREAD_ID() ((void *)pthread_self()) # elif SQLITE_OS_WIN # define SQLITE_GET_THREAD_ID() ((void *)GetCurrentThreadId()) # else # define SQLITE_GET_THREAD_ID() ((void *)0) # endif # endif #else # define sqlite3MutexTimeOfDay() (0) # define sqlite3MutexTimeAlert(X,Y) # define SQLITE_GET_MUTEX_TIME # define SQLITE_GET_MUTEX_ID(p) (-1) # define SQLITE_GET_THREAD_ID() ((void *)0) #endif sqlite3_int64 sqlite3StatusValue(int); void sqlite3StatusUp(int, int); void sqlite3StatusDown(int, int); void sqlite3StatusHighwater(int, int); /* Access to mutexes used by sqlite3_status() */ sqlite3_mutex *sqlite3Pcache1Mutex(void); |
︙ |