modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/lsm1/lsm_unix.c (about)

     1  /*
     2  ** 2011-12-03
     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  **
    13  ** Unix-specific run-time environment implementation for LSM.
    14  */
    15  
    16  #ifndef _WIN32
    17  
    18  #if defined(__GNUC__) || defined(__TINYC__)
    19  /* workaround for ftruncate() visibility on gcc. */
    20  # ifndef _XOPEN_SOURCE
    21  #  define _XOPEN_SOURCE 500
    22  # endif
    23  #endif
    24  
    25  #include <unistd.h>
    26  #include <sys/types.h>
    27  
    28  #include <sys/stat.h>
    29  #include <fcntl.h>
    30  #include <assert.h>
    31  #include <string.h>
    32  
    33  #include <stdlib.h>
    34  #include <stdarg.h>
    35  #include <stdio.h>
    36  #include <ctype.h>
    37  
    38  #include <unistd.h>
    39  #include <errno.h>
    40  
    41  #include <sys/mman.h>
    42  #include "lsmInt.h"
    43  
    44  /* There is no fdatasync() call on Android */
    45  #ifdef __ANDROID__
    46  # define fdatasync(x) fsync(x)
    47  #endif
    48  
    49  /*
    50  ** An open file is an instance of the following object
    51  */
    52  typedef struct PosixFile PosixFile;
    53  struct PosixFile {
    54    lsm_env *pEnv;                  /* The run-time environment */
    55    const char *zName;              /* Full path to file */
    56    int fd;                         /* The open file descriptor */
    57    int shmfd;                      /* Shared memory file-descriptor */
    58    void *pMap;                     /* Pointer to mapping of file fd */
    59    off_t nMap;                     /* Size of mapping at pMap in bytes */
    60    int nShm;                       /* Number of entries in array apShm[] */
    61    void **apShm;                   /* Array of 32K shared memory segments */
    62  };
    63  
    64  static char *posixShmFile(PosixFile *p){
    65    char *zShm;
    66    int nName = strlen(p->zName);
    67    zShm = (char *)lsmMalloc(p->pEnv, nName+4+1);
    68    if( zShm ){
    69      memcpy(zShm, p->zName, nName);
    70      memcpy(&zShm[nName], "-shm", 5);
    71    }
    72    return zShm;
    73  }
    74  
    75  static int lsmPosixOsOpen(
    76    lsm_env *pEnv,
    77    const char *zFile,
    78    int flags,
    79    lsm_file **ppFile
    80  ){
    81    int rc = LSM_OK;
    82    PosixFile *p;
    83  
    84    p = lsm_malloc(pEnv, sizeof(PosixFile));
    85    if( p==0 ){
    86      rc = LSM_NOMEM;
    87    }else{
    88      int bReadonly = (flags & LSM_OPEN_READONLY);
    89      int oflags = (bReadonly ? O_RDONLY : (O_RDWR|O_CREAT));
    90      memset(p, 0, sizeof(PosixFile));
    91      p->zName = zFile;
    92      p->pEnv = pEnv;
    93      p->fd = open(zFile, oflags, 0644);
    94      if( p->fd<0 ){
    95        lsm_free(pEnv, p);
    96        p = 0;
    97        if( errno==ENOENT ){
    98          rc = lsmErrorBkpt(LSM_IOERR_NOENT);
    99        }else{
   100          rc = LSM_IOERR_BKPT;
   101        }
   102      }
   103    }
   104  
   105    *ppFile = (lsm_file *)p;
   106    return rc;
   107  }
   108  
   109  static int lsmPosixOsWrite(
   110    lsm_file *pFile,                /* File to write to */
   111    lsm_i64 iOff,                   /* Offset to write to */
   112    void *pData,                    /* Write data from this buffer */
   113    int nData                       /* Bytes of data to write */
   114  ){
   115    int rc = LSM_OK;
   116    PosixFile *p = (PosixFile *)pFile;
   117    off_t offset;
   118  
   119    offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
   120    if( offset!=iOff ){
   121      rc = LSM_IOERR_BKPT;
   122    }else{
   123      ssize_t prc = write(p->fd, pData, (size_t)nData);
   124      if( prc<0 ) rc = LSM_IOERR_BKPT;
   125    }
   126  
   127    return rc;
   128  }
   129  
   130  static int lsmPosixOsTruncate(
   131    lsm_file *pFile,                /* File to write to */
   132    lsm_i64 nSize                   /* Size to truncate file to */
   133  ){
   134    PosixFile *p = (PosixFile *)pFile;
   135    int rc = LSM_OK;                /* Return code */
   136    int prc;                        /* Posix Return Code */
   137    struct stat sStat;              /* Result of fstat() invocation */
   138    
   139    prc = fstat(p->fd, &sStat);
   140    if( prc==0 && sStat.st_size>nSize ){
   141      prc = ftruncate(p->fd, (off_t)nSize);
   142    }
   143    if( prc<0 ) rc = LSM_IOERR_BKPT;
   144  
   145    return rc;
   146  }
   147  
   148  static int lsmPosixOsRead(
   149    lsm_file *pFile,                /* File to read from */
   150    lsm_i64 iOff,                   /* Offset to read from */
   151    void *pData,                    /* Read data into this buffer */
   152    int nData                       /* Bytes of data to read */
   153  ){
   154    int rc = LSM_OK;
   155    PosixFile *p = (PosixFile *)pFile;
   156    off_t offset;
   157  
   158    offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
   159    if( offset!=iOff ){
   160      rc = LSM_IOERR_BKPT;
   161    }else{
   162      ssize_t prc = read(p->fd, pData, (size_t)nData);
   163      if( prc<0 ){ 
   164        rc = LSM_IOERR_BKPT;
   165      }else if( prc<nData ){
   166        memset(&((u8 *)pData)[prc], 0, nData - prc);
   167      }
   168  
   169    }
   170  
   171    return rc;
   172  }
   173  
   174  static int lsmPosixOsSync(lsm_file *pFile){
   175    int rc = LSM_OK;
   176  
   177  #ifndef LSM_NO_SYNC
   178    PosixFile *p = (PosixFile *)pFile;
   179    int prc = 0;
   180  
   181    if( p->pMap ){
   182      prc = msync(p->pMap, p->nMap, MS_SYNC);
   183    }
   184    if( prc==0 ) prc = fdatasync(p->fd);
   185    if( prc<0 ) rc = LSM_IOERR_BKPT;
   186  #else
   187    (void)pFile;
   188  #endif
   189  
   190    return rc;
   191  }
   192  
   193  static int lsmPosixOsSectorSize(lsm_file *pFile){
   194    return 512;
   195  }
   196  
   197  static int lsmPosixOsRemap(
   198    lsm_file *pFile, 
   199    lsm_i64 iMin, 
   200    void **ppOut,
   201    lsm_i64 *pnOut
   202  ){
   203    off_t iSz;
   204    int prc;
   205    PosixFile *p = (PosixFile *)pFile;
   206    struct stat buf;
   207  
   208    /* If the file is between 0 and 2MB in size, extend it in chunks of 256K.
   209    ** Thereafter, in chunks of 1MB at a time.  */
   210    const int aIncrSz[] = {256*1024, 1024*1024};
   211    int nIncrSz = aIncrSz[iMin>(2*1024*1024)];
   212  
   213    if( p->pMap ){
   214      munmap(p->pMap, p->nMap);
   215      *ppOut = p->pMap = 0;
   216      *pnOut = p->nMap = 0;
   217    }
   218  
   219    if( iMin>=0 ){
   220      memset(&buf, 0, sizeof(buf));
   221      prc = fstat(p->fd, &buf);
   222      if( prc!=0 ) return LSM_IOERR_BKPT;
   223      iSz = buf.st_size;
   224      if( iSz<iMin ){
   225        iSz = ((iMin + nIncrSz-1) / nIncrSz) * nIncrSz;
   226        prc = ftruncate(p->fd, iSz);
   227        if( prc!=0 ) return LSM_IOERR_BKPT;
   228      }
   229  
   230      p->pMap = mmap(0, iSz, PROT_READ|PROT_WRITE, MAP_SHARED, p->fd, 0);
   231      p->nMap = iSz;
   232    }
   233  
   234    *ppOut = p->pMap;
   235    *pnOut = p->nMap;
   236    return LSM_OK;
   237  }
   238  
   239  static int lsmPosixOsFullpath(
   240    lsm_env *pEnv,
   241    const char *zName,
   242    char *zOut,
   243    int *pnOut
   244  ){
   245    int nBuf = *pnOut;
   246    int nReq;
   247  
   248    if( zName[0]!='/' ){
   249      char *z;
   250      char *zTmp;
   251      int nTmp = 512;
   252      zTmp = lsmMalloc(pEnv, nTmp);
   253      while( zTmp ){
   254        z = getcwd(zTmp, nTmp);
   255        if( z || errno!=ERANGE ) break;
   256        nTmp = nTmp*2;
   257        zTmp = lsmReallocOrFree(pEnv, zTmp, nTmp);
   258      }
   259      if( zTmp==0 ) return LSM_NOMEM_BKPT;
   260      if( z==0 ) return LSM_IOERR_BKPT;
   261      assert( z==zTmp );
   262  
   263      nTmp = strlen(zTmp);
   264      nReq = nTmp + 1 + strlen(zName) + 1;
   265      if( nReq<=nBuf ){
   266        memcpy(zOut, zTmp, nTmp);
   267        zOut[nTmp] = '/';
   268        memcpy(&zOut[nTmp+1], zName, strlen(zName)+1);
   269      }
   270      lsmFree(pEnv, zTmp);
   271    }else{
   272      nReq = strlen(zName)+1;
   273      if( nReq<=nBuf ){
   274        memcpy(zOut, zName, strlen(zName)+1);
   275      }
   276    }
   277  
   278    *pnOut = nReq;
   279    return LSM_OK;
   280  }
   281  
   282  static int lsmPosixOsFileid(
   283    lsm_file *pFile, 
   284    void *pBuf,
   285    int *pnBuf
   286  ){
   287    int prc;
   288    int nBuf;
   289    int nReq;
   290    PosixFile *p = (PosixFile *)pFile;
   291    struct stat buf;
   292  
   293    nBuf = *pnBuf;
   294    nReq = (sizeof(buf.st_dev) + sizeof(buf.st_ino));
   295    *pnBuf = nReq;
   296    if( nReq>nBuf ) return LSM_OK;
   297  
   298    memset(&buf, 0, sizeof(buf));
   299    prc = fstat(p->fd, &buf);
   300    if( prc!=0 ) return LSM_IOERR_BKPT;
   301  
   302    memcpy(pBuf, &buf.st_dev, sizeof(buf.st_dev));
   303    memcpy(&(((u8 *)pBuf)[sizeof(buf.st_dev)]), &buf.st_ino, sizeof(buf.st_ino));
   304    return LSM_OK;
   305  }
   306  
   307  static int lsmPosixOsUnlink(lsm_env *pEnv, const char *zFile){
   308    int prc = unlink(zFile);
   309    return prc ? LSM_IOERR_BKPT : LSM_OK;
   310  }
   311  
   312  static int lsmPosixOsLock(lsm_file *pFile, int iLock, int eType){
   313    int rc = LSM_OK;
   314    PosixFile *p = (PosixFile *)pFile;
   315    static const short aType[3] = { F_UNLCK, F_RDLCK, F_WRLCK };
   316    struct flock lock;
   317  
   318    assert( aType[LSM_LOCK_UNLOCK]==F_UNLCK );
   319    assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
   320    assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
   321    assert( eType>=0 && eType<array_size(aType) );
   322    assert( iLock>0 && iLock<=32 );
   323  
   324    memset(&lock, 0, sizeof(lock));
   325    lock.l_whence = SEEK_SET;
   326    lock.l_len = 1;
   327    lock.l_type = aType[eType];
   328    lock.l_start = (4096-iLock);
   329  
   330    if( fcntl(p->fd, F_SETLK, &lock) ){
   331      int e = errno;
   332      if( e==EACCES || e==EAGAIN ){
   333        rc = LSM_BUSY;
   334      }else{
   335        rc = LSM_IOERR_BKPT;
   336      }
   337    }
   338  
   339    return rc;
   340  }
   341  
   342  static int lsmPosixOsTestLock(lsm_file *pFile, int iLock, int nLock, int eType){
   343    int rc = LSM_OK;
   344    PosixFile *p = (PosixFile *)pFile;
   345    static const short aType[3] = { 0, F_RDLCK, F_WRLCK };
   346    struct flock lock;
   347  
   348    assert( eType==LSM_LOCK_SHARED || eType==LSM_LOCK_EXCL );
   349    assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
   350    assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
   351    assert( eType>=0 && eType<array_size(aType) );
   352    assert( iLock>0 && iLock<=32 );
   353  
   354    memset(&lock, 0, sizeof(lock));
   355    lock.l_whence = SEEK_SET;
   356    lock.l_len = nLock;
   357    lock.l_type = aType[eType];
   358    lock.l_start = (4096-iLock-nLock+1);
   359  
   360    if( fcntl(p->fd, F_GETLK, &lock) ){
   361      rc = LSM_IOERR_BKPT;
   362    }else if( lock.l_type!=F_UNLCK ){
   363      rc = LSM_BUSY;
   364    }
   365  
   366    return rc;
   367  }
   368  
   369  static int lsmPosixOsShmMap(lsm_file *pFile, int iChunk, int sz, void **ppShm){
   370    PosixFile *p = (PosixFile *)pFile;
   371  
   372    *ppShm = 0;
   373    assert( sz==LSM_SHM_CHUNK_SIZE );
   374    if( iChunk>=p->nShm ){
   375      int i;
   376      void **apNew;
   377      int nNew = iChunk+1;
   378      off_t nReq = nNew * LSM_SHM_CHUNK_SIZE;
   379      struct stat sStat;
   380  
   381      /* If the shared-memory file has not been opened, open it now. */
   382      if( p->shmfd<=0 ){
   383        char *zShm = posixShmFile(p);
   384        if( !zShm ) return LSM_NOMEM_BKPT;
   385        p->shmfd = open(zShm, O_RDWR|O_CREAT, 0644);
   386        lsmFree(p->pEnv, zShm);
   387        if( p->shmfd<0 ){ 
   388          return LSM_IOERR_BKPT;
   389        }
   390      }
   391  
   392      /* If the shared-memory file is not large enough to contain the 
   393      ** requested chunk, cause it to grow.  */
   394      if( fstat(p->shmfd, &sStat) ){
   395        return LSM_IOERR_BKPT;
   396      }
   397      if( sStat.st_size<nReq ){
   398        if( ftruncate(p->shmfd, nReq) ){
   399          return LSM_IOERR_BKPT;
   400        }
   401      }
   402  
   403      apNew = (void **)lsmRealloc(p->pEnv, p->apShm, sizeof(void *) * nNew);
   404      if( !apNew ) return LSM_NOMEM_BKPT;
   405      for(i=p->nShm; i<nNew; i++){
   406        apNew[i] = 0;
   407      }
   408      p->apShm = apNew;
   409      p->nShm = nNew;
   410    }
   411  
   412    if( p->apShm[iChunk]==0 ){
   413      p->apShm[iChunk] = mmap(0, LSM_SHM_CHUNK_SIZE, 
   414          PROT_READ|PROT_WRITE, MAP_SHARED, p->shmfd, iChunk*LSM_SHM_CHUNK_SIZE
   415      );
   416      if( p->apShm[iChunk]==0 ) return LSM_IOERR_BKPT;
   417    }
   418  
   419    *ppShm = p->apShm[iChunk];
   420    return LSM_OK;
   421  }
   422  
   423  static void lsmPosixOsShmBarrier(void){
   424  }
   425  
   426  static int lsmPosixOsShmUnmap(lsm_file *pFile, int bDelete){
   427    PosixFile *p = (PosixFile *)pFile;
   428    if( p->shmfd>0 ){
   429      int i;
   430      for(i=0; i<p->nShm; i++){
   431        if( p->apShm[i] ){
   432          munmap(p->apShm[i], LSM_SHM_CHUNK_SIZE);
   433          p->apShm[i] = 0;
   434        }
   435      }
   436      close(p->shmfd);
   437      p->shmfd = 0;
   438      if( bDelete ){
   439        char *zShm = posixShmFile(p);
   440        if( zShm ) unlink(zShm);
   441        lsmFree(p->pEnv, zShm);
   442      }
   443    }
   444    return LSM_OK;
   445  }
   446  
   447  
   448  static int lsmPosixOsClose(lsm_file *pFile){
   449     PosixFile *p = (PosixFile *)pFile;
   450     lsmPosixOsShmUnmap(pFile, 0);
   451     if( p->pMap ) munmap(p->pMap, p->nMap);
   452     close(p->fd);
   453     lsm_free(p->pEnv, p->apShm);
   454     lsm_free(p->pEnv, p);
   455     return LSM_OK;
   456  }
   457  
   458  static int lsmPosixOsSleep(lsm_env *pEnv, int us){
   459  #if 0
   460    /* Apparently on Android usleep() returns void */
   461    if( usleep(us) ) return LSM_IOERR;
   462  #endif
   463    usleep(us);
   464    return LSM_OK;
   465  }
   466  
   467  /****************************************************************************
   468  ** Memory allocation routines.
   469  */
   470  #define BLOCK_HDR_SIZE ROUND8( sizeof(size_t) )
   471  
   472  static void *lsmPosixOsMalloc(lsm_env *pEnv, size_t N){
   473    unsigned char * m;
   474    N += BLOCK_HDR_SIZE;
   475    m = (unsigned char *)malloc(N);
   476    *((size_t*)m) = N;
   477    return m + BLOCK_HDR_SIZE;
   478  }
   479  
   480  static void lsmPosixOsFree(lsm_env *pEnv, void *p){
   481    if(p){
   482      free( ((unsigned char *)p) - BLOCK_HDR_SIZE );
   483    }
   484  }
   485  
   486  static void *lsmPosixOsRealloc(lsm_env *pEnv, void *p, size_t N){
   487    unsigned char * m = (unsigned char *)p;
   488    if(1>N){
   489      lsmPosixOsFree( pEnv, p );
   490      return NULL;
   491    }else if(NULL==p){
   492      return lsmPosixOsMalloc(pEnv, N);
   493    }else{
   494      void * re = NULL;
   495      m -= BLOCK_HDR_SIZE;
   496  #if 0 /* arguable: don't shrink */
   497      size_t * sz = (size_t*)m;
   498      if(*sz >= (size_t)N){
   499        return p;
   500      }
   501  #endif
   502      re = realloc( m, N + BLOCK_HDR_SIZE );
   503      if(re){
   504        m = (unsigned char *)re;
   505        *((size_t*)m) = N;
   506        return m + BLOCK_HDR_SIZE;
   507      }else{
   508        return NULL;
   509      }
   510    }
   511  }
   512  
   513  static size_t lsmPosixOsMSize(lsm_env *pEnv, void *p){
   514    unsigned char * m = (unsigned char *)p;
   515    return *((size_t*)(m-BLOCK_HDR_SIZE));
   516  }
   517  #undef BLOCK_HDR_SIZE
   518  
   519  
   520  #ifdef LSM_MUTEX_PTHREADS 
   521  /*************************************************************************
   522  ** Mutex methods for pthreads based systems.  If LSM_MUTEX_PTHREADS is
   523  ** missing then a no-op implementation of mutexes found in lsm_mutex.c
   524  ** will be used instead.
   525  */
   526  #include <pthread.h>
   527  
   528  typedef struct PthreadMutex PthreadMutex;
   529  struct PthreadMutex {
   530    lsm_env *pEnv;
   531    pthread_mutex_t mutex;
   532  #ifdef LSM_DEBUG
   533    pthread_t owner;
   534  #endif
   535  };
   536  
   537  #ifdef LSM_DEBUG
   538  # define LSM_PTHREAD_STATIC_MUTEX { 0, PTHREAD_MUTEX_INITIALIZER, 0 }
   539  #else
   540  # define LSM_PTHREAD_STATIC_MUTEX { 0, PTHREAD_MUTEX_INITIALIZER }
   541  #endif
   542  
   543  static int lsmPosixOsMutexStatic(
   544    lsm_env *pEnv,
   545    int iMutex,
   546    lsm_mutex **ppStatic
   547  ){
   548    static PthreadMutex sMutex[2] = {
   549      LSM_PTHREAD_STATIC_MUTEX,
   550      LSM_PTHREAD_STATIC_MUTEX
   551    };
   552  
   553    assert( iMutex==LSM_MUTEX_GLOBAL || iMutex==LSM_MUTEX_HEAP );
   554    assert( LSM_MUTEX_GLOBAL==1 && LSM_MUTEX_HEAP==2 );
   555  
   556    *ppStatic = (lsm_mutex *)&sMutex[iMutex-1];
   557    return LSM_OK;
   558  }
   559  
   560  static int lsmPosixOsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
   561    PthreadMutex *pMutex;           /* Pointer to new mutex */
   562    pthread_mutexattr_t attr;       /* Attributes object */
   563  
   564    pMutex = (PthreadMutex *)lsmMallocZero(pEnv, sizeof(PthreadMutex));
   565    if( !pMutex ) return LSM_NOMEM_BKPT;
   566  
   567    pMutex->pEnv = pEnv;
   568    pthread_mutexattr_init(&attr);
   569    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
   570    pthread_mutex_init(&pMutex->mutex, &attr);
   571    pthread_mutexattr_destroy(&attr);
   572  
   573    *ppNew = (lsm_mutex *)pMutex;
   574    return LSM_OK;
   575  }
   576  
   577  static void lsmPosixOsMutexDel(lsm_mutex *p){
   578    PthreadMutex *pMutex = (PthreadMutex *)p;
   579    pthread_mutex_destroy(&pMutex->mutex);
   580    lsmFree(pMutex->pEnv, pMutex);
   581  }
   582  
   583  static void lsmPosixOsMutexEnter(lsm_mutex *p){
   584    PthreadMutex *pMutex = (PthreadMutex *)p;
   585    pthread_mutex_lock(&pMutex->mutex);
   586  
   587  #ifdef LSM_DEBUG
   588    assert( !pthread_equal(pMutex->owner, pthread_self()) );
   589    pMutex->owner = pthread_self();
   590    assert( pthread_equal(pMutex->owner, pthread_self()) );
   591  #endif
   592  }
   593  
   594  static int lsmPosixOsMutexTry(lsm_mutex *p){
   595    int ret;
   596    PthreadMutex *pMutex = (PthreadMutex *)p;
   597    ret = pthread_mutex_trylock(&pMutex->mutex);
   598  #ifdef LSM_DEBUG
   599    if( ret==0 ){
   600      assert( !pthread_equal(pMutex->owner, pthread_self()) );
   601      pMutex->owner = pthread_self();
   602      assert( pthread_equal(pMutex->owner, pthread_self()) );
   603    }
   604  #endif
   605    return ret;
   606  }
   607  
   608  static void lsmPosixOsMutexLeave(lsm_mutex *p){
   609    PthreadMutex *pMutex = (PthreadMutex *)p;
   610  #ifdef LSM_DEBUG
   611    assert( pthread_equal(pMutex->owner, pthread_self()) );
   612    pMutex->owner = 0;
   613    assert( !pthread_equal(pMutex->owner, pthread_self()) );
   614  #endif
   615    pthread_mutex_unlock(&pMutex->mutex);
   616  }
   617  
   618  #ifdef LSM_DEBUG
   619  static int lsmPosixOsMutexHeld(lsm_mutex *p){
   620    PthreadMutex *pMutex = (PthreadMutex *)p;
   621    return pMutex ? pthread_equal(pMutex->owner, pthread_self()) : 1;
   622  }
   623  static int lsmPosixOsMutexNotHeld(lsm_mutex *p){
   624    PthreadMutex *pMutex = (PthreadMutex *)p;
   625    return pMutex ? !pthread_equal(pMutex->owner, pthread_self()) : 1;
   626  }
   627  #endif
   628  /*
   629  ** End of pthreads mutex implementation.
   630  *************************************************************************/
   631  #else
   632  /*************************************************************************
   633  ** Noop mutex implementation
   634  */
   635  typedef struct NoopMutex NoopMutex;
   636  struct NoopMutex {
   637    lsm_env *pEnv;                  /* Environment handle (for xFree()) */
   638    int bHeld;                      /* True if mutex is held */
   639    int bStatic;                    /* True for a static mutex */
   640  };
   641  static NoopMutex aStaticNoopMutex[2] = {
   642    {0, 0, 1},
   643    {0, 0, 1},
   644  };
   645  
   646  static int lsmPosixOsMutexStatic(
   647    lsm_env *pEnv,
   648    int iMutex,
   649    lsm_mutex **ppStatic
   650  ){
   651    assert( iMutex>=1 && iMutex<=(int)array_size(aStaticNoopMutex) );
   652    *ppStatic = (lsm_mutex *)&aStaticNoopMutex[iMutex-1];
   653    return LSM_OK;
   654  }
   655  static int lsmPosixOsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
   656    NoopMutex *p;
   657    p = (NoopMutex *)lsmMallocZero(pEnv, sizeof(NoopMutex));
   658    if( p ) p->pEnv = pEnv;
   659    *ppNew = (lsm_mutex *)p;
   660    return (p ? LSM_OK : LSM_NOMEM_BKPT);
   661  }
   662  static void lsmPosixOsMutexDel(lsm_mutex *pMutex)  { 
   663    NoopMutex *p = (NoopMutex *)pMutex;
   664    assert( p->bStatic==0 && p->pEnv );
   665    lsmFree(p->pEnv, p);
   666  }
   667  static void lsmPosixOsMutexEnter(lsm_mutex *pMutex){ 
   668    NoopMutex *p = (NoopMutex *)pMutex;
   669    assert( p->bHeld==0 );
   670    p->bHeld = 1;
   671  }
   672  static int lsmPosixOsMutexTry(lsm_mutex *pMutex){
   673    NoopMutex *p = (NoopMutex *)pMutex;
   674    assert( p->bHeld==0 );
   675    p->bHeld = 1;
   676    return 0;
   677  }
   678  static void lsmPosixOsMutexLeave(lsm_mutex *pMutex){ 
   679    NoopMutex *p = (NoopMutex *)pMutex;
   680    assert( p->bHeld==1 );
   681    p->bHeld = 0;
   682  }
   683  #ifdef LSM_DEBUG
   684  static int lsmPosixOsMutexHeld(lsm_mutex *pMutex){ 
   685    NoopMutex *p = (NoopMutex *)pMutex;
   686    return p ? p->bHeld : 1;
   687  }
   688  static int lsmPosixOsMutexNotHeld(lsm_mutex *pMutex){ 
   689    NoopMutex *p = (NoopMutex *)pMutex;
   690    return p ? !p->bHeld : 1;
   691  }
   692  #endif
   693  /***************************************************************************/
   694  #endif /* else LSM_MUTEX_NONE */
   695  
   696  /* Without LSM_DEBUG, the MutexHeld tests are never called */
   697  #ifndef LSM_DEBUG
   698  # define lsmPosixOsMutexHeld    0
   699  # define lsmPosixOsMutexNotHeld 0
   700  #endif
   701  
   702  lsm_env *lsm_default_env(void){
   703    static lsm_env posix_env = {
   704      sizeof(lsm_env),         /* nByte */
   705      1,                       /* iVersion */
   706      /***** file i/o ******************/
   707      0,                       /* pVfsCtx */
   708      lsmPosixOsFullpath,      /* xFullpath */
   709      lsmPosixOsOpen,          /* xOpen */
   710      lsmPosixOsRead,          /* xRead */
   711      lsmPosixOsWrite,         /* xWrite */
   712      lsmPosixOsTruncate,      /* xTruncate */
   713      lsmPosixOsSync,          /* xSync */
   714      lsmPosixOsSectorSize,    /* xSectorSize */
   715      lsmPosixOsRemap,         /* xRemap */
   716      lsmPosixOsFileid,        /* xFileid */
   717      lsmPosixOsClose,         /* xClose */
   718      lsmPosixOsUnlink,        /* xUnlink */
   719      lsmPosixOsLock,          /* xLock */
   720      lsmPosixOsTestLock,      /* xTestLock */
   721      lsmPosixOsShmMap,        /* xShmMap */
   722      lsmPosixOsShmBarrier,    /* xShmBarrier */
   723      lsmPosixOsShmUnmap,      /* xShmUnmap */
   724      /***** memory allocation *********/
   725      0,                       /* pMemCtx */
   726      lsmPosixOsMalloc,        /* xMalloc */
   727      lsmPosixOsRealloc,       /* xRealloc */
   728      lsmPosixOsFree,          /* xFree */
   729      lsmPosixOsMSize,         /* xSize */
   730      /***** mutexes *********************/
   731      0,                       /* pMutexCtx */
   732      lsmPosixOsMutexStatic,   /* xMutexStatic */
   733      lsmPosixOsMutexNew,      /* xMutexNew */
   734      lsmPosixOsMutexDel,      /* xMutexDel */
   735      lsmPosixOsMutexEnter,    /* xMutexEnter */
   736      lsmPosixOsMutexTry,      /* xMutexTry */
   737      lsmPosixOsMutexLeave,    /* xMutexLeave */
   738      lsmPosixOsMutexHeld,     /* xMutexHeld */
   739      lsmPosixOsMutexNotHeld,  /* xMutexNotHeld */
   740      /***** other *********************/
   741      lsmPosixOsSleep,         /* xSleep */
   742    };
   743    return &posix_env;
   744  }
   745  
   746  #endif