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.
10**
11*************************************************************************
12** This file contains the C functions that implement mutexes for OS/2
13*/
14#include "sqliteInt.h"
15
16/*
17** The code in this file is only used if SQLITE_MUTEX_OS2 is defined.
18** See the mutex.h file for details.
19*/
20#ifdef SQLITE_MUTEX_OS2
21
22/********************** OS/2 Mutex Implementation **********************
23**
24** This implementation of mutexes is built using the OS/2 API.
25*/
26
27/*
28** The mutex object
29** Each recursive mutex is an instance of the following structure.
30*/
31struct 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
37};
38
39#ifdef SQLITE_DEBUG
40#define SQLITE3_MUTEX_INITIALIZER { 0, 0, 0 }
41#else
42#define SQLITE3_MUTEX_INITIALIZER { 0, 0 }
43#endif
44
45/*
46** Initialize and deinitialize the mutex subsystem.
47*/
48static int os2MutexInit(void){ return SQLITE_OK; }
49static int os2MutexEnd(void){ return SQLITE_OK; }
50
51/*
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:
57**
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>
68**
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.
78**
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.
86**
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.
92*/
93static 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;
104        }
105      }
106      break;
107    }
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,
117      };
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 );
135              }
136              isInit = 1;
137            }
138            DosCloseMutexSem( mutex );
139          }else if( rc == ERROR_DUPLICATE_NAME ){
140            DosSleep( 1 );
141          }else{
142            return p;
143          }
144        }
145      }
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;
151    }
152  }
153  return p;
154}
155
156
157/*
158** This routine deallocates a previously allocated mutex.
159** SQLite is careful to deallocate every mutex that it allocates.
160*/
161static 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 );
172}
173
174#ifdef SQLITE_DEBUG
175/*
176** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
177** intended for use inside assert() statements.
178*/
179static 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;
189}
190static 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;
200}
201static 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);
207}
208#endif
209
210/*
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.
220*/
221static 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
227}
228static 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
236  }
237  return rc;
238}
239
240/*
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.
245*/
246static 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
252}
253
254sqlite3_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
267    0,
268    0
269#endif
270  };
271
272  return &sMutex;
273}
274#endif /* SQLITE_MUTEX_OS2 */
275