drh | 90f6a5b | 2007-08-15 13:04:54 +0000 | [diff] [blame] | 1 | /* |
| 2 | ** 2007 August 14 |
| 3 | ** |
| 4 | ** The author disclaims copyright to this source code. In place of |
| 5 | ** a legal notice, here is a blessing: |
| 6 | ** |
| 7 | ** May you do good and not evil. |
| 8 | ** May you find forgiveness for yourself and forgive others. |
| 9 | ** May you share freely, never taking more than you give. |
| 10 | ** |
| 11 | ************************************************************************* |
drh | 437b901 | 2007-08-28 16:34:42 +0000 | [diff] [blame] | 12 | ** This file contains the C functions that implement mutexes. |
drh | 90f6a5b | 2007-08-15 13:04:54 +0000 | [diff] [blame] | 13 | ** |
drh | 18472fa | 2008-10-07 15:25:48 +0000 | [diff] [blame] | 14 | ** This file contains code that is common across all mutex implementations. |
drh | 90f6a5b | 2007-08-15 13:04:54 +0000 | [diff] [blame] | 15 | */ |
| 16 | #include "sqliteInt.h" |
| 17 | |
drh | d0bc5d2 | 2009-09-10 22:30:53 +0000 | [diff] [blame] | 18 | #if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT) |
drh | fe5bdb3 | 2009-09-10 17:45:00 +0000 | [diff] [blame] | 19 | /* |
| 20 | ** For debugging purposes, record when the mutex subsystem is initialized |
| 21 | ** and uninitialized so that we can assert() if there is an attempt to |
| 22 | ** allocate a mutex while the system is uninitialized. |
| 23 | */ |
| 24 | static SQLITE_WSD int mutexIsInit = 0; |
mistachkin | 04abf08 | 2015-09-12 18:57:45 +0000 | [diff] [blame] | 25 | #endif /* SQLITE_DEBUG && !defined(SQLITE_MUTEX_OMIT) */ |
drh | fe5bdb3 | 2009-09-10 17:45:00 +0000 | [diff] [blame] | 26 | |
| 27 | |
drh | 18472fa | 2008-10-07 15:25:48 +0000 | [diff] [blame] | 28 | #ifndef SQLITE_MUTEX_OMIT |
dan | 8385bec | 2017-11-25 17:51:01 +0000 | [diff] [blame] | 29 | |
| 30 | #ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS |
| 31 | /* |
| 32 | ** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains |
| 33 | ** the implementation of a wrapper around the system default mutex |
| 34 | ** implementation (sqlite3DefaultMutex()). |
| 35 | ** |
| 36 | ** Most calls are passed directly through to the underlying default |
| 37 | ** mutex implementation. Except, if a mutex is configured by calling |
| 38 | ** sqlite3MutexWarnOnContention() on it, then if contention is ever |
| 39 | ** encountered within xMutexEnter() a warning is emitted via sqlite3_log(). |
| 40 | ** |
| 41 | ** This type of mutex is used as the database handle mutex when testing |
| 42 | ** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. |
| 43 | */ |
| 44 | |
| 45 | /* |
| 46 | ** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS |
dan | a90a2d5 | 2017-11-28 07:47:57 +0000 | [diff] [blame] | 47 | ** is defined. Variable CheckMutex.mutex is a pointer to the real mutex |
| 48 | ** allocated by the system mutex implementation. Variable iType is usually set |
| 49 | ** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST |
| 50 | ** or one of the static mutex identifiers. Or, if this is a recursive mutex |
| 51 | ** that has been configured using sqlite3MutexWarnOnContention(), it is |
| 52 | ** set to SQLITE_MUTEX_WARNONCONTENTION. |
dan | 8385bec | 2017-11-25 17:51:01 +0000 | [diff] [blame] | 53 | */ |
| 54 | typedef struct CheckMutex CheckMutex; |
| 55 | struct CheckMutex { |
| 56 | int iType; |
| 57 | sqlite3_mutex *mutex; |
| 58 | }; |
| 59 | |
dan | a90a2d5 | 2017-11-28 07:47:57 +0000 | [diff] [blame] | 60 | #define SQLITE_MUTEX_WARNONCONTENTION (-1) |
| 61 | |
dan | 8385bec | 2017-11-25 17:51:01 +0000 | [diff] [blame] | 62 | /* |
| 63 | ** Pointer to real mutex methods object used by the CheckMutex |
| 64 | ** implementation. Set by checkMutexInit(). |
| 65 | */ |
| 66 | static SQLITE_WSD const sqlite3_mutex_methods *pGlobalMutexMethods; |
| 67 | |
| 68 | #ifdef SQLITE_DEBUG |
| 69 | static int checkMutexHeld(sqlite3_mutex *p){ |
| 70 | return pGlobalMutexMethods->xMutexHeld(((CheckMutex*)p)->mutex); |
| 71 | } |
| 72 | static int checkMutexNotheld(sqlite3_mutex *p){ |
| 73 | return pGlobalMutexMethods->xMutexNotheld(((CheckMutex*)p)->mutex); |
| 74 | } |
| 75 | #endif |
| 76 | |
| 77 | /* |
| 78 | ** Initialize and deinitialize the mutex subsystem. |
| 79 | */ |
| 80 | static int checkMutexInit(void){ |
| 81 | pGlobalMutexMethods = sqlite3DefaultMutex(); |
| 82 | return SQLITE_OK; |
| 83 | } |
| 84 | static int checkMutexEnd(void){ |
| 85 | pGlobalMutexMethods = 0; |
| 86 | return SQLITE_OK; |
| 87 | } |
| 88 | |
| 89 | /* |
| 90 | ** Allocate a mutex. |
| 91 | */ |
| 92 | static sqlite3_mutex *checkMutexAlloc(int iType){ |
| 93 | static CheckMutex staticMutexes[] = { |
| 94 | {2, 0}, {3, 0}, {4, 0}, {5, 0}, |
| 95 | {6, 0}, {7, 0}, {8, 0}, {9, 0}, |
| 96 | {10, 0}, {11, 0}, {12, 0}, {13, 0} |
| 97 | }; |
| 98 | CheckMutex *p = 0; |
| 99 | |
| 100 | assert( SQLITE_MUTEX_RECURSIVE==1 && SQLITE_MUTEX_FAST==0 ); |
| 101 | if( iType<2 ){ |
| 102 | p = sqlite3MallocZero(sizeof(CheckMutex)); |
| 103 | if( p==0 ) return 0; |
| 104 | p->iType = iType; |
| 105 | }else{ |
| 106 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 107 | if( iType-2>=ArraySize(staticMutexes) ){ |
| 108 | (void)SQLITE_MISUSE_BKPT; |
| 109 | return 0; |
| 110 | } |
| 111 | #endif |
| 112 | p = &staticMutexes[iType-2]; |
| 113 | } |
| 114 | |
| 115 | if( p->mutex==0 ){ |
| 116 | p->mutex = pGlobalMutexMethods->xMutexAlloc(iType); |
| 117 | if( p->mutex==0 ){ |
| 118 | if( iType<2 ){ |
| 119 | sqlite3_free(p); |
| 120 | } |
| 121 | p = 0; |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | return (sqlite3_mutex*)p; |
| 126 | } |
| 127 | |
| 128 | /* |
| 129 | ** Free a mutex. |
| 130 | */ |
| 131 | static void checkMutexFree(sqlite3_mutex *p){ |
dan | a90a2d5 | 2017-11-28 07:47:57 +0000 | [diff] [blame] | 132 | assert( SQLITE_MUTEX_RECURSIVE<2 ); |
| 133 | assert( SQLITE_MUTEX_FAST<2 ); |
| 134 | assert( SQLITE_MUTEX_WARNONCONTENTION<2 ); |
| 135 | |
dan | 8385bec | 2017-11-25 17:51:01 +0000 | [diff] [blame] | 136 | #if SQLITE_ENABLE_API_ARMOR |
dan | 8adb25a | 2017-12-05 14:58:59 +0000 | [diff] [blame] | 137 | if( ((CheckMutex*)p)->iType<2 ) |
dan | 8385bec | 2017-11-25 17:51:01 +0000 | [diff] [blame] | 138 | #endif |
| 139 | { |
| 140 | CheckMutex *pCheck = (CheckMutex*)p; |
| 141 | pGlobalMutexMethods->xMutexFree(pCheck->mutex); |
| 142 | sqlite3_free(pCheck); |
| 143 | } |
| 144 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 145 | else{ |
| 146 | (void)SQLITE_MISUSE_BKPT; |
| 147 | } |
| 148 | #endif |
| 149 | } |
| 150 | |
| 151 | /* |
| 152 | ** Enter the mutex. |
| 153 | */ |
| 154 | static void checkMutexEnter(sqlite3_mutex *p){ |
| 155 | CheckMutex *pCheck = (CheckMutex*)p; |
dan | a90a2d5 | 2017-11-28 07:47:57 +0000 | [diff] [blame] | 156 | if( pCheck->iType==SQLITE_MUTEX_WARNONCONTENTION ){ |
dan | 8385bec | 2017-11-25 17:51:01 +0000 | [diff] [blame] | 157 | if( SQLITE_OK==pGlobalMutexMethods->xMutexTry(pCheck->mutex) ){ |
| 158 | return; |
| 159 | } |
| 160 | sqlite3_log(SQLITE_MISUSE, |
| 161 | "illegal multi-threaded access to database connection" |
| 162 | ); |
| 163 | } |
| 164 | pGlobalMutexMethods->xMutexEnter(pCheck->mutex); |
| 165 | } |
| 166 | |
| 167 | /* |
| 168 | ** Enter the mutex (do not block). |
| 169 | */ |
| 170 | static int checkMutexTry(sqlite3_mutex *p){ |
| 171 | CheckMutex *pCheck = (CheckMutex*)p; |
| 172 | return pGlobalMutexMethods->xMutexTry(pCheck->mutex); |
| 173 | } |
| 174 | |
| 175 | /* |
| 176 | ** Leave the mutex. |
| 177 | */ |
| 178 | static void checkMutexLeave(sqlite3_mutex *p){ |
| 179 | CheckMutex *pCheck = (CheckMutex*)p; |
| 180 | pGlobalMutexMethods->xMutexLeave(pCheck->mutex); |
| 181 | } |
| 182 | |
| 183 | sqlite3_mutex_methods const *multiThreadedCheckMutex(void){ |
| 184 | static const sqlite3_mutex_methods sMutex = { |
| 185 | checkMutexInit, |
| 186 | checkMutexEnd, |
| 187 | checkMutexAlloc, |
| 188 | checkMutexFree, |
| 189 | checkMutexEnter, |
| 190 | checkMutexTry, |
| 191 | checkMutexLeave, |
| 192 | #ifdef SQLITE_DEBUG |
| 193 | checkMutexHeld, |
| 194 | checkMutexNotheld |
| 195 | #else |
| 196 | 0, |
| 197 | 0 |
| 198 | #endif |
| 199 | }; |
| 200 | return &sMutex; |
| 201 | } |
| 202 | |
| 203 | /* |
| 204 | ** Mark the SQLITE_MUTEX_RECURSIVE mutex passed as the only argument as |
| 205 | ** one on which there should be no contention. |
| 206 | */ |
| 207 | void sqlite3MutexWarnOnContention(sqlite3_mutex *p){ |
| 208 | if( sqlite3GlobalConfig.mutex.xMutexAlloc==checkMutexAlloc ){ |
| 209 | CheckMutex *pCheck = (CheckMutex*)p; |
| 210 | assert( pCheck->iType==SQLITE_MUTEX_RECURSIVE ); |
dan | a90a2d5 | 2017-11-28 07:47:57 +0000 | [diff] [blame] | 211 | pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION; |
dan | 8385bec | 2017-11-25 17:51:01 +0000 | [diff] [blame] | 212 | } |
| 213 | } |
| 214 | #endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */ |
| 215 | |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 216 | /* |
| 217 | ** Initialize the mutex system. |
| 218 | */ |
danielk1977 | d025174 | 2008-06-18 18:57:42 +0000 | [diff] [blame] | 219 | int sqlite3MutexInit(void){ |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 220 | int rc = SQLITE_OK; |
drh | 92d7652 | 2010-05-05 00:05:24 +0000 | [diff] [blame] | 221 | if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){ |
| 222 | /* If the xMutexAlloc method has not been set, then the user did not |
| 223 | ** install a mutex implementation via sqlite3_config() prior to |
| 224 | ** sqlite3_initialize() being called. This block copies pointers to |
| 225 | ** the default implementation into the sqlite3GlobalConfig structure. |
| 226 | */ |
dan | 558814f | 2010-06-02 05:53:53 +0000 | [diff] [blame] | 227 | sqlite3_mutex_methods const *pFrom; |
drh | 92d7652 | 2010-05-05 00:05:24 +0000 | [diff] [blame] | 228 | sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex; |
drh | e64ca7b | 2009-07-16 18:21:17 +0000 | [diff] [blame] | 229 | |
drh | 92d7652 | 2010-05-05 00:05:24 +0000 | [diff] [blame] | 230 | if( sqlite3GlobalConfig.bCoreMutex ){ |
dan | 8385bec | 2017-11-25 17:51:01 +0000 | [diff] [blame] | 231 | #ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS |
| 232 | pFrom = multiThreadedCheckMutex(); |
| 233 | #else |
drh | 92d7652 | 2010-05-05 00:05:24 +0000 | [diff] [blame] | 234 | pFrom = sqlite3DefaultMutex(); |
dan | 8385bec | 2017-11-25 17:51:01 +0000 | [diff] [blame] | 235 | #endif |
drh | 92d7652 | 2010-05-05 00:05:24 +0000 | [diff] [blame] | 236 | }else{ |
| 237 | pFrom = sqlite3NoopMutex(); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 238 | } |
drh | f5ed7ad | 2015-06-15 14:43:25 +0000 | [diff] [blame] | 239 | pTo->xMutexInit = pFrom->xMutexInit; |
| 240 | pTo->xMutexEnd = pFrom->xMutexEnd; |
| 241 | pTo->xMutexFree = pFrom->xMutexFree; |
| 242 | pTo->xMutexEnter = pFrom->xMutexEnter; |
| 243 | pTo->xMutexTry = pFrom->xMutexTry; |
| 244 | pTo->xMutexLeave = pFrom->xMutexLeave; |
| 245 | pTo->xMutexHeld = pFrom->xMutexHeld; |
| 246 | pTo->xMutexNotheld = pFrom->xMutexNotheld; |
drh | 6081c1d | 2015-09-06 02:51:04 +0000 | [diff] [blame] | 247 | sqlite3MemoryBarrier(); |
drh | 92d7652 | 2010-05-05 00:05:24 +0000 | [diff] [blame] | 248 | pTo->xMutexAlloc = pFrom->xMutexAlloc; |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 249 | } |
mistachkin | 04abf08 | 2015-09-12 18:57:45 +0000 | [diff] [blame] | 250 | assert( sqlite3GlobalConfig.mutex.xMutexInit ); |
drh | 92d7652 | 2010-05-05 00:05:24 +0000 | [diff] [blame] | 251 | rc = sqlite3GlobalConfig.mutex.xMutexInit(); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 252 | |
drh | fe5bdb3 | 2009-09-10 17:45:00 +0000 | [diff] [blame] | 253 | #ifdef SQLITE_DEBUG |
| 254 | GLOBAL(int, mutexIsInit) = 1; |
| 255 | #endif |
| 256 | |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 257 | return rc; |
| 258 | } |
| 259 | |
| 260 | /* |
| 261 | ** Shutdown the mutex system. This call frees resources allocated by |
danielk1977 | d025174 | 2008-06-18 18:57:42 +0000 | [diff] [blame] | 262 | ** sqlite3MutexInit(). |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 263 | */ |
danielk1977 | d025174 | 2008-06-18 18:57:42 +0000 | [diff] [blame] | 264 | int sqlite3MutexEnd(void){ |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 265 | int rc = SQLITE_OK; |
danielk1977 | 0a54907 | 2009-02-17 16:29:10 +0000 | [diff] [blame] | 266 | if( sqlite3GlobalConfig.mutex.xMutexEnd ){ |
| 267 | rc = sqlite3GlobalConfig.mutex.xMutexEnd(); |
| 268 | } |
drh | fe5bdb3 | 2009-09-10 17:45:00 +0000 | [diff] [blame] | 269 | |
| 270 | #ifdef SQLITE_DEBUG |
| 271 | GLOBAL(int, mutexIsInit) = 0; |
| 272 | #endif |
| 273 | |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 274 | return rc; |
| 275 | } |
| 276 | |
| 277 | /* |
| 278 | ** Retrieve a pointer to a static mutex or allocate a new dynamic one. |
| 279 | */ |
| 280 | sqlite3_mutex *sqlite3_mutex_alloc(int id){ |
danielk1977 | bc10d77 | 2008-06-18 18:08:39 +0000 | [diff] [blame] | 281 | #ifndef SQLITE_OMIT_AUTOINIT |
drh | d42d0be | 2014-07-30 21:10:12 +0000 | [diff] [blame] | 282 | if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0; |
mistachkin | 2d8ad51 | 2014-10-27 22:06:21 +0000 | [diff] [blame] | 283 | if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0; |
danielk1977 | bc10d77 | 2008-06-18 18:08:39 +0000 | [diff] [blame] | 284 | #endif |
mistachkin | 04abf08 | 2015-09-12 18:57:45 +0000 | [diff] [blame] | 285 | assert( sqlite3GlobalConfig.mutex.xMutexAlloc ); |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 286 | return sqlite3GlobalConfig.mutex.xMutexAlloc(id); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 287 | } |
| 288 | |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 289 | sqlite3_mutex *sqlite3MutexAlloc(int id){ |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 290 | if( !sqlite3GlobalConfig.bCoreMutex ){ |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 291 | return 0; |
| 292 | } |
drh | fe5bdb3 | 2009-09-10 17:45:00 +0000 | [diff] [blame] | 293 | assert( GLOBAL(int, mutexIsInit) ); |
mistachkin | 04abf08 | 2015-09-12 18:57:45 +0000 | [diff] [blame] | 294 | assert( sqlite3GlobalConfig.mutex.xMutexAlloc ); |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 295 | return sqlite3GlobalConfig.mutex.xMutexAlloc(id); |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 296 | } |
| 297 | |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 298 | /* |
| 299 | ** Free a dynamic mutex. |
| 300 | */ |
| 301 | void sqlite3_mutex_free(sqlite3_mutex *p){ |
| 302 | if( p ){ |
mistachkin | 04abf08 | 2015-09-12 18:57:45 +0000 | [diff] [blame] | 303 | assert( sqlite3GlobalConfig.mutex.xMutexFree ); |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 304 | sqlite3GlobalConfig.mutex.xMutexFree(p); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 305 | } |
| 306 | } |
| 307 | |
| 308 | /* |
| 309 | ** Obtain the mutex p. If some other thread already has the mutex, block |
| 310 | ** until it can be obtained. |
| 311 | */ |
| 312 | void sqlite3_mutex_enter(sqlite3_mutex *p){ |
| 313 | if( p ){ |
mistachkin | 04abf08 | 2015-09-12 18:57:45 +0000 | [diff] [blame] | 314 | assert( sqlite3GlobalConfig.mutex.xMutexEnter ); |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 315 | sqlite3GlobalConfig.mutex.xMutexEnter(p); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 316 | } |
| 317 | } |
| 318 | |
| 319 | /* |
| 320 | ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another |
| 321 | ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. |
| 322 | */ |
| 323 | int sqlite3_mutex_try(sqlite3_mutex *p){ |
| 324 | int rc = SQLITE_OK; |
| 325 | if( p ){ |
mistachkin | 04abf08 | 2015-09-12 18:57:45 +0000 | [diff] [blame] | 326 | assert( sqlite3GlobalConfig.mutex.xMutexTry ); |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 327 | return sqlite3GlobalConfig.mutex.xMutexTry(p); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 328 | } |
| 329 | return rc; |
| 330 | } |
| 331 | |
| 332 | /* |
| 333 | ** The sqlite3_mutex_leave() routine exits a mutex that was previously |
| 334 | ** entered by the same thread. The behavior is undefined if the mutex |
| 335 | ** is not currently entered. If a NULL pointer is passed as an argument |
| 336 | ** this function is a no-op. |
| 337 | */ |
| 338 | void sqlite3_mutex_leave(sqlite3_mutex *p){ |
| 339 | if( p ){ |
mistachkin | 04abf08 | 2015-09-12 18:57:45 +0000 | [diff] [blame] | 340 | assert( sqlite3GlobalConfig.mutex.xMutexLeave ); |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 341 | sqlite3GlobalConfig.mutex.xMutexLeave(p); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 342 | } |
| 343 | } |
| 344 | |
| 345 | #ifndef NDEBUG |
| 346 | /* |
| 347 | ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are |
| 348 | ** intended for use inside assert() statements. |
| 349 | */ |
| 350 | int sqlite3_mutex_held(sqlite3_mutex *p){ |
mistachkin | 04abf08 | 2015-09-12 18:57:45 +0000 | [diff] [blame] | 351 | assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld ); |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 352 | return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 353 | } |
| 354 | int sqlite3_mutex_notheld(sqlite3_mutex *p){ |
mistachkin | 04abf08 | 2015-09-12 18:57:45 +0000 | [diff] [blame] | 355 | assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld ); |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 356 | return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 357 | } |
| 358 | #endif |
| 359 | |
drh | e4c88c0 | 2012-01-04 12:57:45 +0000 | [diff] [blame] | 360 | #endif /* !defined(SQLITE_MUTEX_OMIT) */ |