| OLD | NEW | 
 | (Empty) | 
|    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.11 2008/11/22 19:50:54 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             unsigned 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 */ |  | 
| OLD | NEW |