blob: 15ffd2c9f3b2fbdf2cf4b5e32a7fd681c0001964 [file] [log] [blame]
drh437b9012007-08-28 16:34:42 +00001/*
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.
10**
11*************************************************************************
12** This file contains the C functions that implement mutexes for OS/2
13**
pweilbacherc06b54f2008-11-22 19:50:53 +000014** $Id: mutex_os2.c,v 1.11 2008/11/22 19:50:54 pweilbacher Exp $
drh437b9012007-08-28 16:34:42 +000015*/
16#include "sqliteInt.h"
17
drh437b9012007-08-28 16:34:42 +000018/*
19** The code in this file is only used if SQLITE_MUTEX_OS2 is defined.
20** See the mutex.h file for details.
21*/
22#ifdef SQLITE_MUTEX_OS2
23
pweilbacherec70b6b2007-09-20 21:40:23 +000024/********************** OS/2 Mutex Implementation **********************
25**
26** This implementation of mutexes is built using the OS/2 API.
27*/
drh437b9012007-08-28 16:34:42 +000028
29/*
30** The mutex object
pweilbacherec70b6b2007-09-20 21:40:23 +000031** Each recursive mutex is an instance of the following structure.
drh437b9012007-08-28 16:34:42 +000032*/
33struct sqlite3_mutex {
pweilbacherec70b6b2007-09-20 21:40:23 +000034 HMTX mutex; /* Mutex controlling the lock */
35 int id; /* Mutex type */
36 int nRef; /* Number of references */
37 TID owner; /* Thread holding this mutex */
drh437b9012007-08-28 16:34:42 +000038};
39
pweilbacherdc965c32008-02-01 19:42:37 +000040#define OS2_MUTEX_INITIALIZER 0,0,0,0
41
drh437b9012007-08-28 16:34:42 +000042/*
drh40257ff2008-06-13 18:24:27 +000043** Initialize and deinitialize the mutex subsystem.
44*/
pweilbacher26169642008-06-23 22:13:27 +000045static int os2MutexInit(void){ return SQLITE_OK; }
46static int os2MutexEnd(void){ return SQLITE_OK; }
drh40257ff2008-06-13 18:24:27 +000047
48/*
drh437b9012007-08-28 16:34:42 +000049** The sqlite3_mutex_alloc() routine allocates a new
50** mutex and returns a pointer to it. If it returns NULL
51** that means that a mutex could not be allocated.
pweilbacherec70b6b2007-09-20 21:40:23 +000052** SQLite will unwind its stack and return an error. The argument
53** to sqlite3_mutex_alloc() is one of these integer constants:
54**
55** <ul>
56** <li> SQLITE_MUTEX_FAST 0
57** <li> SQLITE_MUTEX_RECURSIVE 1
58** <li> SQLITE_MUTEX_STATIC_MASTER 2
59** <li> SQLITE_MUTEX_STATIC_MEM 3
60** <li> SQLITE_MUTEX_STATIC_PRNG 4
61** </ul>
62**
63** The first two constants cause sqlite3_mutex_alloc() to create
64** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
65** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
66** The mutex implementation does not need to make a distinction
67** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
68** not want to. But SQLite will only request a recursive mutex in
69** cases where it really needs one. If a faster non-recursive mutex
70** implementation is available on the host platform, the mutex subsystem
71** might return such a mutex in response to SQLITE_MUTEX_FAST.
72**
73** The other allowed parameters to sqlite3_mutex_alloc() each return
74** a pointer to a static preexisting mutex. Three static mutexes are
75** used by the current version of SQLite. Future versions of SQLite
76** may add additional static mutexes. Static mutexes are for internal
77** use by SQLite only. Applications that use SQLite mutexes should
78** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
79** SQLITE_MUTEX_RECURSIVE.
80**
81** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
82** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
83** returns a different mutex on every call. But for the static
84** mutex types, the same mutex is returned on every call that has
85** the same type number.
drh437b9012007-08-28 16:34:42 +000086*/
pweilbacher26169642008-06-23 22:13:27 +000087static sqlite3_mutex *os2MutexAlloc(int iType){
pweilbacherdc965c32008-02-01 19:42:37 +000088 sqlite3_mutex *p = NULL;
pweilbacherec70b6b2007-09-20 21:40:23 +000089 switch( iType ){
drh437b9012007-08-28 16:34:42 +000090 case SQLITE_MUTEX_FAST:
91 case SQLITE_MUTEX_RECURSIVE: {
pweilbacherec70b6b2007-09-20 21:40:23 +000092 p = sqlite3MallocZero( sizeof(*p) );
93 if( p ){
pweilbacherec70b6b2007-09-20 21:40:23 +000094 p->id = iType;
pweilbacherdc965c32008-02-01 19:42:37 +000095 if( DosCreateMutexSem( 0, &p->mutex, 0, FALSE ) != NO_ERROR ){
96 sqlite3_free( p );
97 p = NULL;
98 }
drh437b9012007-08-28 16:34:42 +000099 }
100 break;
101 }
102 default: {
pweilbacherdc965c32008-02-01 19:42:37 +0000103 static volatile int isInit = 0;
104 static sqlite3_mutex staticMutexes[] = {
105 { OS2_MUTEX_INITIALIZER, },
106 { OS2_MUTEX_INITIALIZER, },
107 { OS2_MUTEX_INITIALIZER, },
108 { OS2_MUTEX_INITIALIZER, },
109 { OS2_MUTEX_INITIALIZER, },
danielk1977dfb316d2008-03-26 18:34:43 +0000110 { OS2_MUTEX_INITIALIZER, },
pweilbacherdc965c32008-02-01 19:42:37 +0000111 };
112 if ( !isInit ){
113 APIRET rc;
114 PTIB ptib;
115 PPIB ppib;
116 HMTX mutex;
117 char name[32];
118 DosGetInfoBlocks( &ptib, &ppib );
119 sqlite3_snprintf( sizeof(name), name, "\\SEM32\\SQLITE%04x",
120 ppib->pib_ulpid );
121 while( !isInit ){
122 mutex = 0;
123 rc = DosCreateMutexSem( name, &mutex, 0, FALSE);
124 if( rc == NO_ERROR ){
pweilbacherc06b54f2008-11-22 19:50:53 +0000125 unsigned int i;
pweilbacherdc965c32008-02-01 19:42:37 +0000126 if( !isInit ){
127 for( i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++ ){
128 DosCreateMutexSem( 0, &staticMutexes[i].mutex, 0, FALSE );
129 }
130 isInit = 1;
131 }
132 DosCloseMutexSem( mutex );
133 }else if( rc == ERROR_DUPLICATE_NAME ){
134 DosSleep( 1 );
135 }else{
136 return p;
pweilbacherec70b6b2007-09-20 21:40:23 +0000137 }
pweilbacherec70b6b2007-09-20 21:40:23 +0000138 }
139 }
140 assert( iType-2 >= 0 );
141 assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
142 p = &staticMutexes[iType-2];
143 p->id = iType;
drh437b9012007-08-28 16:34:42 +0000144 break;
145 }
146 }
pweilbacherec70b6b2007-09-20 21:40:23 +0000147 return p;
drh437b9012007-08-28 16:34:42 +0000148}
149
pweilbacherec70b6b2007-09-20 21:40:23 +0000150
drh437b9012007-08-28 16:34:42 +0000151/*
152** This routine deallocates a previously allocated mutex.
pweilbacherec70b6b2007-09-20 21:40:23 +0000153** SQLite is careful to deallocate every mutex that it allocates.
drh437b9012007-08-28 16:34:42 +0000154*/
pweilbacher26169642008-06-23 22:13:27 +0000155static void os2MutexFree(sqlite3_mutex *p){
drh40257ff2008-06-13 18:24:27 +0000156 if( p==0 ) return;
pweilbacherec70b6b2007-09-20 21:40:23 +0000157 assert( p->nRef==0 );
drh437b9012007-08-28 16:34:42 +0000158 assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
pweilbacherdc965c32008-02-01 19:42:37 +0000159 DosCloseMutexSem( p->mutex );
160 sqlite3_free( p );
drh437b9012007-08-28 16:34:42 +0000161}
162
163/*
164** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
165** to enter a mutex. If another thread is already within the mutex,
166** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
167** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
168** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
169** be entered multiple times by the same thread. In such cases the,
170** mutex must be exited an equal number of times before another thread
171** can enter. If the same thread tries to enter any other kind of mutex
172** more than once, the behavior is undefined.
173*/
pweilbacher26169642008-06-23 22:13:27 +0000174static void os2MutexEnter(sqlite3_mutex *p){
pweilbacherec70b6b2007-09-20 21:40:23 +0000175 TID tid;
176 PID holder1;
177 ULONG holder2;
drh40257ff2008-06-13 18:24:27 +0000178 if( p==0 ) return;
pweilbacher26169642008-06-23 22:13:27 +0000179 assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
pweilbacherec70b6b2007-09-20 21:40:23 +0000180 DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT);
181 DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
182 p->owner = tid;
183 p->nRef++;
drh437b9012007-08-28 16:34:42 +0000184}
pweilbacher26169642008-06-23 22:13:27 +0000185static int os2MutexTry(sqlite3_mutex *p){
pweilbacherec70b6b2007-09-20 21:40:23 +0000186 int rc;
187 TID tid;
188 PID holder1;
189 ULONG holder2;
drh40257ff2008-06-13 18:24:27 +0000190 if( p==0 ) return SQLITE_OK;
pweilbacher26169642008-06-23 22:13:27 +0000191 assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
pweilbacherec70b6b2007-09-20 21:40:23 +0000192 if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR) {
193 DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
194 p->owner = tid;
195 p->nRef++;
196 rc = SQLITE_OK;
197 } else {
198 rc = SQLITE_BUSY;
199 }
200
201 return rc;
drh437b9012007-08-28 16:34:42 +0000202}
203
204/*
205** The sqlite3_mutex_leave() routine exits a mutex that was
206** previously entered by the same thread. The behavior
207** is undefined if the mutex is not currently entered or
208** is not currently allocated. SQLite will never do either.
209*/
pweilbacher26169642008-06-23 22:13:27 +0000210static void os2MutexLeave(sqlite3_mutex *p){
pweilbacherec70b6b2007-09-20 21:40:23 +0000211 TID tid;
212 PID holder1;
213 ULONG holder2;
drh40257ff2008-06-13 18:24:27 +0000214 if( p==0 ) return;
pweilbacherec70b6b2007-09-20 21:40:23 +0000215 assert( p->nRef>0 );
216 DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
217 assert( p->owner==tid );
218 p->nRef--;
219 assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
220 DosReleaseMutexSem(p->mutex);
drh437b9012007-08-28 16:34:42 +0000221}
222
pweilbacher26169642008-06-23 22:13:27 +0000223#ifdef SQLITE_DEBUG
drh437b9012007-08-28 16:34:42 +0000224/*
225** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
226** intended for use inside assert() statements.
227*/
pweilbacher26169642008-06-23 22:13:27 +0000228static int os2MutexHeld(sqlite3_mutex *p){
pweilbacherec70b6b2007-09-20 21:40:23 +0000229 TID tid;
230 PID pid;
231 ULONG ulCount;
232 PTIB ptib;
233 if( p!=0 ) {
234 DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
235 } else {
236 DosGetInfoBlocks(&ptib, NULL);
237 tid = ptib->tib_ptib2->tib2_ultid;
238 }
239 return p==0 || (p->nRef!=0 && p->owner==tid);
drh437b9012007-08-28 16:34:42 +0000240}
pweilbacher26169642008-06-23 22:13:27 +0000241static int os2MutexNotheld(sqlite3_mutex *p){
pweilbacherec70b6b2007-09-20 21:40:23 +0000242 TID tid;
243 PID pid;
244 ULONG ulCount;
245 PTIB ptib;
246 if( p!= 0 ) {
247 DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
248 } else {
249 DosGetInfoBlocks(&ptib, NULL);
250 tid = ptib->tib_ptib2->tib2_ultid;
251 }
252 return p==0 || p->nRef==0 || p->owner!=tid;
drh437b9012007-08-28 16:34:42 +0000253}
pweilbacher26169642008-06-23 22:13:27 +0000254#endif
pweilbacher6a9773e2008-06-18 21:08:16 +0000255
256sqlite3_mutex_methods *sqlite3DefaultMutex(void){
257 static sqlite3_mutex_methods sMutex = {
258 os2MutexInit,
danielk19774a9d1f62008-06-19 08:51:23 +0000259 os2MutexEnd,
pweilbacher6a9773e2008-06-18 21:08:16 +0000260 os2MutexAlloc,
261 os2MutexFree,
262 os2MutexEnter,
263 os2MutexTry,
264 os2MutexLeave,
pweilbacher26169642008-06-23 22:13:27 +0000265#ifdef SQLITE_DEBUG
pweilbacher6a9773e2008-06-18 21:08:16 +0000266 os2MutexHeld,
267 os2MutexNotheld
pweilbacher26169642008-06-23 22:13:27 +0000268#endif
pweilbacher6a9773e2008-06-18 21:08:16 +0000269 };
270
271 return &sMutex;
272}
drh437b9012007-08-28 16:34:42 +0000273#endif /* SQLITE_MUTEX_OS2 */