dvander@1645: /* dvander@1645: ** 2007 August 14 dvander@1645: ** dvander@1645: ** The author disclaims copyright to this source code. In place of dvander@1645: ** a legal notice, here is a blessing: dvander@1645: ** dvander@1645: ** May you do good and not evil. dvander@1645: ** May you find forgiveness for yourself and forgive others. dvander@1645: ** May you share freely, never taking more than you give. dvander@1645: ** dvander@1645: ************************************************************************* dvander@1645: ** This file contains the C functions that implement mutexes. dvander@1645: ** dvander@1645: ** The implementation in this file does not provide any mutual dvander@1645: ** exclusion and is thus suitable for use only in applications dvander@1645: ** that use SQLite in a single thread. But this implementation dvander@1645: ** does do a lot of error checking on mutexes to make sure they dvander@1645: ** are called correctly and at appropriate times. Hence, this dvander@1645: ** implementation is suitable for testing. dvander@1645: ** debugging purposes dvander@1645: ** dvander@1645: ** $Id$ dvander@1645: */ dvander@1645: #include "sqliteInt.h" dvander@1645: dvander@1645: #ifdef SQLITE_MUTEX_NOOP_DEBUG dvander@1645: /* dvander@1645: ** In this implementation, mutexes do not provide any mutual exclusion. dvander@1645: ** But the error checking is provided. This implementation is useful dvander@1645: ** for test purposes. dvander@1645: */ dvander@1645: dvander@1645: /* dvander@1645: ** The mutex object dvander@1645: */ dvander@1645: struct sqlite3_mutex { dvander@1645: int id; /* The mutex type */ dvander@1645: int cnt; /* Number of entries without a matching leave */ dvander@1645: }; dvander@1645: dvander@1645: /* dvander@1645: ** The sqlite3_mutex_alloc() routine allocates a new dvander@1645: ** mutex and returns a pointer to it. If it returns NULL dvander@1645: ** that means that a mutex could not be allocated. dvander@1645: */ dvander@1645: sqlite3_mutex *sqlite3_mutex_alloc(int id){ dvander@1645: static sqlite3_mutex aStatic[5]; dvander@1645: sqlite3_mutex *pNew = 0; dvander@1645: switch( id ){ dvander@1645: case SQLITE_MUTEX_FAST: dvander@1645: case SQLITE_MUTEX_RECURSIVE: { dvander@1645: pNew = sqlite3_malloc(sizeof(*pNew)); dvander@1645: if( pNew ){ dvander@1645: pNew->id = id; dvander@1645: pNew->cnt = 0; dvander@1645: } dvander@1645: break; dvander@1645: } dvander@1645: default: { dvander@1645: assert( id-2 >= 0 ); dvander@1645: assert( id-2 < sizeof(aStatic)/sizeof(aStatic[0]) ); dvander@1645: pNew = &aStatic[id-2]; dvander@1645: pNew->id = id; dvander@1645: break; dvander@1645: } dvander@1645: } dvander@1645: return pNew; dvander@1645: } dvander@1645: dvander@1645: /* dvander@1645: ** This routine deallocates a previously allocated mutex. dvander@1645: */ dvander@1645: void sqlite3_mutex_free(sqlite3_mutex *p){ dvander@1645: assert( p ); dvander@1645: assert( p->cnt==0 ); dvander@1645: assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); dvander@1645: sqlite3_free(p); dvander@1645: } dvander@1645: dvander@1645: /* dvander@1645: ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt dvander@1645: ** to enter a mutex. If another thread is already within the mutex, dvander@1645: ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return dvander@1645: ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK dvander@1645: ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can dvander@1645: ** be entered multiple times by the same thread. In such cases the, dvander@1645: ** mutex must be exited an equal number of times before another thread dvander@1645: ** can enter. If the same thread tries to enter any other kind of mutex dvander@1645: ** more than once, the behavior is undefined. dvander@1645: */ dvander@1645: void sqlite3_mutex_enter(sqlite3_mutex *p){ dvander@1645: assert( p ); dvander@1645: assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); dvander@1645: p->cnt++; dvander@1645: } dvander@1645: int sqlite3_mutex_try(sqlite3_mutex *p){ dvander@1645: assert( p ); dvander@1645: assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); dvander@1645: p->cnt++; dvander@1645: return SQLITE_OK; dvander@1645: } dvander@1645: dvander@1645: /* dvander@1645: ** The sqlite3_mutex_leave() routine exits a mutex that was dvander@1645: ** previously entered by the same thread. The behavior dvander@1645: ** is undefined if the mutex is not currently entered or dvander@1645: ** is not currently allocated. SQLite will never do either. dvander@1645: */ dvander@1645: void sqlite3_mutex_leave(sqlite3_mutex *p){ dvander@1645: assert( p ); dvander@1645: assert( sqlite3_mutex_held(p) ); dvander@1645: p->cnt--; dvander@1645: assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); dvander@1645: } dvander@1645: dvander@1645: /* dvander@1645: ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are dvander@1645: ** intended for use inside assert() statements. dvander@1645: */ dvander@1645: int sqlite3_mutex_held(sqlite3_mutex *p){ dvander@1645: return p==0 || p->cnt>0; dvander@1645: } dvander@1645: int sqlite3_mutex_notheld(sqlite3_mutex *p){ dvander@1645: return p==0 || p->cnt==0; dvander@1645: } dvander@1645: #endif /* SQLITE_MUTEX_NOOP_DEBUG */