aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/sqlite/win32/mutex_w32.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/sqlite/win32/mutex_w32.c')
-rwxr-xr-xlibraries/sqlite/win32/mutex_w32.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/libraries/sqlite/win32/mutex_w32.c b/libraries/sqlite/win32/mutex_w32.c
new file mode 100755
index 0000000..3153cd0
--- /dev/null
+++ b/libraries/sqlite/win32/mutex_w32.c
@@ -0,0 +1,210 @@
1/*
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*************************************************************************
12** This file contains the C functions that implement mutexes for win32
13**
14** $Id: mutex_w32.c,v 1.4 2007/09/05 14:30:42 drh Exp $
15*/
16#define _WIN32_WINNT 0x0400
17#include <Windows.h>
18#include "sqliteInt.h"
19
20/*
21** The code in this file is only used if we are compiling multithreaded
22** on a win32 system.
23*/
24#ifdef SQLITE_MUTEX_W32
25
26/*
27** Each recursive mutex is an instance of the following structure.
28*/
29struct sqlite3_mutex {
30 CRITICAL_SECTION mutex; /* Mutex controlling the lock */
31 int id; /* Mutex type */
32 int nRef; /* Number of enterances */
33 DWORD owner; /* Thread holding this mutex */
34};
35
36/*
37** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
38** or WinCE. Return false (zero) for Win95, Win98, or WinME.
39**
40** Here is an interesting observation: Win95, Win98, and WinME lack
41** the LockFileEx() API. But we can still statically link against that
42** API as long as we don't call it win running Win95/98/ME. A call to
43** this routine is used to determine if the host is Win95/98/ME or
44** WinNT/2K/XP so that we will know whether or not we can safely call
45** the LockFileEx() API.
46*/
47#if OS_WINCE
48# define mutexIsNT() (1)
49#else
50 static int mutexIsNT(void){
51 static int osType = 0;
52 if( osType==0 ){
53 OSVERSIONINFO sInfo;
54 sInfo.dwOSVersionInfoSize = sizeof(sInfo);
55 GetVersionEx(&sInfo);
56 osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
57 }
58 return osType==2;
59 }
60#endif /* OS_WINCE */
61
62
63/*
64** The sqlite3_mutex_alloc() routine allocates a new
65** mutex and returns a pointer to it. If it returns NULL
66** that means that a mutex could not be allocated. SQLite
67** will unwind its stack and return an error. The argument
68** to sqlite3_mutex_alloc() is one of these integer constants:
69**
70** <ul>
71** <li> SQLITE_MUTEX_FAST 0
72** <li> SQLITE_MUTEX_RECURSIVE 1
73** <li> SQLITE_MUTEX_STATIC_MASTER 2
74** <li> SQLITE_MUTEX_STATIC_MEM 3
75** <li> SQLITE_MUTEX_STATIC_PRNG 4
76** </ul>
77**
78** The first two constants cause sqlite3_mutex_alloc() to create
79** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
80** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
81** The mutex implementation does not need to make a distinction
82** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
83** not want to. But SQLite will only request a recursive mutex in
84** cases where it really needs one. If a faster non-recursive mutex
85** implementation is available on the host platform, the mutex subsystem
86** might return such a mutex in response to SQLITE_MUTEX_FAST.
87**
88** The other allowed parameters to sqlite3_mutex_alloc() each return
89** a pointer to a static preexisting mutex. Three static mutexes are
90** used by the current version of SQLite. Future versions of SQLite
91** may add additional static mutexes. Static mutexes are for internal
92** use by SQLite only. Applications that use SQLite mutexes should
93** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
94** SQLITE_MUTEX_RECURSIVE.
95**
96** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
97** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
98** returns a different mutex on every call. But for the static
99** mutex types, the same mutex is returned on every call that has
100** the same type number.
101*/
102sqlite3_mutex *sqlite3_mutex_alloc(int iType){
103 sqlite3_mutex *p;
104
105 switch( iType ){
106 case SQLITE_MUTEX_FAST:
107 case SQLITE_MUTEX_RECURSIVE: {
108 p = sqlite3MallocZero( sizeof(*p) );
109 if( p ){
110 p->id = iType;
111 InitializeCriticalSection(&p->mutex);
112 }
113 break;
114 }
115 default: {
116 static sqlite3_mutex staticMutexes[5];
117 static int isInit = 0;
118 while( !isInit ){
119 static long lock = 0;
120 if( InterlockedIncrement(&lock)==1 ){
121 int i;
122 for(i=0; i<sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++){
123 InitializeCriticalSection(&staticMutexes[i].mutex);
124 }
125 isInit = 1;
126 }else{
127 Sleep(1);
128 }
129 }
130 assert( iType-2 >= 0 );
131 assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
132 p = &staticMutexes[iType-2];
133 p->id = iType;
134 break;
135 }
136 }
137 return p;
138}
139
140
141/*
142** This routine deallocates a previously
143** allocated mutex. SQLite is careful to deallocate every
144** mutex that it allocates.
145*/
146void sqlite3_mutex_free(sqlite3_mutex *p){
147 assert( p );
148 assert( p->nRef==0 );
149 assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
150 DeleteCriticalSection(&p->mutex);
151 sqlite3_free(p);
152}
153
154/*
155** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
156** to enter a mutex. If another thread is already within the mutex,
157** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
158** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
159** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
160** be entered multiple times by the same thread. In such cases the,
161** mutex must be exited an equal number of times before another thread
162** can enter. If the same thread tries to enter any other kind of mutex
163** more than once, the behavior is undefined.
164*/
165void sqlite3_mutex_enter(sqlite3_mutex *p){
166 assert( p );
167 assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
168 EnterCriticalSection(&p->mutex);
169 p->owner = GetCurrentThreadId();
170 p->nRef++;
171}
172int sqlite3_mutex_try(sqlite3_mutex *p){
173 int rc;
174 assert( p );
175 assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
176 if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
177 p->owner = GetCurrentThreadId();
178 p->nRef++;
179 rc = SQLITE_OK;
180 }else{
181 rc = SQLITE_BUSY;
182 }
183 return rc;
184}
185
186/*
187** The sqlite3_mutex_leave() routine exits a mutex that was
188** previously entered by the same thread. The behavior
189** is undefined if the mutex is not currently entered or
190** is not currently allocated. SQLite will never do either.
191*/
192void sqlite3_mutex_leave(sqlite3_mutex *p){
193 assert( p->nRef>0 );
194 assert( p->owner==GetCurrentThreadId() );
195 p->nRef--;
196 assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
197 LeaveCriticalSection(&p->mutex);
198}
199
200/*
201** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
202** intended for use only inside assert() statements.
203*/
204int sqlite3_mutex_held(sqlite3_mutex *p){
205 return p==0 || (p->nRef!=0 && p->owner==GetCurrentThreadId());
206}
207int sqlite3_mutex_notheld(sqlite3_mutex *p){
208 return p==0 || p->nRef==0 || p->owner!=GetCurrentThreadId();
209}
210#endif /* SQLITE_MUTEX_W32 */