blob: d5b31fa7f3108a419605fc726b276eab84f1de4b [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.
drh90f6a5b2007-08-15 13:04:54 +000015*/
16#include "sqliteInt.h"
17
drhd0bc5d22009-09-10 22:30:53 +000018#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT)
drhfe5bdb32009-09-10 17:45:00 +000019/*
20** For debugging purposes, record when the mutex subsystem is initialized
21** and uninitialized so that we can assert() if there is an attempt to
22** allocate a mutex while the system is uninitialized.
23*/
24static SQLITE_WSD int mutexIsInit = 0;
mistachkin8bdc9142015-09-11 05:06:15 +000025#endif /* SQLITE_DEBUG && !defined(SQLITE_MUTEX_OMIT) */
drhfe5bdb32009-09-10 17:45:00 +000026
27
drh18472fa2008-10-07 15:25:48 +000028#ifndef SQLITE_MUTEX_OMIT
danielk19776d2ab0e2008-06-17 17:21:18 +000029/*
mistachkin8bdc9142015-09-11 05:06:15 +000030** Copies a mutex implementation. Both arguments must point to valid
31** memory.
32*/
mistachkinffce11a2015-09-23 16:24:19 +000033void sqlite3MutexCopy(
mistachkin8bdc9142015-09-11 05:06:15 +000034 sqlite3_mutex_methods *pTo,
35 sqlite3_mutex_methods const *pFrom
36){
37 pTo->xMutexInit = pFrom->xMutexInit;
38 pTo->xMutexEnd = pFrom->xMutexEnd;
39 pTo->xMutexFree = pFrom->xMutexFree;
40 pTo->xMutexEnter = pFrom->xMutexEnter;
41 pTo->xMutexTry = pFrom->xMutexTry;
42 pTo->xMutexLeave = pFrom->xMutexLeave;
43 pTo->xMutexHeld = pFrom->xMutexHeld;
44 pTo->xMutexNotheld = pFrom->xMutexNotheld;
45 pTo->xMutexAlloc = pFrom->xMutexAlloc;
46}
47
48/*
danielk19776d2ab0e2008-06-17 17:21:18 +000049** Initialize the mutex system.
50*/
danielk1977d0251742008-06-18 18:57:42 +000051int sqlite3MutexInit(void){
mistachkin8bdc9142015-09-11 05:06:15 +000052 int rc;
mistachkinffce11a2015-09-23 16:24:19 +000053
54 sqlite3MemoryBarrier();
55 if( sqlite3CompareAndSwap(
56 (void * volatile *)&sqlite3GlobalConfig.mutex.xMutexAlloc,
57 0, sqlite3GlobalConfig.mutex.xMutexAlloc)==0 ){
58 /* If the xMutexAlloc method has not been set, then the user did not
59 ** install a mutex implementation via sqlite3_config() prior to
60 ** sqlite3_initialize() being called. This block copies pointers to
61 ** the default implementation into the sqlite3GlobalConfig structure.
drh92d76522010-05-05 00:05:24 +000062 */
dan558814f2010-06-02 05:53:53 +000063 sqlite3_mutex_methods const *pFrom;
mistachkin24271dc2015-09-23 16:33:44 +000064
drh92d76522010-05-05 00:05:24 +000065 if( sqlite3GlobalConfig.bCoreMutex ){
66 pFrom = sqlite3DefaultMutex();
67 }else{
68 pFrom = sqlite3NoopMutex();
danielk19776d2ab0e2008-06-17 17:21:18 +000069 }
mistachkinffce11a2015-09-23 16:24:19 +000070 sqlite3MutexCopy(&sqlite3GlobalConfig.mutex, pFrom);
drh6081c1d2015-09-06 02:51:04 +000071 sqlite3MemoryBarrier();
danielk19776d2ab0e2008-06-17 17:21:18 +000072 }
mistachkinffce11a2015-09-23 16:24:19 +000073 assert( sqlite3GlobalConfig.mutex.xMutexInit );
74 rc = sqlite3GlobalConfig.mutex.xMutexInit();
danielk19776d2ab0e2008-06-17 17:21:18 +000075
drhfe5bdb32009-09-10 17:45:00 +000076#ifdef SQLITE_DEBUG
77 GLOBAL(int, mutexIsInit) = 1;
78#endif
79
danielk19776d2ab0e2008-06-17 17:21:18 +000080 return rc;
81}
82
83/*
84** Shutdown the mutex system. This call frees resources allocated by
danielk1977d0251742008-06-18 18:57:42 +000085** sqlite3MutexInit().
danielk19776d2ab0e2008-06-17 17:21:18 +000086*/
danielk1977d0251742008-06-18 18:57:42 +000087int sqlite3MutexEnd(void){
danielk19776d2ab0e2008-06-17 17:21:18 +000088 int rc = SQLITE_OK;
danielk19770a549072009-02-17 16:29:10 +000089 if( sqlite3GlobalConfig.mutex.xMutexEnd ){
90 rc = sqlite3GlobalConfig.mutex.xMutexEnd();
91 }
drhfe5bdb32009-09-10 17:45:00 +000092
93#ifdef SQLITE_DEBUG
94 GLOBAL(int, mutexIsInit) = 0;
95#endif
96
danielk19776d2ab0e2008-06-17 17:21:18 +000097 return rc;
98}
99
100/*
101** Retrieve a pointer to a static mutex or allocate a new dynamic one.
102*/
103sqlite3_mutex *sqlite3_mutex_alloc(int id){
danielk1977bc10d772008-06-18 18:08:39 +0000104#ifndef SQLITE_OMIT_AUTOINIT
drhd42d0be2014-07-30 21:10:12 +0000105 if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
mistachkin2d8ad512014-10-27 22:06:21 +0000106 if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0;
danielk1977bc10d772008-06-18 18:08:39 +0000107#endif
mistachkin89e57dd2015-09-12 03:35:55 +0000108 assert( sqlite3GlobalConfig.mutex.xMutexAlloc );
danielk1977075c23a2008-09-01 18:34:20 +0000109 return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
danielk19776d2ab0e2008-06-17 17:21:18 +0000110}
111
danielk197759f8c082008-06-18 17:09:10 +0000112sqlite3_mutex *sqlite3MutexAlloc(int id){
danielk1977075c23a2008-09-01 18:34:20 +0000113 if( !sqlite3GlobalConfig.bCoreMutex ){
danielk197759f8c082008-06-18 17:09:10 +0000114 return 0;
115 }
drhfe5bdb32009-09-10 17:45:00 +0000116 assert( GLOBAL(int, mutexIsInit) );
mistachkin89e57dd2015-09-12 03:35:55 +0000117 assert( sqlite3GlobalConfig.mutex.xMutexAlloc );
danielk1977075c23a2008-09-01 18:34:20 +0000118 return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
danielk197759f8c082008-06-18 17:09:10 +0000119}
120
danielk19776d2ab0e2008-06-17 17:21:18 +0000121/*
122** Free a dynamic mutex.
123*/
124void sqlite3_mutex_free(sqlite3_mutex *p){
125 if( p ){
mistachkin89e57dd2015-09-12 03:35:55 +0000126 assert( sqlite3GlobalConfig.mutex.xMutexFree );
danielk1977075c23a2008-09-01 18:34:20 +0000127 sqlite3GlobalConfig.mutex.xMutexFree(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000128 }
129}
130
131/*
132** Obtain the mutex p. If some other thread already has the mutex, block
133** until it can be obtained.
134*/
135void sqlite3_mutex_enter(sqlite3_mutex *p){
136 if( p ){
mistachkin89e57dd2015-09-12 03:35:55 +0000137 assert( sqlite3GlobalConfig.mutex.xMutexEnter );
danielk1977075c23a2008-09-01 18:34:20 +0000138 sqlite3GlobalConfig.mutex.xMutexEnter(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000139 }
140}
141
142/*
143** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
144** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
145*/
146int sqlite3_mutex_try(sqlite3_mutex *p){
147 int rc = SQLITE_OK;
148 if( p ){
mistachkin89e57dd2015-09-12 03:35:55 +0000149 assert( sqlite3GlobalConfig.mutex.xMutexTry );
danielk1977075c23a2008-09-01 18:34:20 +0000150 return sqlite3GlobalConfig.mutex.xMutexTry(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000151 }
152 return rc;
153}
154
155/*
156** The sqlite3_mutex_leave() routine exits a mutex that was previously
157** entered by the same thread. The behavior is undefined if the mutex
158** is not currently entered. If a NULL pointer is passed as an argument
159** this function is a no-op.
160*/
161void sqlite3_mutex_leave(sqlite3_mutex *p){
162 if( p ){
mistachkin89e57dd2015-09-12 03:35:55 +0000163 assert( sqlite3GlobalConfig.mutex.xMutexLeave );
danielk1977075c23a2008-09-01 18:34:20 +0000164 sqlite3GlobalConfig.mutex.xMutexLeave(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000165 }
166}
167
168#ifndef NDEBUG
169/*
170** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
171** intended for use inside assert() statements.
172*/
173int sqlite3_mutex_held(sqlite3_mutex *p){
mistachkin89e57dd2015-09-12 03:35:55 +0000174 assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
danielk1977075c23a2008-09-01 18:34:20 +0000175 return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000176}
177int sqlite3_mutex_notheld(sqlite3_mutex *p){
mistachkin89e57dd2015-09-12 03:35:55 +0000178 assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
danielk1977075c23a2008-09-01 18:34:20 +0000179 return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000180}
181#endif
182
drhe4c88c02012-01-04 12:57:45 +0000183#endif /* !defined(SQLITE_MUTEX_OMIT) */