Merge pull request #37 from developernotes/prerelease
[sqlcipher.git] / src / mutex_os2.c
blobce650d994e3c74582f9fb9e9c0a898c470f8c31d
1 /*
2 ** 2007 August 28
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.
11 *************************************************************************
12 ** This file contains the C functions that implement mutexes for OS/2
14 #include "sqliteInt.h"
17 ** The code in this file is only used if SQLITE_MUTEX_OS2 is defined.
18 ** See the mutex.h file for details.
20 #ifdef SQLITE_MUTEX_OS2
22 /********************** OS/2 Mutex Implementation **********************
24 ** This implementation of mutexes is built using the OS/2 API.
28 ** The mutex object
29 ** Each recursive mutex is an instance of the following structure.
31 struct sqlite3_mutex {
32 HMTX mutex; /* Mutex controlling the lock */
33 int id; /* Mutex type */
34 #ifdef SQLITE_DEBUG
35 int trace; /* True to trace changes */
36 #endif
39 #ifdef SQLITE_DEBUG
40 #define SQLITE3_MUTEX_INITIALIZER { 0, 0, 0 }
41 #else
42 #define SQLITE3_MUTEX_INITIALIZER { 0, 0 }
43 #endif
46 ** Initialize and deinitialize the mutex subsystem.
48 static int os2MutexInit(void){ return SQLITE_OK; }
49 static int os2MutexEnd(void){ return SQLITE_OK; }
52 ** The sqlite3_mutex_alloc() routine allocates a new
53 ** mutex and returns a pointer to it. If it returns NULL
54 ** that means that a mutex could not be allocated.
55 ** SQLite will unwind its stack and return an error. The argument
56 ** to sqlite3_mutex_alloc() is one of these integer constants:
58 ** <ul>
59 ** <li> SQLITE_MUTEX_FAST
60 ** <li> SQLITE_MUTEX_RECURSIVE
61 ** <li> SQLITE_MUTEX_STATIC_MASTER
62 ** <li> SQLITE_MUTEX_STATIC_MEM
63 ** <li> SQLITE_MUTEX_STATIC_MEM2
64 ** <li> SQLITE_MUTEX_STATIC_PRNG
65 ** <li> SQLITE_MUTEX_STATIC_LRU
66 ** <li> SQLITE_MUTEX_STATIC_LRU2
67 ** </ul>
69 ** The first two constants cause sqlite3_mutex_alloc() to create
70 ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
71 ** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
72 ** The mutex implementation does not need to make a distinction
73 ** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
74 ** not want to. But SQLite will only request a recursive mutex in
75 ** cases where it really needs one. If a faster non-recursive mutex
76 ** implementation is available on the host platform, the mutex subsystem
77 ** might return such a mutex in response to SQLITE_MUTEX_FAST.
79 ** The other allowed parameters to sqlite3_mutex_alloc() each return
80 ** a pointer to a static preexisting mutex. Six static mutexes are
81 ** used by the current version of SQLite. Future versions of SQLite
82 ** may add additional static mutexes. Static mutexes are for internal
83 ** use by SQLite only. Applications that use SQLite mutexes should
84 ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
85 ** SQLITE_MUTEX_RECURSIVE.
87 ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
88 ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
89 ** returns a different mutex on every call. But for the static
90 ** mutex types, the same mutex is returned on every call that has
91 ** the same type number.
93 static sqlite3_mutex *os2MutexAlloc(int iType){
94 sqlite3_mutex *p = NULL;
95 switch( iType ){
96 case SQLITE_MUTEX_FAST:
97 case SQLITE_MUTEX_RECURSIVE: {
98 p = sqlite3MallocZero( sizeof(*p) );
99 if( p ){
100 p->id = iType;
101 if( DosCreateMutexSem( 0, &p->mutex, 0, FALSE ) != NO_ERROR ){
102 sqlite3_free( p );
103 p = NULL;
106 break;
108 default: {
109 static volatile int isInit = 0;
110 static sqlite3_mutex staticMutexes[6] = {
111 SQLITE3_MUTEX_INITIALIZER,
112 SQLITE3_MUTEX_INITIALIZER,
113 SQLITE3_MUTEX_INITIALIZER,
114 SQLITE3_MUTEX_INITIALIZER,
115 SQLITE3_MUTEX_INITIALIZER,
116 SQLITE3_MUTEX_INITIALIZER,
118 if ( !isInit ){
119 APIRET rc;
120 PTIB ptib;
121 PPIB ppib;
122 HMTX mutex;
123 char name[32];
124 DosGetInfoBlocks( &ptib, &ppib );
125 sqlite3_snprintf( sizeof(name), name, "\\SEM32\\SQLITE%04x",
126 ppib->pib_ulpid );
127 while( !isInit ){
128 mutex = 0;
129 rc = DosCreateMutexSem( name, &mutex, 0, FALSE);
130 if( rc == NO_ERROR ){
131 unsigned int i;
132 if( !isInit ){
133 for( i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++ ){
134 DosCreateMutexSem( 0, &staticMutexes[i].mutex, 0, FALSE );
136 isInit = 1;
138 DosCloseMutexSem( mutex );
139 }else if( rc == ERROR_DUPLICATE_NAME ){
140 DosSleep( 1 );
141 }else{
142 return p;
146 assert( iType-2 >= 0 );
147 assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
148 p = &staticMutexes[iType-2];
149 p->id = iType;
150 break;
153 return p;
158 ** This routine deallocates a previously allocated mutex.
159 ** SQLite is careful to deallocate every mutex that it allocates.
161 static void os2MutexFree(sqlite3_mutex *p){
162 #ifdef SQLITE_DEBUG
163 TID tid;
164 PID pid;
165 ULONG ulCount;
166 DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
167 assert( ulCount==0 );
168 assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
169 #endif
170 DosCloseMutexSem( p->mutex );
171 sqlite3_free( p );
174 #ifdef SQLITE_DEBUG
176 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
177 ** intended for use inside assert() statements.
179 static int os2MutexHeld(sqlite3_mutex *p){
180 TID tid;
181 PID pid;
182 ULONG ulCount;
183 PTIB ptib;
184 DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
185 if( ulCount==0 || ( ulCount>1 && p->id!=SQLITE_MUTEX_RECURSIVE ) )
186 return 0;
187 DosGetInfoBlocks(&ptib, NULL);
188 return tid==ptib->tib_ptib2->tib2_ultid;
190 static int os2MutexNotheld(sqlite3_mutex *p){
191 TID tid;
192 PID pid;
193 ULONG ulCount;
194 PTIB ptib;
195 DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
196 if( ulCount==0 )
197 return 1;
198 DosGetInfoBlocks(&ptib, NULL);
199 return tid!=ptib->tib_ptib2->tib2_ultid;
201 static void os2MutexTrace(sqlite3_mutex *p, char *pAction){
202 TID tid;
203 PID pid;
204 ULONG ulCount;
205 DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
206 printf("%s mutex %p (%d) with nRef=%ld\n", pAction, (void*)p, p->trace, ulCount);
208 #endif
211 ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
212 ** to enter a mutex. If another thread is already within the mutex,
213 ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
214 ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
215 ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
216 ** be entered multiple times by the same thread. In such cases the,
217 ** mutex must be exited an equal number of times before another thread
218 ** can enter. If the same thread tries to enter any other kind of mutex
219 ** more than once, the behavior is undefined.
221 static void os2MutexEnter(sqlite3_mutex *p){
222 assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
223 DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT);
224 #ifdef SQLITE_DEBUG
225 if( p->trace ) os2MutexTrace(p, "enter");
226 #endif
228 static int os2MutexTry(sqlite3_mutex *p){
229 int rc = SQLITE_BUSY;
230 assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
231 if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR ) {
232 rc = SQLITE_OK;
233 #ifdef SQLITE_DEBUG
234 if( p->trace ) os2MutexTrace(p, "try");
235 #endif
237 return rc;
241 ** The sqlite3_mutex_leave() routine exits a mutex that was
242 ** previously entered by the same thread. The behavior
243 ** is undefined if the mutex is not currently entered or
244 ** is not currently allocated. SQLite will never do either.
246 static void os2MutexLeave(sqlite3_mutex *p){
247 assert( os2MutexHeld(p) );
248 DosReleaseMutexSem(p->mutex);
249 #ifdef SQLITE_DEBUG
250 if( p->trace ) os2MutexTrace(p, "leave");
251 #endif
254 sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
255 static const sqlite3_mutex_methods sMutex = {
256 os2MutexInit,
257 os2MutexEnd,
258 os2MutexAlloc,
259 os2MutexFree,
260 os2MutexEnter,
261 os2MutexTry,
262 os2MutexLeave,
263 #ifdef SQLITE_DEBUG
264 os2MutexHeld,
265 os2MutexNotheld
266 #else
269 #endif
272 return &sMutex;
274 #endif /* SQLITE_MUTEX_OS2 */