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*/
38static int noopMutexInit(void){ return SQLITE_OK; }
39static int noopMutexEnd(void){ return SQLITE_OK; }
40static sqlite3_mutex *noopMutexAlloc(int id){
41 UNUSED_PARAMETER(id);
42 return (sqlite3_mutex*)8;
43}
44static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
45static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
46static int noopMutexTry(sqlite3_mutex *p){
47 UNUSED_PARAMETER(p);
48 return SQLITE_OK;
49}
50static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
51
52sqlite3_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*/
80typedef 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*/
89static int debugMutexHeld(sqlite3_mutex *pX){
90 sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
91 return p==0 || p->cnt>0;
92}
93static 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*/
101static int debugMutexInit(void){ return SQLITE_OK; }
102static 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*/
109static 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*/
140static 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*/
163static 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}
168static 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*/
181static 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
188sqlite3_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
211sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
212 return sqlite3NoopMutex();
213}
214#endif /* defined(SQLITE_MUTEX_NOOP) */
215#endif /* !defined(SQLITE_MUTEX_OMIT) */
216