PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/third_party/sqlite/src/src/btmutex.c

https://gitlab.com/jonnialva90/iridium-browser
C | 300 lines | 150 code | 26 blank | 124 comment | 46 complexity | 30d3e1a263a0cf7a36abad4a41920685 MD5 | raw file
  1. /*
  2. ** 2007 August 27
  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. *************************************************************************
  12. **
  13. ** This file contains code used to implement mutexes on Btree objects.
  14. ** This code really belongs in btree.c. But btree.c is getting too
  15. ** big and we want to break it down some. This packaged seemed like
  16. ** a good breakout.
  17. */
  18. #include "btreeInt.h"
  19. #ifndef SQLITE_OMIT_SHARED_CACHE
  20. #if SQLITE_THREADSAFE
  21. /*
  22. ** Obtain the BtShared mutex associated with B-Tree handle p. Also,
  23. ** set BtShared.db to the database handle associated with p and the
  24. ** p->locked boolean to true.
  25. */
  26. static void lockBtreeMutex(Btree *p){
  27. assert( p->locked==0 );
  28. assert( sqlite3_mutex_notheld(p->pBt->mutex) );
  29. assert( sqlite3_mutex_held(p->db->mutex) );
  30. sqlite3_mutex_enter(p->pBt->mutex);
  31. p->pBt->db = p->db;
  32. p->locked = 1;
  33. }
  34. /*
  35. ** Release the BtShared mutex associated with B-Tree handle p and
  36. ** clear the p->locked boolean.
  37. */
  38. static void SQLITE_NOINLINE unlockBtreeMutex(Btree *p){
  39. BtShared *pBt = p->pBt;
  40. assert( p->locked==1 );
  41. assert( sqlite3_mutex_held(pBt->mutex) );
  42. assert( sqlite3_mutex_held(p->db->mutex) );
  43. assert( p->db==pBt->db );
  44. sqlite3_mutex_leave(pBt->mutex);
  45. p->locked = 0;
  46. }
  47. /* Forward reference */
  48. static void SQLITE_NOINLINE btreeLockCarefully(Btree *p);
  49. /*
  50. ** Enter a mutex on the given BTree object.
  51. **
  52. ** If the object is not sharable, then no mutex is ever required
  53. ** and this routine is a no-op. The underlying mutex is non-recursive.
  54. ** But we keep a reference count in Btree.wantToLock so the behavior
  55. ** of this interface is recursive.
  56. **
  57. ** To avoid deadlocks, multiple Btrees are locked in the same order
  58. ** by all database connections. The p->pNext is a list of other
  59. ** Btrees belonging to the same database connection as the p Btree
  60. ** which need to be locked after p. If we cannot get a lock on
  61. ** p, then first unlock all of the others on p->pNext, then wait
  62. ** for the lock to become available on p, then relock all of the
  63. ** subsequent Btrees that desire a lock.
  64. */
  65. void sqlite3BtreeEnter(Btree *p){
  66. /* Some basic sanity checking on the Btree. The list of Btrees
  67. ** connected by pNext and pPrev should be in sorted order by
  68. ** Btree.pBt value. All elements of the list should belong to
  69. ** the same connection. Only shared Btrees are on the list. */
  70. assert( p->pNext==0 || p->pNext->pBt>p->pBt );
  71. assert( p->pPrev==0 || p->pPrev->pBt<p->pBt );
  72. assert( p->pNext==0 || p->pNext->db==p->db );
  73. assert( p->pPrev==0 || p->pPrev->db==p->db );
  74. assert( p->sharable || (p->pNext==0 && p->pPrev==0) );
  75. /* Check for locking consistency */
  76. assert( !p->locked || p->wantToLock>0 );
  77. assert( p->sharable || p->wantToLock==0 );
  78. /* We should already hold a lock on the database connection */
  79. assert( sqlite3_mutex_held(p->db->mutex) );
  80. /* Unless the database is sharable and unlocked, then BtShared.db
  81. ** should already be set correctly. */
  82. assert( (p->locked==0 && p->sharable) || p->pBt->db==p->db );
  83. if( !p->sharable ) return;
  84. p->wantToLock++;
  85. if( p->locked ) return;
  86. btreeLockCarefully(p);
  87. }
  88. /* This is a helper function for sqlite3BtreeLock(). By moving
  89. ** complex, but seldom used logic, out of sqlite3BtreeLock() and
  90. ** into this routine, we avoid unnecessary stack pointer changes
  91. ** and thus help the sqlite3BtreeLock() routine to run much faster
  92. ** in the common case.
  93. */
  94. static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){
  95. Btree *pLater;
  96. /* In most cases, we should be able to acquire the lock we
  97. ** want without having to go through the ascending lock
  98. ** procedure that follows. Just be sure not to block.
  99. */
  100. if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){
  101. p->pBt->db = p->db;
  102. p->locked = 1;
  103. return;
  104. }
  105. /* To avoid deadlock, first release all locks with a larger
  106. ** BtShared address. Then acquire our lock. Then reacquire
  107. ** the other BtShared locks that we used to hold in ascending
  108. ** order.
  109. */
  110. for(pLater=p->pNext; pLater; pLater=pLater->pNext){
  111. assert( pLater->sharable );
  112. assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt );
  113. assert( !pLater->locked || pLater->wantToLock>0 );
  114. if( pLater->locked ){
  115. unlockBtreeMutex(pLater);
  116. }
  117. }
  118. lockBtreeMutex(p);
  119. for(pLater=p->pNext; pLater; pLater=pLater->pNext){
  120. if( pLater->wantToLock ){
  121. lockBtreeMutex(pLater);
  122. }
  123. }
  124. }
  125. /*
  126. ** Exit the recursive mutex on a Btree.
  127. */
  128. void sqlite3BtreeLeave(Btree *p){
  129. if( p->sharable ){
  130. assert( p->wantToLock>0 );
  131. p->wantToLock--;
  132. if( p->wantToLock==0 ){
  133. unlockBtreeMutex(p);
  134. }
  135. }
  136. }
  137. #ifndef NDEBUG
  138. /*
  139. ** Return true if the BtShared mutex is held on the btree, or if the
  140. ** B-Tree is not marked as sharable.
  141. **
  142. ** This routine is used only from within assert() statements.
  143. */
  144. int sqlite3BtreeHoldsMutex(Btree *p){
  145. assert( p->sharable==0 || p->locked==0 || p->wantToLock>0 );
  146. assert( p->sharable==0 || p->locked==0 || p->db==p->pBt->db );
  147. assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->pBt->mutex) );
  148. assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->db->mutex) );
  149. return (p->sharable==0 || p->locked);
  150. }
  151. #endif
  152. #ifndef SQLITE_OMIT_INCRBLOB
  153. /*
  154. ** Enter and leave a mutex on a Btree given a cursor owned by that
  155. ** Btree. These entry points are used by incremental I/O and can be
  156. ** omitted if that module is not used.
  157. */
  158. void sqlite3BtreeEnterCursor(BtCursor *pCur){
  159. sqlite3BtreeEnter(pCur->pBtree);
  160. }
  161. void sqlite3BtreeLeaveCursor(BtCursor *pCur){
  162. sqlite3BtreeLeave(pCur->pBtree);
  163. }
  164. #endif /* SQLITE_OMIT_INCRBLOB */
  165. /*
  166. ** Enter the mutex on every Btree associated with a database
  167. ** connection. This is needed (for example) prior to parsing
  168. ** a statement since we will be comparing table and column names
  169. ** against all schemas and we do not want those schemas being
  170. ** reset out from under us.
  171. **
  172. ** There is a corresponding leave-all procedures.
  173. **
  174. ** Enter the mutexes in accending order by BtShared pointer address
  175. ** to avoid the possibility of deadlock when two threads with
  176. ** two or more btrees in common both try to lock all their btrees
  177. ** at the same instant.
  178. */
  179. void sqlite3BtreeEnterAll(sqlite3 *db){
  180. int i;
  181. Btree *p;
  182. assert( sqlite3_mutex_held(db->mutex) );
  183. for(i=0; i<db->nDb; i++){
  184. p = db->aDb[i].pBt;
  185. if( p ) sqlite3BtreeEnter(p);
  186. }
  187. }
  188. void sqlite3BtreeLeaveAll(sqlite3 *db){
  189. int i;
  190. Btree *p;
  191. assert( sqlite3_mutex_held(db->mutex) );
  192. for(i=0; i<db->nDb; i++){
  193. p = db->aDb[i].pBt;
  194. if( p ) sqlite3BtreeLeave(p);
  195. }
  196. }
  197. /*
  198. ** Return true if a particular Btree requires a lock. Return FALSE if
  199. ** no lock is ever required since it is not sharable.
  200. */
  201. int sqlite3BtreeSharable(Btree *p){
  202. return p->sharable;
  203. }
  204. #ifndef NDEBUG
  205. /*
  206. ** Return true if the current thread holds the database connection
  207. ** mutex and all required BtShared mutexes.
  208. **
  209. ** This routine is used inside assert() statements only.
  210. */
  211. int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
  212. int i;
  213. if( !sqlite3_mutex_held(db->mutex) ){
  214. return 0;
  215. }
  216. for(i=0; i<db->nDb; i++){
  217. Btree *p;
  218. p = db->aDb[i].pBt;
  219. if( p && p->sharable &&
  220. (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){
  221. return 0;
  222. }
  223. }
  224. return 1;
  225. }
  226. #endif /* NDEBUG */
  227. #ifndef NDEBUG
  228. /*
  229. ** Return true if the correct mutexes are held for accessing the
  230. ** db->aDb[iDb].pSchema structure. The mutexes required for schema
  231. ** access are:
  232. **
  233. ** (1) The mutex on db
  234. ** (2) if iDb!=1, then the mutex on db->aDb[iDb].pBt.
  235. **
  236. ** If pSchema is not NULL, then iDb is computed from pSchema and
  237. ** db using sqlite3SchemaToIndex().
  238. */
  239. int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){
  240. Btree *p;
  241. assert( db!=0 );
  242. if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema);
  243. assert( iDb>=0 && iDb<db->nDb );
  244. if( !sqlite3_mutex_held(db->mutex) ) return 0;
  245. if( iDb==1 ) return 1;
  246. p = db->aDb[iDb].pBt;
  247. assert( p!=0 );
  248. return p->sharable==0 || p->locked==1;
  249. }
  250. #endif /* NDEBUG */
  251. #else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */
  252. /*
  253. ** The following are special cases for mutex enter routines for use
  254. ** in single threaded applications that use shared cache. Except for
  255. ** these two routines, all mutex operations are no-ops in that case and
  256. ** are null #defines in btree.h.
  257. **
  258. ** If shared cache is disabled, then all btree mutex routines, including
  259. ** the ones below, are no-ops and are null #defines in btree.h.
  260. */
  261. void sqlite3BtreeEnter(Btree *p){
  262. p->pBt->db = p->db;
  263. }
  264. void sqlite3BtreeEnterAll(sqlite3 *db){
  265. int i;
  266. for(i=0; i<db->nDb; i++){
  267. Btree *p = db->aDb[i].pBt;
  268. if( p ){
  269. p->pBt->db = p->db;
  270. }
  271. }
  272. }
  273. #endif /* if SQLITE_THREADSAFE */
  274. #endif /* ifndef SQLITE_OMIT_SHARED_CACHE */