AryaWu/sqlite
0
1/*2** 2008 October 073**4** The author disclaims copyright to this source code. In place of5** 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 mutual15** exclusion and is thus suitable for use only in applications16** that use SQLite in a single thread. The routines defined17** here are place-holders. Applications can substitute working18** mutex routines at start-time using the19**20** sqlite3_config(SQLITE_CONFIG_MUTEX,...)21**22** interface.23**24** If compiled with SQLITE_DEBUG, then additional logic is inserted25** that does error checking on mutexes to make sure they are being26** called correctly.27*/28#include "sqliteInt.h"29 30#ifndef SQLITE_MUTEX_OMIT31 32#ifndef SQLITE_DEBUG33/*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_DEBUG71/*72** In this implementation, error checking is provided for testing73** and debugging purposes. The mutexes still do not provide any74** mutual exclusion.75*/76 77/*78** The mutex object79*/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 are87** 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 new106** mutex and returns a pointer to it. If it returns NULL107** 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_ARMOR124 if( id-2<0 || id-2>=ArraySize(aStatic) ){125 (void)SQLITE_MISUSE_BKPT;126 return 0;127 }128#endif129 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_ARMOR147 (void)SQLITE_MISUSE_BKPT;148#endif149 }150}151 152/*153** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt154** to enter a mutex. If another thread is already within the mutex,155** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return156** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK157** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can158** be entered multiple times by the same thread. In such cases the,159** mutex must be exited an equal number of times before another thread160** can enter. If the same thread tries to enter any other kind of mutex161** 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 was177** previously entered by the same thread. The behavior178** is undefined if the mutex is not currently entered or179** 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 debugMutexNotheld200 };201 202 return &sMutex;203}204#endif /* SQLITE_DEBUG */205 206/*207** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation208** is used regardless of the run-time threadsafety setting.209*/210#ifdef SQLITE_MUTEX_NOOP211sqlite3_mutex_methods const *sqlite3DefaultMutex(void){212 return sqlite3NoopMutex();213}214#endif /* defined(SQLITE_MUTEX_NOOP) */215#endif /* !defined(SQLITE_MUTEX_OMIT) */216 