btmutex.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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. ** $Id: btmutex.c,v 1.8 2007/12/07 18:55:28 drh Exp $
  14. **
  15. ** This file contains code used to implement mutexes on Btree objects.
  16. ** This code really belongs in btree.c. But btree.c is getting too
  17. ** big and we want to break it down some. This packaged seemed like
  18. ** a good breakout.
  19. */
  20. #include "btreeInt.h"
  21. #if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE)
  22. /*
  23. ** Enter a mutex on the given BTree object.
  24. **
  25. ** If the object is not sharable, then no mutex is ever required
  26. ** and this routine is a no-op. The underlying mutex is non-recursive.
  27. ** But we keep a reference count in Btree.wantToLock so the behavior
  28. ** of this interface is recursive.
  29. **
  30. ** To avoid deadlocks, multiple Btrees are locked in the same order
  31. ** by all database connections. The p->pNext is a list of other
  32. ** Btrees belonging to the same database connection as the p Btree
  33. ** which need to be locked after p. If we cannot get a lock on
  34. ** p, then first unlock all of the others on p->pNext, then wait
  35. ** for the lock to become available on p, then relock all of the
  36. ** subsequent Btrees that desire a lock.
  37. */
  38. void sqlite3BtreeEnter(Btree *p){
  39. Btree *pLater;
  40. /* Some basic sanity checking on the Btree. The list of Btrees
  41. ** connected by pNext and pPrev should be in sorted order by
  42. ** Btree.pBt value. All elements of the list should belong to
  43. ** the same connection. Only shared Btrees are on the list. */
  44. assert( p->pNext==0 || p->pNext->pBt>p->pBt );
  45. assert( p->pPrev==0 || p->pPrev->pBt<p->pBt );
  46. assert( p->pNext==0 || p->pNext->db==p->db );
  47. assert( p->pPrev==0 || p->pPrev->db==p->db );
  48. assert( p->sharable || (p->pNext==0 && p->pPrev==0) );
  49. /* Check for locking consistency */
  50. assert( !p->locked || p->wantToLock>0 );
  51. assert( p->sharable || p->wantToLock==0 );
  52. /* We should already hold a lock on the database connection */
  53. assert( sqlite3_mutex_held(p->db->mutex) );
  54. if( !p->sharable ) return;
  55. p->wantToLock++;
  56. if( p->locked ) return;
  57. /* In most cases, we should be able to acquire the lock we
  58. ** want without having to go throught the ascending lock
  59. ** procedure that follows. Just be sure not to block.
  60. */
  61. if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){
  62. p->locked = 1;
  63. return;
  64. }
  65. /* To avoid deadlock, first release all locks with a larger
  66. ** BtShared address. Then acquire our lock. Then reacquire
  67. ** the other BtShared locks that we used to hold in ascending
  68. ** order.
  69. */
  70. for(pLater=p->pNext; pLater; pLater=pLater->pNext){
  71. assert( pLater->sharable );
  72. assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt );
  73. assert( !pLater->locked || pLater->wantToLock>0 );
  74. if( pLater->locked ){
  75. sqlite3_mutex_leave(pLater->pBt->mutex);
  76. pLater->locked = 0;
  77. }
  78. }
  79. sqlite3_mutex_enter(p->pBt->mutex);
  80. p->locked = 1;
  81. for(pLater=p->pNext; pLater; pLater=pLater->pNext){
  82. if( pLater->wantToLock ){
  83. sqlite3_mutex_enter(pLater->pBt->mutex);
  84. pLater->locked = 1;
  85. }
  86. }
  87. }
  88. /*
  89. ** Exit the recursive mutex on a Btree.
  90. */
  91. void sqlite3BtreeLeave(Btree *p){
  92. if( p->sharable ){
  93. assert( p->wantToLock>0 );
  94. p->wantToLock--;
  95. if( p->wantToLock==0 ){
  96. assert( p->locked );
  97. sqlite3_mutex_leave(p->pBt->mutex);
  98. p->locked = 0;
  99. }
  100. }
  101. }
  102. #ifndef NDEBUG
  103. /*
  104. ** Return true if the BtShared mutex is held on the btree.
  105. **
  106. ** This routine makes no determination one why or another if the
  107. ** database connection mutex is held.
  108. **
  109. ** This routine is used only from within assert() statements.
  110. */
  111. int sqlite3BtreeHoldsMutex(Btree *p){
  112. return (p->sharable==0 ||
  113. (p->locked && p->wantToLock && sqlite3_mutex_held(p->pBt->mutex)));
  114. }
  115. #endif
  116. #ifndef SQLITE_OMIT_INCRBLOB
  117. /*
  118. ** Enter and leave a mutex on a Btree given a cursor owned by that
  119. ** Btree. These entry points are used by incremental I/O and can be
  120. ** omitted if that module is not used.
  121. */
  122. void sqlite3BtreeEnterCursor(BtCursor *pCur){
  123. sqlite3BtreeEnter(pCur->pBtree);
  124. }
  125. void sqlite3BtreeLeaveCursor(BtCursor *pCur){
  126. sqlite3BtreeLeave(pCur->pBtree);
  127. }
  128. #endif /* SQLITE_OMIT_INCRBLOB */
  129. /*
  130. ** Enter the mutex on every Btree associated with a database
  131. ** connection. This is needed (for example) prior to parsing
  132. ** a statement since we will be comparing table and column names
  133. ** against all schemas and we do not want those schemas being
  134. ** reset out from under us.
  135. **
  136. ** There is a corresponding leave-all procedures.
  137. **
  138. ** Enter the mutexes in accending order by BtShared pointer address
  139. ** to avoid the possibility of deadlock when two threads with
  140. ** two or more btrees in common both try to lock all their btrees
  141. ** at the same instant.
  142. */
  143. void sqlite3BtreeEnterAll(sqlite3 *db){
  144. int i;
  145. Btree *p, *pLater;
  146. assert( sqlite3_mutex_held(db->mutex) );
  147. for(i=0; i<db->nDb; i++){
  148. p = db->aDb[i].pBt;
  149. if( p && p->sharable ){
  150. p->wantToLock++;
  151. if( !p->locked ){
  152. assert( p->wantToLock==1 );
  153. while( p->pPrev ) p = p->pPrev;
  154. while( p->locked && p->pNext ) p = p->pNext;
  155. for(pLater = p->pNext; pLater; pLater=pLater->pNext){
  156. if( pLater->locked ){
  157. sqlite3_mutex_leave(pLater->pBt->mutex);
  158. pLater->locked = 0;
  159. }
  160. }
  161. while( p ){
  162. sqlite3_mutex_enter(p->pBt->mutex);
  163. p->locked++;
  164. p = p->pNext;
  165. }
  166. }
  167. }
  168. }
  169. }
  170. void sqlite3BtreeLeaveAll(sqlite3 *db){
  171. int i;
  172. Btree *p;
  173. assert( sqlite3_mutex_held(db->mutex) );
  174. for(i=0; i<db->nDb; i++){
  175. p = db->aDb[i].pBt;
  176. if( p && p->sharable ){
  177. assert( p->wantToLock>0 );
  178. p->wantToLock--;
  179. if( p->wantToLock==0 ){
  180. assert( p->locked );
  181. sqlite3_mutex_leave(p->pBt->mutex);
  182. p->locked = 0;
  183. }
  184. }
  185. }
  186. }
  187. #ifndef NDEBUG
  188. /*
  189. ** Return true if the current thread holds the database connection
  190. ** mutex and all required BtShared mutexes.
  191. **
  192. ** This routine is used inside assert() statements only.
  193. */
  194. int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
  195. int i;
  196. if( !sqlite3_mutex_held(db->mutex) ){
  197. return 0;
  198. }
  199. for(i=0; i<db->nDb; i++){
  200. Btree *p;
  201. p = db->aDb[i].pBt;
  202. if( p && p->sharable &&
  203. (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){
  204. return 0;
  205. }
  206. }
  207. return 1;
  208. }
  209. #endif /* NDEBUG */
  210. /*
  211. ** Potentially dd a new Btree pointer to a BtreeMutexArray.
  212. ** Really only add the Btree if it can possibly be shared with
  213. ** another database connection.
  214. **
  215. ** The Btrees are kept in sorted order by pBtree->pBt. That
  216. ** way when we go to enter all the mutexes, we can enter them
  217. ** in order without every having to backup and retry and without
  218. ** worrying about deadlock.
  219. **
  220. ** The number of shared btrees will always be small (usually 0 or 1)
  221. ** so an insertion sort is an adequate algorithm here.
  222. */
  223. void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){
  224. int i, j;
  225. BtShared *pBt;
  226. if( pBtree==0 || pBtree->sharable==0 ) return;
  227. #ifndef NDEBUG
  228. {
  229. for(i=0; i<pArray->nMutex; i++){
  230. assert( pArray->aBtree[i]!=pBtree );
  231. }
  232. }
  233. #endif
  234. assert( pArray->nMutex>=0 );
  235. assert( pArray->nMutex<sizeof(pArray->aBtree)/sizeof(pArray->aBtree[0])-1 );
  236. pBt = pBtree->pBt;
  237. for(i=0; i<pArray->nMutex; i++){
  238. assert( pArray->aBtree[i]!=pBtree );
  239. if( pArray->aBtree[i]->pBt>pBt ){
  240. for(j=pArray->nMutex; j>i; j--){
  241. pArray->aBtree[j] = pArray->aBtree[j-1];
  242. }
  243. pArray->aBtree[i] = pBtree;
  244. pArray->nMutex++;
  245. return;
  246. }
  247. }
  248. pArray->aBtree[pArray->nMutex++] = pBtree;
  249. }
  250. /*
  251. ** Enter the mutex of every btree in the array. This routine is
  252. ** called at the beginning of sqlite3VdbeExec(). The mutexes are
  253. ** exited at the end of the same function.
  254. */
  255. void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){
  256. int i;
  257. for(i=0; i<pArray->nMutex; i++){
  258. Btree *p = pArray->aBtree[i];
  259. /* Some basic sanity checking */
  260. assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
  261. assert( !p->locked || p->wantToLock>0 );
  262. /* We should already hold a lock on the database connection */
  263. assert( sqlite3_mutex_held(p->db->mutex) );
  264. p->wantToLock++;
  265. if( !p->locked && p->sharable ){
  266. sqlite3_mutex_enter(p->pBt->mutex);
  267. p->locked = 1;
  268. }
  269. }
  270. }
  271. /*
  272. ** Leave the mutex of every btree in the group.
  273. */
  274. void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){
  275. int i;
  276. for(i=0; i<pArray->nMutex; i++){
  277. Btree *p = pArray->aBtree[i];
  278. /* Some basic sanity checking */
  279. assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
  280. assert( p->locked || !p->sharable );
  281. assert( p->wantToLock>0 );
  282. /* We should already hold a lock on the database connection */
  283. assert( sqlite3_mutex_held(p->db->mutex) );
  284. p->wantToLock--;
  285. if( p->wantToLock==0 && p->locked ){
  286. sqlite3_mutex_leave(p->pBt->mutex);
  287. p->locked = 0;
  288. }
  289. }
  290. }
  291. #endif /* SQLITE_THREADSAFE && !SQLITE_OMIT_SHARED_CACHE */