Annotation of embedaddon/sqlite3/src/mutex_os2.c, revision 1.1.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>