mutex_os2.c.svn-base
上传用户:sunhongbo
上传日期:2022-01-25
资源大小:3010k
文件大小:8k
源码类别:

数据库系统

开发平台:

C/C++

  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.6 2008/03/26 18:34:43 danielk1977 Exp $
  15. */
  16. #include "sqliteInt.h"
  17. /*
  18. ** The code in this file is only used if SQLITE_MUTEX_OS2 is defined.
  19. ** See the mutex.h file for details.
  20. */
  21. #ifdef SQLITE_MUTEX_OS2
  22. /********************** OS/2 Mutex Implementation **********************
  23. **
  24. ** This implementation of mutexes is built using the OS/2 API.
  25. */
  26. /*
  27. ** The mutex object
  28. ** Each recursive mutex is an instance of the following structure.
  29. */
  30. struct sqlite3_mutex {
  31.   HMTX mutex;       /* Mutex controlling the lock */
  32.   int  id;          /* Mutex type */
  33.   int  nRef;        /* Number of references */
  34.   TID  owner;       /* Thread holding this mutex */
  35. };
  36. #define OS2_MUTEX_INITIALIZER   0,0,0,0
  37. /*
  38. ** The sqlite3_mutex_alloc() routine allocates a new
  39. ** mutex and returns a pointer to it.  If it returns NULL
  40. ** that means that a mutex could not be allocated. 
  41. ** SQLite will unwind its stack and return an error.  The argument
  42. ** to sqlite3_mutex_alloc() is one of these integer constants:
  43. **
  44. ** <ul>
  45. ** <li>  SQLITE_MUTEX_FAST               0
  46. ** <li>  SQLITE_MUTEX_RECURSIVE          1
  47. ** <li>  SQLITE_MUTEX_STATIC_MASTER      2
  48. ** <li>  SQLITE_MUTEX_STATIC_MEM         3
  49. ** <li>  SQLITE_MUTEX_STATIC_PRNG        4
  50. ** </ul>
  51. **
  52. ** The first two constants cause sqlite3_mutex_alloc() to create
  53. ** a new mutex.  The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
  54. ** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
  55. ** The mutex implementation does not need to make a distinction
  56. ** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
  57. ** not want to.  But SQLite will only request a recursive mutex in
  58. ** cases where it really needs one.  If a faster non-recursive mutex
  59. ** implementation is available on the host platform, the mutex subsystem
  60. ** might return such a mutex in response to SQLITE_MUTEX_FAST.
  61. **
  62. ** The other allowed parameters to sqlite3_mutex_alloc() each return
  63. ** a pointer to a static preexisting mutex.  Three static mutexes are
  64. ** used by the current version of SQLite.  Future versions of SQLite
  65. ** may add additional static mutexes.  Static mutexes are for internal
  66. ** use by SQLite only.  Applications that use SQLite mutexes should
  67. ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
  68. ** SQLITE_MUTEX_RECURSIVE.
  69. **
  70. ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
  71. ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
  72. ** returns a different mutex on every call.  But for the static
  73. ** mutex types, the same mutex is returned on every call that has
  74. ** the same type number.
  75. */
  76. sqlite3_mutex *sqlite3_mutex_alloc(int iType){
  77.   sqlite3_mutex *p = NULL;
  78.   switch( iType ){
  79.     case SQLITE_MUTEX_FAST:
  80.     case SQLITE_MUTEX_RECURSIVE: {
  81.       p = sqlite3MallocZero( sizeof(*p) );
  82.       if( p ){
  83.         p->id = iType;
  84.         if( DosCreateMutexSem( 0, &p->mutex, 0, FALSE ) != NO_ERROR ){
  85.           sqlite3_free( p );
  86.           p = NULL;
  87.         }
  88.       }
  89.       break;
  90.     }
  91.     default: {
  92.       static volatile int isInit = 0;
  93.       static sqlite3_mutex staticMutexes[] = {
  94.         { OS2_MUTEX_INITIALIZER, },
  95.         { OS2_MUTEX_INITIALIZER, },
  96.         { OS2_MUTEX_INITIALIZER, },
  97.         { OS2_MUTEX_INITIALIZER, },
  98.         { OS2_MUTEX_INITIALIZER, },
  99.         { OS2_MUTEX_INITIALIZER, },
  100.       };
  101.       if ( !isInit ){
  102.         APIRET rc;
  103.         PTIB ptib;
  104.         PPIB ppib;
  105.         HMTX mutex;
  106.         char name[32];
  107.         DosGetInfoBlocks( &ptib, &ppib );
  108.         sqlite3_snprintf( sizeof(name), name, "\SEM32\SQLITE%04x",
  109.                           ppib->pib_ulpid );
  110.         while( !isInit ){
  111.           mutex = 0;
  112.           rc = DosCreateMutexSem( name, &mutex, 0, FALSE);
  113.           if( rc == NO_ERROR ){
  114.             int i;
  115.             if( !isInit ){
  116.               for( i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++ ){
  117.                 DosCreateMutexSem( 0, &staticMutexes[i].mutex, 0, FALSE );
  118.               }
  119.               isInit = 1;
  120.             }
  121.             DosCloseMutexSem( mutex );
  122.           }else if( rc == ERROR_DUPLICATE_NAME ){
  123.             DosSleep( 1 );
  124.           }else{
  125.             return p;
  126.           }
  127.         }
  128.       }
  129.       assert( iType-2 >= 0 );
  130.       assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
  131.       p = &staticMutexes[iType-2];
  132.       p->id = iType;
  133.       break;
  134.     }
  135.   }
  136.   return p;
  137. }
  138. /*
  139. ** This routine deallocates a previously allocated mutex.
  140. ** SQLite is careful to deallocate every mutex that it allocates.
  141. */
  142. void sqlite3_mutex_free(sqlite3_mutex *p){
  143.   assert( p );
  144.   assert( p->nRef==0 );
  145.   assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
  146.   DosCloseMutexSem( p->mutex );
  147.   sqlite3_free( p );
  148. }
  149. /*
  150. ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
  151. ** to enter a mutex.  If another thread is already within the mutex,
  152. ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
  153. ** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
  154. ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
  155. ** be entered multiple times by the same thread.  In such cases the,
  156. ** mutex must be exited an equal number of times before another thread
  157. ** can enter.  If the same thread tries to enter any other kind of mutex
  158. ** more than once, the behavior is undefined.
  159. */
  160. void sqlite3_mutex_enter(sqlite3_mutex *p){
  161.   TID tid;
  162.   PID holder1;
  163.   ULONG holder2;
  164.   assert( p );
  165.   assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
  166.   DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT);
  167.   DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
  168.   p->owner = tid;
  169.   p->nRef++;
  170. }
  171. int sqlite3_mutex_try(sqlite3_mutex *p){
  172.   int rc;
  173.   TID tid;
  174.   PID holder1;
  175.   ULONG holder2;
  176.   assert( p );
  177.   assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
  178.   if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR) {
  179.     DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
  180.     p->owner = tid;
  181.     p->nRef++;
  182.     rc = SQLITE_OK;
  183.   } else {
  184.     rc = SQLITE_BUSY;
  185.   }
  186.   return rc;
  187. }
  188. /*
  189. ** The sqlite3_mutex_leave() routine exits a mutex that was
  190. ** previously entered by the same thread.  The behavior
  191. ** is undefined if the mutex is not currently entered or
  192. ** is not currently allocated.  SQLite will never do either.
  193. */
  194. void sqlite3_mutex_leave(sqlite3_mutex *p){
  195.   TID tid;
  196.   PID holder1;
  197.   ULONG holder2;
  198.   assert( p->nRef>0 );
  199.   DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
  200.   assert( p->owner==tid );
  201.   p->nRef--;
  202.   assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
  203.   DosReleaseMutexSem(p->mutex);
  204. }
  205. /*
  206. ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
  207. ** intended for use inside assert() statements.
  208. */
  209. int sqlite3_mutex_held(sqlite3_mutex *p){
  210.   TID tid;
  211.   PID pid;
  212.   ULONG ulCount;
  213.   PTIB ptib;
  214.   if( p!=0 ) {
  215.     DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
  216.   } else {
  217.     DosGetInfoBlocks(&ptib, NULL);
  218.     tid = ptib->tib_ptib2->tib2_ultid;
  219.   }
  220.   return p==0 || (p->nRef!=0 && p->owner==tid);
  221. }
  222. int sqlite3_mutex_notheld(sqlite3_mutex *p){
  223.   TID tid;
  224.   PID pid;
  225.   ULONG ulCount;
  226.   PTIB ptib;
  227.   if( p!= 0 ) {
  228.     DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
  229.   } else {
  230.     DosGetInfoBlocks(&ptib, NULL);
  231.     tid = ptib->tib_ptib2->tib2_ultid;
  232.   }
  233.   return p==0 || p->nRef==0 || p->owner!=tid;
  234. }
  235. #endif /* SQLITE_MUTEX_OS2 */