xref: /sqlite-3.40.0/src/mutex_noop.c (revision 93de6538)
1 /*
2 ** 2008 October 07
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 ** This 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.  The routines defined
17 ** here are place-holders.  Applications can substitute working
18 ** mutex routines at start-time using the
19 **
20 **     sqlite3_config(SQLITE_CONFIG_MUTEX,...)
21 **
22 ** interface.
23 **
24 ** If compiled with SQLITE_DEBUG, then additional logic is inserted
25 ** that does error checking on mutexes to make sure they are being
26 ** called correctly.
27 */
28 #include "sqliteInt.h"
29 
30 #ifndef SQLITE_MUTEX_OMIT
31 
32 #ifndef SQLITE_DEBUG
33 /*
34 ** Stub routines for all mutex methods.
35 **
36 ** This routines provide no mutual exclusion or error checking.
37 */
noopMutexInit(void)38 static int noopMutexInit(void){ return SQLITE_OK; }
noopMutexEnd(void)39 static int noopMutexEnd(void){ return SQLITE_OK; }
noopMutexAlloc(int id)40 static sqlite3_mutex *noopMutexAlloc(int id){
41   UNUSED_PARAMETER(id);
42   return (sqlite3_mutex*)8;
43 }
noopMutexFree(sqlite3_mutex * p)44 static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
noopMutexEnter(sqlite3_mutex * p)45 static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
noopMutexTry(sqlite3_mutex * p)46 static int noopMutexTry(sqlite3_mutex *p){
47   UNUSED_PARAMETER(p);
48   return SQLITE_OK;
49 }
noopMutexLeave(sqlite3_mutex * p)50 static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
51 
sqlite3NoopMutex(void)52 sqlite3_mutex_methods const *sqlite3NoopMutex(void){
53   static const sqlite3_mutex_methods sMutex = {
54     noopMutexInit,
55     noopMutexEnd,
56     noopMutexAlloc,
57     noopMutexFree,
58     noopMutexEnter,
59     noopMutexTry,
60     noopMutexLeave,
61 
62     0,
63     0,
64   };
65 
66   return &sMutex;
67 }
68 #endif /* !SQLITE_DEBUG */
69 
70 #ifdef SQLITE_DEBUG
71 /*
72 ** In this implementation, error checking is provided for testing
73 ** and debugging purposes.  The mutexes still do not provide any
74 ** mutual exclusion.
75 */
76 
77 /*
78 ** The mutex object
79 */
80 typedef struct sqlite3_debug_mutex {
81   int id;     /* The mutex type */
82   int cnt;    /* Number of entries without a matching leave */
83 } sqlite3_debug_mutex;
84 
85 /*
86 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
87 ** intended for use inside assert() statements.
88 */
debugMutexHeld(sqlite3_mutex * pX)89 static int debugMutexHeld(sqlite3_mutex *pX){
90   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
91   return p==0 || p->cnt>0;
92 }
debugMutexNotheld(sqlite3_mutex * pX)93 static int debugMutexNotheld(sqlite3_mutex *pX){
94   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
95   return p==0 || p->cnt==0;
96 }
97 
98 /*
99 ** Initialize and deinitialize the mutex subsystem.
100 */
debugMutexInit(void)101 static int debugMutexInit(void){ return SQLITE_OK; }
debugMutexEnd(void)102 static int debugMutexEnd(void){ return SQLITE_OK; }
103 
104 /*
105 ** The sqlite3_mutex_alloc() routine allocates a new
106 ** mutex and returns a pointer to it.  If it returns NULL
107 ** that means that a mutex could not be allocated.
108 */
debugMutexAlloc(int id)109 static sqlite3_mutex *debugMutexAlloc(int id){
110   static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_VFS3 - 1];
111   sqlite3_debug_mutex *pNew = 0;
112   switch( id ){
113     case SQLITE_MUTEX_FAST:
114     case SQLITE_MUTEX_RECURSIVE: {
115       pNew = sqlite3Malloc(sizeof(*pNew));
116       if( pNew ){
117         pNew->id = id;
118         pNew->cnt = 0;
119       }
120       break;
121     }
122     default: {
123 #ifdef SQLITE_ENABLE_API_ARMOR
124       if( id-2<0 || id-2>=ArraySize(aStatic) ){
125         (void)SQLITE_MISUSE_BKPT;
126         return 0;
127       }
128 #endif
129       pNew = &aStatic[id-2];
130       pNew->id = id;
131       break;
132     }
133   }
134   return (sqlite3_mutex*)pNew;
135 }
136 
137 /*
138 ** This routine deallocates a previously allocated mutex.
139 */
debugMutexFree(sqlite3_mutex * pX)140 static void debugMutexFree(sqlite3_mutex *pX){
141   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
142   assert( p->cnt==0 );
143   if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){
144     sqlite3_free(p);
145   }else{
146 #ifdef SQLITE_ENABLE_API_ARMOR
147     (void)SQLITE_MISUSE_BKPT;
148 #endif
149   }
150 }
151 
152 /*
153 ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
154 ** to enter a mutex.  If another thread is already within the mutex,
155 ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
156 ** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
157 ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
158 ** be entered multiple times by the same thread.  In such cases the,
159 ** mutex must be exited an equal number of times before another thread
160 ** can enter.  If the same thread tries to enter any other kind of mutex
161 ** more than once, the behavior is undefined.
162 */
debugMutexEnter(sqlite3_mutex * pX)163 static void debugMutexEnter(sqlite3_mutex *pX){
164   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
165   assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
166   p->cnt++;
167 }
debugMutexTry(sqlite3_mutex * pX)168 static int debugMutexTry(sqlite3_mutex *pX){
169   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
170   assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
171   p->cnt++;
172   return SQLITE_OK;
173 }
174 
175 /*
176 ** The sqlite3_mutex_leave() routine exits a mutex that was
177 ** previously entered by the same thread.  The behavior
178 ** is undefined if the mutex is not currently entered or
179 ** is not currently allocated.  SQLite will never do either.
180 */
debugMutexLeave(sqlite3_mutex * pX)181 static void debugMutexLeave(sqlite3_mutex *pX){
182   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
183   assert( debugMutexHeld(pX) );
184   p->cnt--;
185   assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
186 }
187 
sqlite3NoopMutex(void)188 sqlite3_mutex_methods const *sqlite3NoopMutex(void){
189   static const sqlite3_mutex_methods sMutex = {
190     debugMutexInit,
191     debugMutexEnd,
192     debugMutexAlloc,
193     debugMutexFree,
194     debugMutexEnter,
195     debugMutexTry,
196     debugMutexLeave,
197 
198     debugMutexHeld,
199     debugMutexNotheld
200   };
201 
202   return &sMutex;
203 }
204 #endif /* SQLITE_DEBUG */
205 
206 /*
207 ** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation
208 ** is used regardless of the run-time threadsafety setting.
209 */
210 #ifdef SQLITE_MUTEX_NOOP
sqlite3DefaultMutex(void)211 sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
212   return sqlite3NoopMutex();
213 }
214 #endif /* defined(SQLITE_MUTEX_NOOP) */
215 #endif /* !defined(SQLITE_MUTEX_OMIT) */
216