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>