mutex_os2.c

Go to the documentation of this file.
00001 /*
00002 ** 2007 August 28
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 *************************************************************************
00012 ** This file contains the C functions that implement mutexes for OS/2
00013 **
00014 ** $Id: mutex_os2.c,v 1.10 2008/06/23 22:13:28 pweilbacher Exp $
00015 */
00016 #include "sqliteInt.h"
00017 
00018 /*
00019 ** The code in this file is only used if SQLITE_MUTEX_OS2 is defined.
00020 ** See the mutex.h file for details.
00021 */
00022 #ifdef SQLITE_MUTEX_OS2
00023 
00024 /********************** OS/2 Mutex Implementation **********************
00025 **
00026 ** This implementation of mutexes is built using the OS/2 API.
00027 */
00028 
00029 /*
00030 ** The mutex object
00031 ** Each recursive mutex is an instance of the following structure.
00032 */
00033 struct sqlite3_mutex {
00034   HMTX mutex;       /* Mutex controlling the lock */
00035   int  id;          /* Mutex type */
00036   int  nRef;        /* Number of references */
00037   TID  owner;       /* Thread holding this mutex */
00038 };
00039 
00040 #define OS2_MUTEX_INITIALIZER   0,0,0,0
00041 
00042 /*
00043 ** Initialize and deinitialize the mutex subsystem.
00044 */
00045 static int os2MutexInit(void){ return SQLITE_OK; }
00046 static int os2MutexEnd(void){ return SQLITE_OK; }
00047 
00048 /*
00049 ** The sqlite3_mutex_alloc() routine allocates a new
00050 ** mutex and returns a pointer to it.  If it returns NULL
00051 ** that means that a mutex could not be allocated. 
00052 ** SQLite will unwind its stack and return an error.  The argument
00053 ** to sqlite3_mutex_alloc() is one of these integer constants:
00054 **
00055 ** <ul>
00056 ** <li>  SQLITE_MUTEX_FAST               0
00057 ** <li>  SQLITE_MUTEX_RECURSIVE          1
00058 ** <li>  SQLITE_MUTEX_STATIC_MASTER      2
00059 ** <li>  SQLITE_MUTEX_STATIC_MEM         3
00060 ** <li>  SQLITE_MUTEX_STATIC_PRNG        4
00061 ** </ul>
00062 **
00063 ** The first two constants cause sqlite3_mutex_alloc() to create
00064 ** a new mutex.  The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
00065 ** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
00066 ** The mutex implementation does not need to make a distinction
00067 ** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
00068 ** not want to.  But SQLite will only request a recursive mutex in
00069 ** cases where it really needs one.  If a faster non-recursive mutex
00070 ** implementation is available on the host platform, the mutex subsystem
00071 ** might return such a mutex in response to SQLITE_MUTEX_FAST.
00072 **
00073 ** The other allowed parameters to sqlite3_mutex_alloc() each return
00074 ** a pointer to a static preexisting mutex.  Three static mutexes are
00075 ** used by the current version of SQLite.  Future versions of SQLite
00076 ** may add additional static mutexes.  Static mutexes are for internal
00077 ** use by SQLite only.  Applications that use SQLite mutexes should
00078 ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
00079 ** SQLITE_MUTEX_RECURSIVE.
00080 **
00081 ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
00082 ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
00083 ** returns a different mutex on every call.  But for the static
00084 ** mutex types, the same mutex is returned on every call that has
00085 ** the same type number.
00086 */
00087 static sqlite3_mutex *os2MutexAlloc(int iType){
00088   sqlite3_mutex *p = NULL;
00089   switch( iType ){
00090     case SQLITE_MUTEX_FAST:
00091     case SQLITE_MUTEX_RECURSIVE: {
00092       p = sqlite3MallocZero( sizeof(*p) );
00093       if( p ){
00094         p->id = iType;
00095         if( DosCreateMutexSem( 0, &p->mutex, 0, FALSE ) != NO_ERROR ){
00096           sqlite3_free( p );
00097           p = NULL;
00098         }
00099       }
00100       break;
00101     }
00102     default: {
00103       static volatile int isInit = 0;
00104       static sqlite3_mutex staticMutexes[] = {
00105         { OS2_MUTEX_INITIALIZER, },
00106         { OS2_MUTEX_INITIALIZER, },
00107         { OS2_MUTEX_INITIALIZER, },
00108         { OS2_MUTEX_INITIALIZER, },
00109         { OS2_MUTEX_INITIALIZER, },
00110         { OS2_MUTEX_INITIALIZER, },
00111       };
00112       if ( !isInit ){
00113         APIRET rc;
00114         PTIB ptib;
00115         PPIB ppib;
00116         HMTX mutex;
00117         char name[32];
00118         DosGetInfoBlocks( &ptib, &ppib );
00119         sqlite3_snprintf( sizeof(name), name, "\\SEM32\\SQLITE%04x",
00120                           ppib->pib_ulpid );
00121         while( !isInit ){
00122           mutex = 0;
00123           rc = DosCreateMutexSem( name, &mutex, 0, FALSE);
00124           if( rc == NO_ERROR ){
00125             int i;
00126             if( !isInit ){
00127               for( i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++ ){
00128                 DosCreateMutexSem( 0, &staticMutexes[i].mutex, 0, FALSE );
00129               }
00130               isInit = 1;
00131             }
00132             DosCloseMutexSem( mutex );
00133           }else if( rc == ERROR_DUPLICATE_NAME ){
00134             DosSleep( 1 );
00135           }else{
00136             return p;
00137           }
00138         }
00139       }
00140       assert( iType-2 >= 0 );
00141       assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
00142       p = &staticMutexes[iType-2];
00143       p->id = iType;
00144       break;
00145     }
00146   }
00147   return p;
00148 }
00149 
00150 
00151 /*
00152 ** This routine deallocates a previously allocated mutex.
00153 ** SQLite is careful to deallocate every mutex that it allocates.
00154 */
00155 static void os2MutexFree(sqlite3_mutex *p){
00156   if( p==0 ) return;
00157   assert( p->nRef==0 );
00158   assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
00159   DosCloseMutexSem( p->mutex );
00160   sqlite3_free( p );
00161 }
00162 
00163 /*
00164 ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
00165 ** to enter a mutex.  If another thread is already within the mutex,
00166 ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
00167 ** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
00168 ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
00169 ** be entered multiple times by the same thread.  In such cases the,
00170 ** mutex must be exited an equal number of times before another thread
00171 ** can enter.  If the same thread tries to enter any other kind of mutex
00172 ** more than once, the behavior is undefined.
00173 */
00174 static void os2MutexEnter(sqlite3_mutex *p){
00175   TID tid;
00176   PID holder1;
00177   ULONG holder2;
00178   if( p==0 ) return;
00179   assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
00180   DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT);
00181   DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
00182   p->owner = tid;
00183   p->nRef++;
00184 }
00185 static int os2MutexTry(sqlite3_mutex *p){
00186   int rc;
00187   TID tid;
00188   PID holder1;
00189   ULONG holder2;
00190   if( p==0 ) return SQLITE_OK;
00191   assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
00192   if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR) {
00193     DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
00194     p->owner = tid;
00195     p->nRef++;
00196     rc = SQLITE_OK;
00197   } else {
00198     rc = SQLITE_BUSY;
00199   }
00200 
00201   return rc;
00202 }
00203 
00204 /*
00205 ** The sqlite3_mutex_leave() routine exits a mutex that was
00206 ** previously entered by the same thread.  The behavior
00207 ** is undefined if the mutex is not currently entered or
00208 ** is not currently allocated.  SQLite will never do either.
00209 */
00210 static void os2MutexLeave(sqlite3_mutex *p){
00211   TID tid;
00212   PID holder1;
00213   ULONG holder2;
00214   if( p==0 ) return;
00215   assert( p->nRef>0 );
00216   DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
00217   assert( p->owner==tid );
00218   p->nRef--;
00219   assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
00220   DosReleaseMutexSem(p->mutex);
00221 }
00222 
00223 #ifdef SQLITE_DEBUG
00224 /*
00225 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
00226 ** intended for use inside assert() statements.
00227 */
00228 static int os2MutexHeld(sqlite3_mutex *p){
00229   TID tid;
00230   PID pid;
00231   ULONG ulCount;
00232   PTIB ptib;
00233   if( p!=0 ) {
00234     DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
00235   } else {
00236     DosGetInfoBlocks(&ptib, NULL);
00237     tid = ptib->tib_ptib2->tib2_ultid;
00238   }
00239   return p==0 || (p->nRef!=0 && p->owner==tid);
00240 }
00241 static int os2MutexNotheld(sqlite3_mutex *p){
00242   TID tid;
00243   PID pid;
00244   ULONG ulCount;
00245   PTIB ptib;
00246   if( p!= 0 ) {
00247     DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
00248   } else {
00249     DosGetInfoBlocks(&ptib, NULL);
00250     tid = ptib->tib_ptib2->tib2_ultid;
00251   }
00252   return p==0 || p->nRef==0 || p->owner!=tid;
00253 }
00254 #endif
00255 
00256 sqlite3_mutex_methods *sqlite3DefaultMutex(void){
00257   static sqlite3_mutex_methods sMutex = {
00258     os2MutexInit,
00259     os2MutexEnd,
00260     os2MutexAlloc,
00261     os2MutexFree,
00262     os2MutexEnter,
00263     os2MutexTry,
00264     os2MutexLeave,
00265 #ifdef SQLITE_DEBUG
00266     os2MutexHeld,
00267     os2MutexNotheld
00268 #endif
00269   };
00270 
00271   return &sMutex;
00272 }
00273 #endif /* SQLITE_MUTEX_OS2 */

ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:55 2011 by Doxygen 1.6.1