Annotation of embedaddon/sqlite3/src/mutex_os2.c, revision 1.1

1.1     ! misho       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: */
        !            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
        !            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: */
        !            48: static int os2MutexInit(void){ return SQLITE_OK; }
        !            49: static 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: */
        !            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;
        !           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: */
        !           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 );
        !           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: */
        !           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;
        !           189: }
        !           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;
        !           200: }
        !           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);
        !           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: */
        !           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
        !           227: }
        !           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
        !           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: */
        !           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
        !           252: }
        !           253: 
        !           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
        !           267:     0,
        !           268:     0
        !           269: #endif
        !           270:   };
        !           271: 
        !           272:   return &sMutex;
        !           273: }
        !           274: #endif /* SQLITE_MUTEX_OS2 */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>