persistentstorage/sqlite3api/SQLite/mutex_os2.c
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     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 ** $Id: mutex_os2.c,v 1.10 2008/06/23 22:13:28 pweilbacher Exp $
       
    15 */
       
    16 #include "sqliteInt.h"
       
    17 
       
    18 /*
       
    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 
       
    24 /********************** OS/2 Mutex Implementation **********************
       
    25 **
       
    26 ** This implementation of mutexes is built using the OS/2 API.
       
    27 */
       
    28 
       
    29 /*
       
    30 ** The mutex object
       
    31 ** Each recursive mutex is an instance of the following structure.
       
    32 */
       
    33 struct sqlite3_mutex {
       
    34   HMTX mutex;       /* Mutex controlling the lock */
       
    35   int  id;          /* Mutex type */
       
    36   int  nRef;        /* Number of references */
       
    37   TID  owner;       /* Thread holding this mutex */
       
    38 };
       
    39 
       
    40 #define OS2_MUTEX_INITIALIZER   0,0,0,0
       
    41 
       
    42 /*
       
    43 ** Initialize and deinitialize the mutex subsystem.
       
    44 */
       
    45 static int os2MutexInit(void){ return SQLITE_OK; }
       
    46 static int os2MutexEnd(void){ return SQLITE_OK; }
       
    47 
       
    48 /*
       
    49 ** 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. 
       
    52 ** 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.
       
    86 */
       
    87 static sqlite3_mutex *os2MutexAlloc(int iType){
       
    88   sqlite3_mutex *p = NULL;
       
    89   switch( iType ){
       
    90     case SQLITE_MUTEX_FAST:
       
    91     case SQLITE_MUTEX_RECURSIVE: {
       
    92       p = sqlite3MallocZero( sizeof(*p) );
       
    93       if( p ){
       
    94         p->id = iType;
       
    95         if( DosCreateMutexSem( 0, &p->mutex, 0, FALSE ) != NO_ERROR ){
       
    96           sqlite3_free( p );
       
    97           p = NULL;
       
    98         }
       
    99       }
       
   100       break;
       
   101     }
       
   102     default: {
       
   103       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, },
       
   110         { OS2_MUTEX_INITIALIZER, },
       
   111       };
       
   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 ){
       
   125             int i;
       
   126             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;
       
   137           }
       
   138         }
       
   139       }
       
   140       assert( iType-2 >= 0 );
       
   141       assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
       
   142       p = &staticMutexes[iType-2];
       
   143       p->id = iType;
       
   144       break;
       
   145     }
       
   146   }
       
   147   return p;
       
   148 }
       
   149 
       
   150 
       
   151 /*
       
   152 ** This routine deallocates a previously allocated mutex.
       
   153 ** SQLite is careful to deallocate every mutex that it allocates.
       
   154 */
       
   155 static void os2MutexFree(sqlite3_mutex *p){
       
   156   if( p==0 ) return;
       
   157   assert( p->nRef==0 );
       
   158   assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
       
   159   DosCloseMutexSem( p->mutex );
       
   160   sqlite3_free( p );
       
   161 }
       
   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 */
       
   174 static void os2MutexEnter(sqlite3_mutex *p){
       
   175   TID tid;
       
   176   PID holder1;
       
   177   ULONG holder2;
       
   178   if( p==0 ) return;
       
   179   assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
       
   180   DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT);
       
   181   DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
       
   182   p->owner = tid;
       
   183   p->nRef++;
       
   184 }
       
   185 static int os2MutexTry(sqlite3_mutex *p){
       
   186   int rc;
       
   187   TID tid;
       
   188   PID holder1;
       
   189   ULONG holder2;
       
   190   if( p==0 ) return SQLITE_OK;
       
   191   assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
       
   192   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;
       
   202 }
       
   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 */
       
   210 static void os2MutexLeave(sqlite3_mutex *p){
       
   211   TID tid;
       
   212   PID holder1;
       
   213   ULONG holder2;
       
   214   if( p==0 ) return;
       
   215   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);
       
   221 }
       
   222 
       
   223 #ifdef SQLITE_DEBUG
       
   224 /*
       
   225 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
       
   226 ** intended for use inside assert() statements.
       
   227 */
       
   228 static int os2MutexHeld(sqlite3_mutex *p){
       
   229   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);
       
   240 }
       
   241 static int os2MutexNotheld(sqlite3_mutex *p){
       
   242   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;
       
   253 }
       
   254 #endif
       
   255 
       
   256 sqlite3_mutex_methods *sqlite3DefaultMutex(void){
       
   257   static sqlite3_mutex_methods sMutex = {
       
   258     os2MutexInit,
       
   259     os2MutexEnd,
       
   260     os2MutexAlloc,
       
   261     os2MutexFree,
       
   262     os2MutexEnter,
       
   263     os2MutexTry,
       
   264     os2MutexLeave,
       
   265 #ifdef SQLITE_DEBUG
       
   266     os2MutexHeld,
       
   267     os2MutexNotheld
       
   268 #endif
       
   269   };
       
   270 
       
   271   return &sMutex;
       
   272 }
       
   273 #endif /* SQLITE_MUTEX_OS2 */