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[6];
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      assert( id-2 >= 0 );
124      assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) );
125      pNew = &aStatic[id-2];
126      pNew->id = id;
127      break;
128    }
129  }
130  return (sqlite3_mutex*)pNew;
131}
132
133/*
134** This routine deallocates a previously allocated mutex.
135*/
136static void debugMutexFree(sqlite3_mutex *pX){
137  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
138  assert( p->cnt==0 );
139  assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
140  sqlite3_free(p);
141}
142
143/*
144** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
145** to enter a mutex.  If another thread is already within the mutex,
146** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
147** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
148** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
149** be entered multiple times by the same thread.  In such cases the,
150** mutex must be exited an equal number of times before another thread
151** can enter.  If the same thread tries to enter any other kind of mutex
152** more than once, the behavior is undefined.
153*/
154static void debugMutexEnter(sqlite3_mutex *pX){
155  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
156  assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
157  p->cnt++;
158}
159static int debugMutexTry(sqlite3_mutex *pX){
160  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
161  assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
162  p->cnt++;
163  return SQLITE_OK;
164}
165
166/*
167** The sqlite3_mutex_leave() routine exits a mutex that was
168** previously entered by the same thread.  The behavior
169** is undefined if the mutex is not currently entered or
170** is not currently allocated.  SQLite will never do either.
171*/
172static void debugMutexLeave(sqlite3_mutex *pX){
173  sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
174  assert( debugMutexHeld(pX) );
175  p->cnt--;
176  assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
177}
178
179sqlite3_mutex_methods const *sqlite3NoopMutex(void){
180  static const sqlite3_mutex_methods sMutex = {
181    debugMutexInit,
182    debugMutexEnd,
183    debugMutexAlloc,
184    debugMutexFree,
185    debugMutexEnter,
186    debugMutexTry,
187    debugMutexLeave,
188
189    debugMutexHeld,
190    debugMutexNotheld
191  };
192
193  return &sMutex;
194}
195#endif /* SQLITE_DEBUG */
196
197/*
198** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation
199** is used regardless of the run-time threadsafety setting.
200*/
201#ifdef SQLITE_MUTEX_NOOP
202sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
203  return sqlite3NoopMutex();
204}
205#endif /* SQLITE_MUTEX_NOOP */
206#endif /* SQLITE_MUTEX_OMIT */
207