blob: 03cae57bf9832efaab35a048d319886fe4c273fe [file] [log] [blame]
drh90f6a5b2007-08-15 13:04:54 +00001/*
2** 2007 August 14
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*************************************************************************
drh437b9012007-08-28 16:34:42 +000012** This file contains the C functions that implement mutexes.
drh90f6a5b2007-08-15 13:04:54 +000013**
drh18472fa2008-10-07 15:25:48 +000014** This file contains code that is common across all mutex implementations.
15
drh437b9012007-08-28 16:34:42 +000016**
drh18472fa2008-10-07 15:25:48 +000017** $Id: mutex.c,v 1.29 2008/10/07 15:25:48 drh Exp $
drh90f6a5b2007-08-15 13:04:54 +000018*/
19#include "sqliteInt.h"
20
drh18472fa2008-10-07 15:25:48 +000021#ifndef SQLITE_MUTEX_OMIT
danielk19776d2ab0e2008-06-17 17:21:18 +000022/*
23** Initialize the mutex system.
24*/
danielk1977d0251742008-06-18 18:57:42 +000025int sqlite3MutexInit(void){
danielk197759f8c082008-06-18 17:09:10 +000026 int rc = SQLITE_OK;
danielk1977075c23a2008-09-01 18:34:20 +000027 if( sqlite3GlobalConfig.bCoreMutex ){
28 if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
danielk197759f8c082008-06-18 17:09:10 +000029 /* If the xMutexAlloc method has not been set, then the user did not
30 ** install a mutex implementation via sqlite3_config() prior to
31 ** sqlite3_initialize() being called. This block copies pointers to
danielk1977075c23a2008-09-01 18:34:20 +000032 ** the default implementation into the sqlite3GlobalConfig structure.
danielk197759f8c082008-06-18 17:09:10 +000033 **
34 ** The danger is that although sqlite3_config() is not a threadsafe
35 ** API, sqlite3_initialize() is, and so multiple threads may be
36 ** attempting to run this function simultaneously. To guard write
danielk1977075c23a2008-09-01 18:34:20 +000037 ** access to the sqlite3GlobalConfig structure, the 'MASTER' static mutex
danielk197759f8c082008-06-18 17:09:10 +000038 ** is obtained before modifying it.
39 */
40 sqlite3_mutex_methods *p = sqlite3DefaultMutex();
41 sqlite3_mutex *pMaster = 0;
42
43 rc = p->xMutexInit();
44 if( rc==SQLITE_OK ){
45 pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
46 assert(pMaster);
47 p->xMutexEnter(pMaster);
danielk1977075c23a2008-09-01 18:34:20 +000048 assert( sqlite3GlobalConfig.mutex.xMutexAlloc==0
49 || sqlite3GlobalConfig.mutex.xMutexAlloc==p->xMutexAlloc
danielk197759f8c082008-06-18 17:09:10 +000050 );
danielk1977075c23a2008-09-01 18:34:20 +000051 if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
52 sqlite3GlobalConfig.mutex = *p;
danielk197759f8c082008-06-18 17:09:10 +000053 }
54 p->xMutexLeave(pMaster);
danielk19776d2ab0e2008-06-17 17:21:18 +000055 }
danielk197759f8c082008-06-18 17:09:10 +000056 }else{
danielk1977075c23a2008-09-01 18:34:20 +000057 rc = sqlite3GlobalConfig.mutex.xMutexInit();
danielk19776d2ab0e2008-06-17 17:21:18 +000058 }
danielk19776d2ab0e2008-06-17 17:21:18 +000059 }
60
61 return rc;
62}
63
64/*
65** Shutdown the mutex system. This call frees resources allocated by
danielk1977d0251742008-06-18 18:57:42 +000066** sqlite3MutexInit().
danielk19776d2ab0e2008-06-17 17:21:18 +000067*/
danielk1977d0251742008-06-18 18:57:42 +000068int sqlite3MutexEnd(void){
danielk19776d2ab0e2008-06-17 17:21:18 +000069 int rc = SQLITE_OK;
danielk1977075c23a2008-09-01 18:34:20 +000070 rc = sqlite3GlobalConfig.mutex.xMutexEnd();
danielk19776d2ab0e2008-06-17 17:21:18 +000071 return rc;
72}
73
74/*
75** Retrieve a pointer to a static mutex or allocate a new dynamic one.
76*/
77sqlite3_mutex *sqlite3_mutex_alloc(int id){
danielk1977bc10d772008-06-18 18:08:39 +000078#ifndef SQLITE_OMIT_AUTOINIT
79 if( sqlite3_initialize() ) return 0;
80#endif
danielk1977075c23a2008-09-01 18:34:20 +000081 return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
danielk19776d2ab0e2008-06-17 17:21:18 +000082}
83
danielk197759f8c082008-06-18 17:09:10 +000084sqlite3_mutex *sqlite3MutexAlloc(int id){
danielk1977075c23a2008-09-01 18:34:20 +000085 if( !sqlite3GlobalConfig.bCoreMutex ){
danielk197759f8c082008-06-18 17:09:10 +000086 return 0;
87 }
danielk1977075c23a2008-09-01 18:34:20 +000088 return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
danielk197759f8c082008-06-18 17:09:10 +000089}
90
danielk19776d2ab0e2008-06-17 17:21:18 +000091/*
92** Free a dynamic mutex.
93*/
94void sqlite3_mutex_free(sqlite3_mutex *p){
95 if( p ){
danielk1977075c23a2008-09-01 18:34:20 +000096 sqlite3GlobalConfig.mutex.xMutexFree(p);
danielk19776d2ab0e2008-06-17 17:21:18 +000097 }
98}
99
100/*
101** Obtain the mutex p. If some other thread already has the mutex, block
102** until it can be obtained.
103*/
104void sqlite3_mutex_enter(sqlite3_mutex *p){
105 if( p ){
danielk1977075c23a2008-09-01 18:34:20 +0000106 sqlite3GlobalConfig.mutex.xMutexEnter(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000107 }
108}
109
110/*
111** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
112** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
113*/
114int sqlite3_mutex_try(sqlite3_mutex *p){
115 int rc = SQLITE_OK;
116 if( p ){
danielk1977075c23a2008-09-01 18:34:20 +0000117 return sqlite3GlobalConfig.mutex.xMutexTry(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000118 }
119 return rc;
120}
121
122/*
123** The sqlite3_mutex_leave() routine exits a mutex that was previously
124** entered by the same thread. The behavior is undefined if the mutex
125** is not currently entered. If a NULL pointer is passed as an argument
126** this function is a no-op.
127*/
128void sqlite3_mutex_leave(sqlite3_mutex *p){
129 if( p ){
danielk1977075c23a2008-09-01 18:34:20 +0000130 sqlite3GlobalConfig.mutex.xMutexLeave(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000131 }
132}
133
134#ifndef NDEBUG
135/*
136** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
137** intended for use inside assert() statements.
138*/
139int sqlite3_mutex_held(sqlite3_mutex *p){
danielk1977075c23a2008-09-01 18:34:20 +0000140 return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000141}
142int sqlite3_mutex_notheld(sqlite3_mutex *p){
danielk1977075c23a2008-09-01 18:34:20 +0000143 return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000144}
145#endif
146
drh18472fa2008-10-07 15:25:48 +0000147#endif /* SQLITE_OMIT_MUTEX */