summaryrefslogtreecommitdiffstats
path: root/ext/lsm1/lsm_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/lsm1/lsm_unix.c')
-rw-r--r--ext/lsm1/lsm_unix.c753
1 files changed, 753 insertions, 0 deletions
diff --git a/ext/lsm1/lsm_unix.c b/ext/lsm1/lsm_unix.c
new file mode 100644
index 0000000..88952d1
--- /dev/null
+++ b/ext/lsm1/lsm_unix.c
@@ -0,0 +1,753 @@
+/*
+** 2011-12-03
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** Unix-specific run-time environment implementation for LSM.
+*/
+
+#ifndef _WIN32
+
+#if defined(__GNUC__) || defined(__TINYC__)
+/* workaround for ftruncate() visibility on gcc. */
+# ifndef _XOPEN_SOURCE
+# define _XOPEN_SOURCE 500
+# endif
+#endif
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <string.h>
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/mman.h>
+#include "lsmInt.h"
+
+/* There is no fdatasync() call on Android */
+#ifdef __ANDROID__
+# define fdatasync(x) fsync(x)
+#endif
+
+/*
+** An open file is an instance of the following object
+*/
+typedef struct PosixFile PosixFile;
+struct PosixFile {
+ lsm_env *pEnv; /* The run-time environment */
+ const char *zName; /* Full path to file */
+ int fd; /* The open file descriptor */
+ int shmfd; /* Shared memory file-descriptor */
+ void *pMap; /* Pointer to mapping of file fd */
+ off_t nMap; /* Size of mapping at pMap in bytes */
+ int nShm; /* Number of entries in array apShm[] */
+ void **apShm; /* Array of 32K shared memory segments */
+};
+
+static char *posixShmFile(PosixFile *p){
+ char *zShm;
+ int nName = strlen(p->zName);
+ zShm = (char *)lsmMalloc(p->pEnv, nName+4+1);
+ if( zShm ){
+ memcpy(zShm, p->zName, nName);
+ memcpy(&zShm[nName], "-shm", 5);
+ }
+ return zShm;
+}
+
+static int lsmPosixOsOpen(
+ lsm_env *pEnv,
+ const char *zFile,
+ int flags,
+ lsm_file **ppFile
+){
+ int rc = LSM_OK;
+ PosixFile *p;
+
+ p = lsm_malloc(pEnv, sizeof(PosixFile));
+ if( p==0 ){
+ rc = LSM_NOMEM;
+ }else{
+ int bReadonly = (flags & LSM_OPEN_READONLY);
+ int oflags = (bReadonly ? O_RDONLY : (O_RDWR|O_CREAT));
+ memset(p, 0, sizeof(PosixFile));
+ p->zName = zFile;
+ p->pEnv = pEnv;
+ p->fd = open(zFile, oflags, 0644);
+ if( p->fd<0 ){
+ lsm_free(pEnv, p);
+ p = 0;
+ if( errno==ENOENT ){
+ rc = lsmErrorBkpt(LSM_IOERR_NOENT);
+ }else{
+ rc = LSM_IOERR_BKPT;
+ }
+ }
+ }
+
+ *ppFile = (lsm_file *)p;
+ return rc;
+}
+
+static int lsmPosixOsWrite(
+ lsm_file *pFile, /* File to write to */
+ lsm_i64 iOff, /* Offset to write to */
+ void *pData, /* Write data from this buffer */
+ int nData /* Bytes of data to write */
+){
+ int rc = LSM_OK;
+ PosixFile *p = (PosixFile *)pFile;
+ off_t offset;
+
+ offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
+ if( offset!=iOff ){
+ rc = LSM_IOERR_BKPT;
+ }else{
+ ssize_t prc = write(p->fd, pData, (size_t)nData);
+ if( prc<0 ) rc = LSM_IOERR_BKPT;
+ }
+
+ return rc;
+}
+
+static int lsmPosixOsTruncate(
+ lsm_file *pFile, /* File to write to */
+ lsm_i64 nSize /* Size to truncate file to */
+){
+ PosixFile *p = (PosixFile *)pFile;
+ int rc = LSM_OK; /* Return code */
+ int prc; /* Posix Return Code */
+ struct stat sStat; /* Result of fstat() invocation */
+
+ prc = fstat(p->fd, &sStat);
+ if( prc==0 && sStat.st_size>nSize ){
+ prc = ftruncate(p->fd, (off_t)nSize);
+ }
+ if( prc<0 ) rc = LSM_IOERR_BKPT;
+
+ return rc;
+}
+
+static int lsmPosixOsRead(
+ lsm_file *pFile, /* File to read from */
+ lsm_i64 iOff, /* Offset to read from */
+ void *pData, /* Read data into this buffer */
+ int nData /* Bytes of data to read */
+){
+ int rc = LSM_OK;
+ PosixFile *p = (PosixFile *)pFile;
+ off_t offset;
+
+ offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
+ if( offset!=iOff ){
+ rc = LSM_IOERR_BKPT;
+ }else{
+ ssize_t prc = read(p->fd, pData, (size_t)nData);
+ if( prc<0 ){
+ rc = LSM_IOERR_BKPT;
+ }else if( prc<nData ){
+ memset(&((u8 *)pData)[prc], 0, nData - prc);
+ }
+
+ }
+
+ return rc;
+}
+
+static int lsmPosixOsSync(lsm_file *pFile){
+ int rc = LSM_OK;
+
+#ifndef LSM_NO_SYNC
+ PosixFile *p = (PosixFile *)pFile;
+ int prc = 0;
+
+ if( p->pMap ){
+ prc = msync(p->pMap, p->nMap, MS_SYNC);
+ }
+ if( prc==0 ) prc = fdatasync(p->fd);
+ if( prc<0 ) rc = LSM_IOERR_BKPT;
+#else
+ (void)pFile;
+#endif
+
+ return rc;
+}
+
+static int lsmPosixOsSectorSize(lsm_file *pFile){
+ return 512;
+}
+
+static int lsmPosixOsRemap(
+ lsm_file *pFile,
+ lsm_i64 iMin,
+ void **ppOut,
+ lsm_i64 *pnOut
+){
+ off_t iSz;
+ int prc;
+ PosixFile *p = (PosixFile *)pFile;
+ struct stat buf;
+
+ /* If the file is between 0 and 2MB in size, extend it in chunks of 256K.
+ ** Thereafter, in chunks of 1MB at a time. */
+ const int aIncrSz[] = {256*1024, 1024*1024};
+ int nIncrSz = aIncrSz[iMin>(2*1024*1024)];
+
+ if( p->pMap ){
+ munmap(p->pMap, p->nMap);
+ *ppOut = p->pMap = 0;
+ *pnOut = p->nMap = 0;
+ }
+
+ if( iMin>=0 ){
+ memset(&buf, 0, sizeof(buf));
+ prc = fstat(p->fd, &buf);
+ if( prc!=0 ) return LSM_IOERR_BKPT;
+ iSz = buf.st_size;
+ if( iSz<iMin ){
+ iSz = ((iMin + nIncrSz-1) / nIncrSz) * nIncrSz;
+ prc = ftruncate(p->fd, iSz);
+ if( prc!=0 ) return LSM_IOERR_BKPT;
+ }
+
+ p->pMap = mmap(0, iSz, PROT_READ|PROT_WRITE, MAP_SHARED, p->fd, 0);
+ if( p->pMap==MAP_FAILED ){
+ p->pMap = 0;
+ return LSM_IOERR_BKPT;
+ }
+ p->nMap = iSz;
+ }
+
+ *ppOut = p->pMap;
+ *pnOut = p->nMap;
+ return LSM_OK;
+}
+
+static int lsmPosixOsFullpath(
+ lsm_env *pEnv,
+ const char *zName,
+ char *zOut,
+ int *pnOut
+){
+ int nBuf = *pnOut;
+ int nReq;
+
+ if( zName[0]!='/' ){
+ char *z;
+ char *zTmp;
+ int nTmp = 512;
+ zTmp = lsmMalloc(pEnv, nTmp);
+ while( zTmp ){
+ z = getcwd(zTmp, nTmp);
+ if( z || errno!=ERANGE ) break;
+ nTmp = nTmp*2;
+ zTmp = lsmReallocOrFree(pEnv, zTmp, nTmp);
+ }
+ if( zTmp==0 ) return LSM_NOMEM_BKPT;
+ if( z==0 ) return LSM_IOERR_BKPT;
+ assert( z==zTmp );
+
+ nTmp = strlen(zTmp);
+ nReq = nTmp + 1 + strlen(zName) + 1;
+ if( nReq<=nBuf ){
+ memcpy(zOut, zTmp, nTmp);
+ zOut[nTmp] = '/';
+ memcpy(&zOut[nTmp+1], zName, strlen(zName)+1);
+ }
+ lsmFree(pEnv, zTmp);
+ }else{
+ nReq = strlen(zName)+1;
+ if( nReq<=nBuf ){
+ memcpy(zOut, zName, strlen(zName)+1);
+ }
+ }
+
+ *pnOut = nReq;
+ return LSM_OK;
+}
+
+static int lsmPosixOsFileid(
+ lsm_file *pFile,
+ void *pBuf,
+ int *pnBuf
+){
+ int prc;
+ int nBuf;
+ int nReq;
+ PosixFile *p = (PosixFile *)pFile;
+ struct stat buf;
+
+ nBuf = *pnBuf;
+ nReq = (sizeof(buf.st_dev) + sizeof(buf.st_ino));
+ *pnBuf = nReq;
+ if( nReq>nBuf ) return LSM_OK;
+
+ memset(&buf, 0, sizeof(buf));
+ prc = fstat(p->fd, &buf);
+ if( prc!=0 ) return LSM_IOERR_BKPT;
+
+ memcpy(pBuf, &buf.st_dev, sizeof(buf.st_dev));
+ memcpy(&(((u8 *)pBuf)[sizeof(buf.st_dev)]), &buf.st_ino, sizeof(buf.st_ino));
+ return LSM_OK;
+}
+
+static int lsmPosixOsUnlink(lsm_env *pEnv, const char *zFile){
+ int prc = unlink(zFile);
+ return prc ? LSM_IOERR_BKPT : LSM_OK;
+}
+
+static int lsmPosixOsLock(lsm_file *pFile, int iLock, int eType){
+ int rc = LSM_OK;
+ PosixFile *p = (PosixFile *)pFile;
+ static const short aType[3] = { F_UNLCK, F_RDLCK, F_WRLCK };
+ struct flock lock;
+
+ assert( aType[LSM_LOCK_UNLOCK]==F_UNLCK );
+ assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
+ assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
+ assert( eType>=0 && eType<array_size(aType) );
+ assert( iLock>0 && iLock<=32 );
+
+ memset(&lock, 0, sizeof(lock));
+ lock.l_whence = SEEK_SET;
+ lock.l_len = 1;
+ lock.l_type = aType[eType];
+ lock.l_start = (4096-iLock);
+
+ if( fcntl(p->fd, F_SETLK, &lock) ){
+ int e = errno;
+ if( e==EACCES || e==EAGAIN ){
+ rc = LSM_BUSY;
+ }else{
+ rc = LSM_IOERR_BKPT;
+ }
+ }
+
+ return rc;
+}
+
+static int lsmPosixOsTestLock(lsm_file *pFile, int iLock, int nLock, int eType){
+ int rc = LSM_OK;
+ PosixFile *p = (PosixFile *)pFile;
+ static const short aType[3] = { 0, F_RDLCK, F_WRLCK };
+ struct flock lock;
+
+ assert( eType==LSM_LOCK_SHARED || eType==LSM_LOCK_EXCL );
+ assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
+ assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
+ assert( eType>=0 && eType<array_size(aType) );
+ assert( iLock>0 && iLock<=32 );
+
+ memset(&lock, 0, sizeof(lock));
+ lock.l_whence = SEEK_SET;
+ lock.l_len = nLock;
+ lock.l_type = aType[eType];
+ lock.l_start = (4096-iLock-nLock+1);
+
+ if( fcntl(p->fd, F_GETLK, &lock) ){
+ rc = LSM_IOERR_BKPT;
+ }else if( lock.l_type!=F_UNLCK ){
+ rc = LSM_BUSY;
+ }
+
+ return rc;
+}
+
+static int lsmPosixOsShmMap(lsm_file *pFile, int iChunk, int sz, void **ppShm){
+ PosixFile *p = (PosixFile *)pFile;
+
+ *ppShm = 0;
+ assert( sz==LSM_SHM_CHUNK_SIZE );
+ if( iChunk>=p->nShm ){
+ int i;
+ void **apNew;
+ int nNew = iChunk+1;
+ off_t nReq = nNew * LSM_SHM_CHUNK_SIZE;
+ struct stat sStat;
+
+ /* If the shared-memory file has not been opened, open it now. */
+ if( p->shmfd<=0 ){
+ char *zShm = posixShmFile(p);
+ if( !zShm ) return LSM_NOMEM_BKPT;
+ p->shmfd = open(zShm, O_RDWR|O_CREAT, 0644);
+ lsmFree(p->pEnv, zShm);
+ if( p->shmfd<0 ){
+ return LSM_IOERR_BKPT;
+ }
+ }
+
+ /* If the shared-memory file is not large enough to contain the
+ ** requested chunk, cause it to grow. */
+ if( fstat(p->shmfd, &sStat) ){
+ return LSM_IOERR_BKPT;
+ }
+ if( sStat.st_size<nReq ){
+ if( ftruncate(p->shmfd, nReq) ){
+ return LSM_IOERR_BKPT;
+ }
+ }
+
+ apNew = (void **)lsmRealloc(p->pEnv, p->apShm, sizeof(void *) * nNew);
+ if( !apNew ) return LSM_NOMEM_BKPT;
+ for(i=p->nShm; i<nNew; i++){
+ apNew[i] = 0;
+ }
+ p->apShm = apNew;
+ p->nShm = nNew;
+ }
+
+ if( p->apShm[iChunk]==0 ){
+ p->apShm[iChunk] = mmap(0, LSM_SHM_CHUNK_SIZE,
+ PROT_READ|PROT_WRITE, MAP_SHARED, p->shmfd, iChunk*LSM_SHM_CHUNK_SIZE
+ );
+ if( p->apShm[iChunk]==MAP_FAILED ){
+ p->apShm[iChunk] = 0;
+ return LSM_IOERR_BKPT;
+ }
+ }
+
+ *ppShm = p->apShm[iChunk];
+ return LSM_OK;
+}
+
+static void lsmPosixOsShmBarrier(void){
+}
+
+static int lsmPosixOsShmUnmap(lsm_file *pFile, int bDelete){
+ PosixFile *p = (PosixFile *)pFile;
+ if( p->shmfd>0 ){
+ int i;
+ for(i=0; i<p->nShm; i++){
+ if( p->apShm[i] ){
+ munmap(p->apShm[i], LSM_SHM_CHUNK_SIZE);
+ p->apShm[i] = 0;
+ }
+ }
+ close(p->shmfd);
+ p->shmfd = 0;
+ if( bDelete ){
+ char *zShm = posixShmFile(p);
+ if( zShm ) unlink(zShm);
+ lsmFree(p->pEnv, zShm);
+ }
+ }
+ return LSM_OK;
+}
+
+
+static int lsmPosixOsClose(lsm_file *pFile){
+ PosixFile *p = (PosixFile *)pFile;
+ lsmPosixOsShmUnmap(pFile, 0);
+ if( p->pMap ) munmap(p->pMap, p->nMap);
+ close(p->fd);
+ lsm_free(p->pEnv, p->apShm);
+ lsm_free(p->pEnv, p);
+ return LSM_OK;
+}
+
+static int lsmPosixOsSleep(lsm_env *pEnv, int us){
+#if 0
+ /* Apparently on Android usleep() returns void */
+ if( usleep(us) ) return LSM_IOERR;
+#endif
+ usleep(us);
+ return LSM_OK;
+}
+
+/****************************************************************************
+** Memory allocation routines.
+*/
+#define BLOCK_HDR_SIZE ROUND8( sizeof(size_t) )
+
+static void *lsmPosixOsMalloc(lsm_env *pEnv, size_t N){
+ unsigned char * m;
+ N += BLOCK_HDR_SIZE;
+ m = (unsigned char *)malloc(N);
+ *((size_t*)m) = N;
+ return m + BLOCK_HDR_SIZE;
+}
+
+static void lsmPosixOsFree(lsm_env *pEnv, void *p){
+ if(p){
+ free( ((unsigned char *)p) - BLOCK_HDR_SIZE );
+ }
+}
+
+static void *lsmPosixOsRealloc(lsm_env *pEnv, void *p, size_t N){
+ unsigned char * m = (unsigned char *)p;
+ if(1>N){
+ lsmPosixOsFree( pEnv, p );
+ return NULL;
+ }else if(NULL==p){
+ return lsmPosixOsMalloc(pEnv, N);
+ }else{
+ void * re = NULL;
+ m -= BLOCK_HDR_SIZE;
+#if 0 /* arguable: don't shrink */
+ size_t * sz = (size_t*)m;
+ if(*sz >= (size_t)N){
+ return p;
+ }
+#endif
+ re = realloc( m, N + BLOCK_HDR_SIZE );
+ if(re){
+ m = (unsigned char *)re;
+ *((size_t*)m) = N;
+ return m + BLOCK_HDR_SIZE;
+ }else{
+ return NULL;
+ }
+ }
+}
+
+static size_t lsmPosixOsMSize(lsm_env *pEnv, void *p){
+ unsigned char * m = (unsigned char *)p;
+ return *((size_t*)(m-BLOCK_HDR_SIZE));
+}
+#undef BLOCK_HDR_SIZE
+
+
+#ifdef LSM_MUTEX_PTHREADS
+/*************************************************************************
+** Mutex methods for pthreads based systems. If LSM_MUTEX_PTHREADS is
+** missing then a no-op implementation of mutexes found in lsm_mutex.c
+** will be used instead.
+*/
+#include <pthread.h>
+
+typedef struct PthreadMutex PthreadMutex;
+struct PthreadMutex {
+ lsm_env *pEnv;
+ pthread_mutex_t mutex;
+#ifdef LSM_DEBUG
+ pthread_t owner;
+#endif
+};
+
+#ifdef LSM_DEBUG
+# define LSM_PTHREAD_STATIC_MUTEX { 0, PTHREAD_MUTEX_INITIALIZER, 0 }
+#else
+# define LSM_PTHREAD_STATIC_MUTEX { 0, PTHREAD_MUTEX_INITIALIZER }
+#endif
+
+static int lsmPosixOsMutexStatic(
+ lsm_env *pEnv,
+ int iMutex,
+ lsm_mutex **ppStatic
+){
+ static PthreadMutex sMutex[2] = {
+ LSM_PTHREAD_STATIC_MUTEX,
+ LSM_PTHREAD_STATIC_MUTEX
+ };
+
+ assert( iMutex==LSM_MUTEX_GLOBAL || iMutex==LSM_MUTEX_HEAP );
+ assert( LSM_MUTEX_GLOBAL==1 && LSM_MUTEX_HEAP==2 );
+
+ *ppStatic = (lsm_mutex *)&sMutex[iMutex-1];
+ return LSM_OK;
+}
+
+static int lsmPosixOsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
+ PthreadMutex *pMutex; /* Pointer to new mutex */
+ pthread_mutexattr_t attr; /* Attributes object */
+
+ pMutex = (PthreadMutex *)lsmMallocZero(pEnv, sizeof(PthreadMutex));
+ if( !pMutex ) return LSM_NOMEM_BKPT;
+
+ pMutex->pEnv = pEnv;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&pMutex->mutex, &attr);
+ pthread_mutexattr_destroy(&attr);
+
+ *ppNew = (lsm_mutex *)pMutex;
+ return LSM_OK;
+}
+
+static void lsmPosixOsMutexDel(lsm_mutex *p){
+ PthreadMutex *pMutex = (PthreadMutex *)p;
+ pthread_mutex_destroy(&pMutex->mutex);
+ lsmFree(pMutex->pEnv, pMutex);
+}
+
+static void lsmPosixOsMutexEnter(lsm_mutex *p){
+ PthreadMutex *pMutex = (PthreadMutex *)p;
+ pthread_mutex_lock(&pMutex->mutex);
+
+#ifdef LSM_DEBUG
+ assert( !pthread_equal(pMutex->owner, pthread_self()) );
+ pMutex->owner = pthread_self();
+ assert( pthread_equal(pMutex->owner, pthread_self()) );
+#endif
+}
+
+static int lsmPosixOsMutexTry(lsm_mutex *p){
+ int ret;
+ PthreadMutex *pMutex = (PthreadMutex *)p;
+ ret = pthread_mutex_trylock(&pMutex->mutex);
+#ifdef LSM_DEBUG
+ if( ret==0 ){
+ assert( !pthread_equal(pMutex->owner, pthread_self()) );
+ pMutex->owner = pthread_self();
+ assert( pthread_equal(pMutex->owner, pthread_self()) );
+ }
+#endif
+ return ret;
+}
+
+static void lsmPosixOsMutexLeave(lsm_mutex *p){
+ PthreadMutex *pMutex = (PthreadMutex *)p;
+#ifdef LSM_DEBUG
+ assert( pthread_equal(pMutex->owner, pthread_self()) );
+ pMutex->owner = 0;
+ assert( !pthread_equal(pMutex->owner, pthread_self()) );
+#endif
+ pthread_mutex_unlock(&pMutex->mutex);
+}
+
+#ifdef LSM_DEBUG
+static int lsmPosixOsMutexHeld(lsm_mutex *p){
+ PthreadMutex *pMutex = (PthreadMutex *)p;
+ return pMutex ? pthread_equal(pMutex->owner, pthread_self()) : 1;
+}
+static int lsmPosixOsMutexNotHeld(lsm_mutex *p){
+ PthreadMutex *pMutex = (PthreadMutex *)p;
+ return pMutex ? !pthread_equal(pMutex->owner, pthread_self()) : 1;
+}
+#endif
+/*
+** End of pthreads mutex implementation.
+*************************************************************************/
+#else
+/*************************************************************************
+** Noop mutex implementation
+*/
+typedef struct NoopMutex NoopMutex;
+struct NoopMutex {
+ lsm_env *pEnv; /* Environment handle (for xFree()) */
+ int bHeld; /* True if mutex is held */
+ int bStatic; /* True for a static mutex */
+};
+static NoopMutex aStaticNoopMutex[2] = {
+ {0, 0, 1},
+ {0, 0, 1},
+};
+
+static int lsmPosixOsMutexStatic(
+ lsm_env *pEnv,
+ int iMutex,
+ lsm_mutex **ppStatic
+){
+ assert( iMutex>=1 && iMutex<=(int)array_size(aStaticNoopMutex) );
+ *ppStatic = (lsm_mutex *)&aStaticNoopMutex[iMutex-1];
+ return LSM_OK;
+}
+static int lsmPosixOsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
+ NoopMutex *p;
+ p = (NoopMutex *)lsmMallocZero(pEnv, sizeof(NoopMutex));
+ if( p ) p->pEnv = pEnv;
+ *ppNew = (lsm_mutex *)p;
+ return (p ? LSM_OK : LSM_NOMEM_BKPT);
+}
+static void lsmPosixOsMutexDel(lsm_mutex *pMutex) {
+ NoopMutex *p = (NoopMutex *)pMutex;
+ assert( p->bStatic==0 && p->pEnv );
+ lsmFree(p->pEnv, p);
+}
+static void lsmPosixOsMutexEnter(lsm_mutex *pMutex){
+ NoopMutex *p = (NoopMutex *)pMutex;
+ assert( p->bHeld==0 );
+ p->bHeld = 1;
+}
+static int lsmPosixOsMutexTry(lsm_mutex *pMutex){
+ NoopMutex *p = (NoopMutex *)pMutex;
+ assert( p->bHeld==0 );
+ p->bHeld = 1;
+ return 0;
+}
+static void lsmPosixOsMutexLeave(lsm_mutex *pMutex){
+ NoopMutex *p = (NoopMutex *)pMutex;
+ assert( p->bHeld==1 );
+ p->bHeld = 0;
+}
+#ifdef LSM_DEBUG
+static int lsmPosixOsMutexHeld(lsm_mutex *pMutex){
+ NoopMutex *p = (NoopMutex *)pMutex;
+ return p ? p->bHeld : 1;
+}
+static int lsmPosixOsMutexNotHeld(lsm_mutex *pMutex){
+ NoopMutex *p = (NoopMutex *)pMutex;
+ return p ? !p->bHeld : 1;
+}
+#endif
+/***************************************************************************/
+#endif /* else LSM_MUTEX_NONE */
+
+/* Without LSM_DEBUG, the MutexHeld tests are never called */
+#ifndef LSM_DEBUG
+# define lsmPosixOsMutexHeld 0
+# define lsmPosixOsMutexNotHeld 0
+#endif
+
+lsm_env *lsm_default_env(void){
+ static lsm_env posix_env = {
+ sizeof(lsm_env), /* nByte */
+ 1, /* iVersion */
+ /***** file i/o ******************/
+ 0, /* pVfsCtx */
+ lsmPosixOsFullpath, /* xFullpath */
+ lsmPosixOsOpen, /* xOpen */
+ lsmPosixOsRead, /* xRead */
+ lsmPosixOsWrite, /* xWrite */
+ lsmPosixOsTruncate, /* xTruncate */
+ lsmPosixOsSync, /* xSync */
+ lsmPosixOsSectorSize, /* xSectorSize */
+ lsmPosixOsRemap, /* xRemap */
+ lsmPosixOsFileid, /* xFileid */
+ lsmPosixOsClose, /* xClose */
+ lsmPosixOsUnlink, /* xUnlink */
+ lsmPosixOsLock, /* xLock */
+ lsmPosixOsTestLock, /* xTestLock */
+ lsmPosixOsShmMap, /* xShmMap */
+ lsmPosixOsShmBarrier, /* xShmBarrier */
+ lsmPosixOsShmUnmap, /* xShmUnmap */
+ /***** memory allocation *********/
+ 0, /* pMemCtx */
+ lsmPosixOsMalloc, /* xMalloc */
+ lsmPosixOsRealloc, /* xRealloc */
+ lsmPosixOsFree, /* xFree */
+ lsmPosixOsMSize, /* xSize */
+ /***** mutexes *********************/
+ 0, /* pMutexCtx */
+ lsmPosixOsMutexStatic, /* xMutexStatic */
+ lsmPosixOsMutexNew, /* xMutexNew */
+ lsmPosixOsMutexDel, /* xMutexDel */
+ lsmPosixOsMutexEnter, /* xMutexEnter */
+ lsmPosixOsMutexTry, /* xMutexTry */
+ lsmPosixOsMutexLeave, /* xMutexLeave */
+ lsmPosixOsMutexHeld, /* xMutexHeld */
+ lsmPosixOsMutexNotHeld, /* xMutexNotHeld */
+ /***** other *********************/
+ lsmPosixOsSleep, /* xSleep */
+ };
+ return &posix_env;
+}
+
+#endif