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. |
| 15 | |
drh | 437b901 | 2007-08-28 16:34:42 +0000 | [diff] [blame] | 16 | ** |
drh | 18472fa | 2008-10-07 15:25:48 +0000 | [diff] [blame] | 17 | ** $Id: mutex.c,v 1.29 2008/10/07 15:25:48 drh Exp $ |
drh | 90f6a5b | 2007-08-15 13:04:54 +0000 | [diff] [blame] | 18 | */ |
| 19 | #include "sqliteInt.h" |
| 20 | |
drh | 18472fa | 2008-10-07 15:25:48 +0000 | [diff] [blame] | 21 | #ifndef SQLITE_MUTEX_OMIT |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 22 | /* |
| 23 | ** Initialize the mutex system. |
| 24 | */ |
danielk1977 | d025174 | 2008-06-18 18:57:42 +0000 | [diff] [blame] | 25 | int sqlite3MutexInit(void){ |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 26 | int rc = SQLITE_OK; |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 27 | if( sqlite3GlobalConfig.bCoreMutex ){ |
| 28 | if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){ |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 29 | /* If the xMutexAlloc method has not been set, then the user did not |
| 30 | ** install a mutex implementation via sqlite3_config() prior to |
| 31 | ** sqlite3_initialize() being called. This block copies pointers to |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 32 | ** the default implementation into the sqlite3GlobalConfig structure. |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 33 | ** |
| 34 | ** The danger is that although sqlite3_config() is not a threadsafe |
| 35 | ** API, sqlite3_initialize() is, and so multiple threads may be |
| 36 | ** attempting to run this function simultaneously. To guard write |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 37 | ** access to the sqlite3GlobalConfig structure, the 'MASTER' static mutex |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 38 | ** is obtained before modifying it. |
| 39 | */ |
| 40 | sqlite3_mutex_methods *p = sqlite3DefaultMutex(); |
| 41 | sqlite3_mutex *pMaster = 0; |
| 42 | |
| 43 | rc = p->xMutexInit(); |
| 44 | if( rc==SQLITE_OK ){ |
| 45 | pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER); |
| 46 | assert(pMaster); |
| 47 | p->xMutexEnter(pMaster); |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 48 | assert( sqlite3GlobalConfig.mutex.xMutexAlloc==0 |
| 49 | || sqlite3GlobalConfig.mutex.xMutexAlloc==p->xMutexAlloc |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 50 | ); |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 51 | if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){ |
| 52 | sqlite3GlobalConfig.mutex = *p; |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 53 | } |
| 54 | p->xMutexLeave(pMaster); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 55 | } |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 56 | }else{ |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 57 | rc = sqlite3GlobalConfig.mutex.xMutexInit(); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 58 | } |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | return rc; |
| 62 | } |
| 63 | |
| 64 | /* |
| 65 | ** Shutdown the mutex system. This call frees resources allocated by |
danielk1977 | d025174 | 2008-06-18 18:57:42 +0000 | [diff] [blame] | 66 | ** sqlite3MutexInit(). |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 67 | */ |
danielk1977 | d025174 | 2008-06-18 18:57:42 +0000 | [diff] [blame] | 68 | int sqlite3MutexEnd(void){ |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 69 | int rc = SQLITE_OK; |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 70 | rc = sqlite3GlobalConfig.mutex.xMutexEnd(); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 71 | return rc; |
| 72 | } |
| 73 | |
| 74 | /* |
| 75 | ** Retrieve a pointer to a static mutex or allocate a new dynamic one. |
| 76 | */ |
| 77 | sqlite3_mutex *sqlite3_mutex_alloc(int id){ |
danielk1977 | bc10d77 | 2008-06-18 18:08:39 +0000 | [diff] [blame] | 78 | #ifndef SQLITE_OMIT_AUTOINIT |
| 79 | if( sqlite3_initialize() ) return 0; |
| 80 | #endif |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 81 | return sqlite3GlobalConfig.mutex.xMutexAlloc(id); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 82 | } |
| 83 | |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 84 | sqlite3_mutex *sqlite3MutexAlloc(int id){ |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 85 | if( !sqlite3GlobalConfig.bCoreMutex ){ |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 86 | return 0; |
| 87 | } |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 88 | return sqlite3GlobalConfig.mutex.xMutexAlloc(id); |
danielk1977 | 59f8c08 | 2008-06-18 17:09:10 +0000 | [diff] [blame] | 89 | } |
| 90 | |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 91 | /* |
| 92 | ** Free a dynamic mutex. |
| 93 | */ |
| 94 | void sqlite3_mutex_free(sqlite3_mutex *p){ |
| 95 | if( p ){ |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 96 | sqlite3GlobalConfig.mutex.xMutexFree(p); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 97 | } |
| 98 | } |
| 99 | |
| 100 | /* |
| 101 | ** Obtain the mutex p. If some other thread already has the mutex, block |
| 102 | ** until it can be obtained. |
| 103 | */ |
| 104 | void sqlite3_mutex_enter(sqlite3_mutex *p){ |
| 105 | if( p ){ |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 106 | sqlite3GlobalConfig.mutex.xMutexEnter(p); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 107 | } |
| 108 | } |
| 109 | |
| 110 | /* |
| 111 | ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another |
| 112 | ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. |
| 113 | */ |
| 114 | int sqlite3_mutex_try(sqlite3_mutex *p){ |
| 115 | int rc = SQLITE_OK; |
| 116 | if( p ){ |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 117 | return sqlite3GlobalConfig.mutex.xMutexTry(p); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 118 | } |
| 119 | return rc; |
| 120 | } |
| 121 | |
| 122 | /* |
| 123 | ** The sqlite3_mutex_leave() routine exits a mutex that was previously |
| 124 | ** entered by the same thread. The behavior is undefined if the mutex |
| 125 | ** is not currently entered. If a NULL pointer is passed as an argument |
| 126 | ** this function is a no-op. |
| 127 | */ |
| 128 | void sqlite3_mutex_leave(sqlite3_mutex *p){ |
| 129 | if( p ){ |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 130 | sqlite3GlobalConfig.mutex.xMutexLeave(p); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 131 | } |
| 132 | } |
| 133 | |
| 134 | #ifndef NDEBUG |
| 135 | /* |
| 136 | ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are |
| 137 | ** intended for use inside assert() statements. |
| 138 | */ |
| 139 | int sqlite3_mutex_held(sqlite3_mutex *p){ |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 140 | return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 141 | } |
| 142 | int sqlite3_mutex_notheld(sqlite3_mutex *p){ |
danielk1977 | 075c23a | 2008-09-01 18:34:20 +0000 | [diff] [blame] | 143 | return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); |
danielk1977 | 6d2ab0e | 2008-06-17 17:21:18 +0000 | [diff] [blame] | 144 | } |
| 145 | #endif |
| 146 | |
drh | 18472fa | 2008-10-07 15:25:48 +0000 | [diff] [blame] | 147 | #endif /* SQLITE_OMIT_MUTEX */ |