xref: /sqlite-3.40.0/src/mutex.c (revision 8a29dfde)
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 *************************************************************************
12 ** This file contains the C functions that implement mutexes.
13 **
14 ** The implementation in this file does not provide any mutual
15 ** exclusion and is thus suitable for use only in applications
16 ** that use SQLite in a single thread.  But this implementation
17 ** does do a lot of error checking on mutexes to make sure they
18 ** are called correctly and at appropriate times.  Hence, this
19 ** implementation is suitable for testing.
20 ** debugging purposes
21 **
22 ** $Id: mutex.c,v 1.17 2008/03/26 18:34:43 danielk1977 Exp $
23 */
24 #include "sqliteInt.h"
25 
26 #ifdef SQLITE_MUTEX_NOOP_DEBUG
27 /*
28 ** In this implementation, mutexes do not provide any mutual exclusion.
29 ** But the error checking is provided.  This implementation is useful
30 ** for test purposes.
31 */
32 
33 /*
34 ** The mutex object
35 */
36 struct sqlite3_mutex {
37   int id;     /* The mutex type */
38   int cnt;    /* Number of entries without a matching leave */
39 };
40 
41 /*
42 ** The sqlite3_mutex_alloc() routine allocates a new
43 ** mutex and returns a pointer to it.  If it returns NULL
44 ** that means that a mutex could not be allocated.
45 */
46 sqlite3_mutex *sqlite3_mutex_alloc(int id){
47   static sqlite3_mutex aStatic[6];
48   sqlite3_mutex *pNew = 0;
49   switch( id ){
50     case SQLITE_MUTEX_FAST:
51     case SQLITE_MUTEX_RECURSIVE: {
52       pNew = sqlite3_malloc(sizeof(*pNew));
53       if( pNew ){
54         pNew->id = id;
55         pNew->cnt = 0;
56       }
57       break;
58     }
59     default: {
60       assert( id-2 >= 0 );
61       assert( id-2 < sizeof(aStatic)/sizeof(aStatic[0]) );
62       pNew = &aStatic[id-2];
63       pNew->id = id;
64       break;
65     }
66   }
67   return pNew;
68 }
69 
70 /*
71 ** This routine deallocates a previously allocated mutex.
72 */
73 void sqlite3_mutex_free(sqlite3_mutex *p){
74   assert( p );
75   assert( p->cnt==0 );
76   assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
77   sqlite3_free(p);
78 }
79 
80 /*
81 ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
82 ** to enter a mutex.  If another thread is already within the mutex,
83 ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
84 ** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
85 ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
86 ** be entered multiple times by the same thread.  In such cases the,
87 ** mutex must be exited an equal number of times before another thread
88 ** can enter.  If the same thread tries to enter any other kind of mutex
89 ** more than once, the behavior is undefined.
90 */
91 void sqlite3_mutex_enter(sqlite3_mutex *p){
92   assert( p );
93   assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
94   p->cnt++;
95 }
96 int sqlite3_mutex_try(sqlite3_mutex *p){
97   assert( p );
98   assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
99   p->cnt++;
100   return SQLITE_OK;
101 }
102 
103 /*
104 ** The sqlite3_mutex_leave() routine exits a mutex that was
105 ** previously entered by the same thread.  The behavior
106 ** is undefined if the mutex is not currently entered or
107 ** is not currently allocated.  SQLite will never do either.
108 */
109 void sqlite3_mutex_leave(sqlite3_mutex *p){
110   assert( p );
111   assert( sqlite3_mutex_held(p) );
112   p->cnt--;
113   assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
114 }
115 
116 /*
117 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
118 ** intended for use inside assert() statements.
119 */
120 int sqlite3_mutex_held(sqlite3_mutex *p){
121   return p==0 || p->cnt>0;
122 }
123 int sqlite3_mutex_notheld(sqlite3_mutex *p){
124   return p==0 || p->cnt==0;
125 }
126 #endif /* SQLITE_MUTEX_NOOP_DEBUG */
127