#ifndef _DB_MUTEX_H_
#define _DB_MUTEX_H_
#ifdef HAVE_MUTEX_SUPPORT
#define LOAD_ACTUAL_MUTEX_CODE
#include "dbinc/mutex_int.h"
#ifndef HAVE_SHARED_LATCHES
#error "Shared latches are required in DB 4.8 and above"
#endif
#endif
#if defined(__cplusplus)
extern "C" {
#endif
#define MUTEX_SPINS_PER_PROCESSOR 50
#define MUTEX_INVALID 0
#define MTX_APPLICATION 1
#define MTX_ATOMIC_EMULATION 2
#define MTX_DB_HANDLE 3
#define MTX_ENV_DBLIST 4
#define MTX_ENV_EXCLDBLIST 5
#define MTX_ENV_HANDLE 6
#define MTX_ENV_REGION 7
#define MTX_LOCK_REGION 8
#define MTX_LOGICAL_LOCK 9
#define MTX_LOG_FILENAME 10
#define MTX_LOG_FLUSH 11
#define MTX_LOG_HANDLE 12
#define MTX_LOG_REGION 13
#define MTX_MPOOLFILE_HANDLE 14
#define MTX_MPOOL_BH 15
#define MTX_MPOOL_FH 16
#define MTX_MPOOL_FILE_BUCKET 17
#define MTX_MPOOL_HANDLE 18
#define MTX_MPOOL_HASH_BUCKET 19
#define MTX_MPOOL_REGION 20
#define MTX_MUTEX_REGION 21
#define MTX_MUTEX_TEST 22
#define MTX_REP_CHKPT 23
#define MTX_REP_DATABASE 24
#define MTX_REP_DIAG 25
#define MTX_REP_EVENT 26
#define MTX_REP_REGION 27
#define MTX_REP_START 28
#define MTX_REP_WAITER 29
#define MTX_REPMGR 30
#define MTX_SEQUENCE 31
#define MTX_TWISTER 32
#define MTX_TCL_EVENTS 33
#define MTX_TXN_ACTIVE 34
#define MTX_TXN_CHKPT 35
#define MTX_TXN_COMMIT 36
#define MTX_TXN_MVCC 37
#define MTX_TXN_REGION 38
#define MTX_MAX_ENTRY 38
#undef __mutex_init
#undef __mutex_lock
#undef __mutex_timedlock
#undef __mutex_unlock
#undef __mutex_destroy
#undef __mutex_trylock
#if !defined(HAVE_MUTEX_HYBRID) && ( \
defined(HAVE_MUTEX_PTHREADS) || \
defined(HAVE_MUTEX_SOLARIS_LWP) || \
defined(HAVE_MUTEX_UI_THREADS))
#define __mutex_init(a, b, c) __db_pthread_mutex_init(a, b, c)
#define __mutex_lock(a, b) __db_pthread_mutex_lock(a, b, 0)
#define __mutex_timedlock(a, b, c) __db_pthread_mutex_lock(a, b, c)
#define __mutex_unlock(a, b) __db_pthread_mutex_unlock(a, b)
#define __mutex_destroy(a, b) __db_pthread_mutex_destroy(a, b)
#define __mutex_trylock(a, b) __db_pthread_mutex_trylock(a, b)
static inline int __db_pthread_mutex_trylock(ENV *env, db_mutex_t mutex)
{
int ret;
DB_MUTEX *mutexp;
if (!MUTEX_ON(env) || F_ISSET(env->dbenv, DB_ENV_NOLOCKING))
return (0);
mutexp = MUTEXP_SET(env, mutex);
#ifdef HAVE_SHARED_LATCHES
if (F_ISSET(mutexp, DB_MUTEX_SHARED))
ret = pthread_rwlock_trywrlock(&mutexp->u.rwlock);
else
#endif
ret = pthread_mutex_trylock(&mutexp->u.m.mutex);
if (ret == EBUSY)
ret = DB_LOCK_NOTGRANTED;
else if (ret == 0) {
F_SET(mutexp, DB_MUTEX_LOCKED);
env->dbenv->thread_id(env->dbenv, &mutexp->pid, &mutexp->tid);
STAT_INC(env,
mutex, set_nowait, mutexp->mutex_set_nowait, mutex);
}
return (ret);
}
#ifdef HAVE_SHARED_LATCHES
#define __mutex_rdlock(a, b) __db_pthread_mutex_readlock(a, b)
#define __mutex_tryrdlock(a, b) __db_pthread_mutex_tryreadlock(a, b)
static inline int __db_pthread_mutex_tryreadlock(ENV *env, db_mutex_t mutex)
{
int ret;
DB_MUTEX *mutexp;
if (!MUTEX_ON(env) || F_ISSET(env->dbenv, DB_ENV_NOLOCKING))
return (0);
mutexp = MUTEXP_SET(env, mutex);
if (F_ISSET(mutexp, DB_MUTEX_SHARED))
ret = pthread_rwlock_tryrdlock(&mutexp->u.rwlock);
else
return (EINVAL);
if (ret == EBUSY)
ret = DB_LOCK_NOTGRANTED;
#ifdef HAVE_STATISTICS
if (ret == 0)
STAT_INC(env,
mutex, set_rd_nowait, mutexp->mutex_set_nowait, mutex);
#endif
return (ret);
}
#endif
#elif defined(HAVE_MUTEX_WIN32) || defined(HAVE_MUTEX_WIN32_GCC)
#define __mutex_init(a, b, c) __db_win32_mutex_init(a, b, c)
#define __mutex_lock(a, b) __db_win32_mutex_lock(a, b, 0)
#define __mutex_timedlock(a, b, c) __db_win32_mutex_lock(a, b, c)
#define __mutex_trylock(a, b) __db_win32_mutex_trylock(a, b)
#define __mutex_unlock(a, b) __db_win32_mutex_unlock(a, b)
#define __mutex_destroy(a, b) __db_win32_mutex_destroy(a, b)
#ifdef HAVE_SHARED_LATCHES
#define __mutex_rdlock(a, b) __db_win32_mutex_readlock(a, b)
#define __mutex_tryrdlock(a, b) __db_win32_mutex_tryreadlock(a, b)
#endif
#elif defined(HAVE_MUTEX_FCNTL)
#define __mutex_init(a, b, c) __db_fcntl_mutex_init(a, b, c)
#define __mutex_lock(a, b) __db_fcntl_mutex_lock(a, b, 0)
#define __mutex_timedlock(a, b, c) __db_fcntl_lock(a, b, c)
#define __mutex_trylock(a, b) __db_fcntl_mutex_trylock(a, b)
#define __mutex_unlock(a, b) __db_fcntl_mutex_unlock(a, b)
#define __mutex_destroy(a, b) __db_fcntl_mutex_destroy(a, b)
#else
#define __mutex_init(a, b, c) __db_tas_mutex_init(a, b, c)
#define __mutex_lock(a, b) __db_tas_mutex_lock(a, b, 0)
#define __mutex_timedlock(a, b, c) __db_tas_mutex_lock(a, b, c)
#define __mutex_trylock(a, b) __db_tas_mutex_trylock(a, b)
#define __mutex_unlock(a, b) __db_tas_mutex_unlock(a, b)
#define __mutex_destroy(a, b) __db_tas_mutex_destroy(a, b)
#if defined(HAVE_SHARED_LATCHES)
#define __mutex_rdlock(a, b) __db_tas_mutex_readlock(a, b)
#define __mutex_tryrdlock(a,b) __db_tas_mutex_tryreadlock(a, b)
#endif
#endif
#ifndef __mutex_rdlock
#define __mutex_rdlock(a, b) __mutex_lock(a, b)
#endif
#ifndef __mutex_tryrdlock
#define __mutex_tryrdlock(a, b) __mutex_trylock(a, b)
#endif
#ifdef HAVE_MUTEX_SUPPORT
#define MUTEX_LOCK(env, mutex) do { \
if ((mutex) != MUTEX_INVALID && \
__mutex_lock(env, mutex) != 0) \
return (DB_RUNRECOVERY); \
} while (0)
#define MUTEX_TRYLOCK(env, mutex) \
(((mutex) == MUTEX_INVALID) ? 0 : __mutex_trylock(env, mutex))
#define MUTEX_READLOCK(env, mutex) do { \
if ((mutex) != MUTEX_INVALID && \
__mutex_rdlock(env, mutex) != 0) \
return (DB_RUNRECOVERY); \
} while (0)
#define MUTEX_TRY_READLOCK(env, mutex) \
((mutex) != MUTEX_INVALID ? __mutex_tryrdlock(env, mutex) : 0)
#define MUTEX_UNLOCK(env, mutex) do { \
if ((mutex) != MUTEX_INVALID && \
__mutex_unlock(env, mutex) != 0) \
return (DB_RUNRECOVERY); \
} while (0)
#define MUTEX_WAIT(env, mutex, duration) do { \
int __ret; \
if ((mutex) != MUTEX_INVALID && \
(__ret = __mutex_timedlock(env, mutex, duration)) != 0 && \
__ret != DB_TIMEOUT) \
return (DB_RUNRECOVERY); \
} while (0)
#else
#define MUTEX_LOCK(env, mutex) (mutex) = (mutex)
#define MUTEX_TRYLOCK(env, mutex) (mutex) = (mutex)
#define MUTEX_READLOCK(env, mutex) (mutex) = (mutex)
#define MUTEX_TRY_READLOCK(env, mutex) (mutex) = (mutex)
#define MUTEX_UNLOCK(env, mutex) (mutex) = (mutex)
#define MUTEX_REQUIRED(env, mutex) (mutex) = (mutex)
#define MUTEX_REQUIRED_READ(env, mutex) (mutex) = (mutex)
#define MUTEX_WAIT(env, mutex, duration) (mutex) = (mutex)
#endif
#ifdef HAVE_MUTEX_VXWORKS
#include "taskLib.h"
#define DB_BEGIN_SINGLE_THREAD do { \
if (DB_GLOBAL(db_global_init)) \
(void)semTake(DB_GLOBAL(db_global_lock), WAIT_FOREVER); \
else { \
taskLock(); \
if (DB_GLOBAL(db_global_init)) { \
taskUnlock(); \
(void)semTake(DB_GLOBAL(db_global_lock), \
WAIT_FOREVER); \
continue; \
} \
DB_GLOBAL(db_global_lock) = \
semBCreate(SEM_Q_FIFO, SEM_EMPTY); \
if (DB_GLOBAL(db_global_lock) != NULL) \
DB_GLOBAL(db_global_init) = 1; \
taskUnlock(); \
} \
} while (DB_GLOBAL(db_global_init) == 0)
#define DB_END_SINGLE_THREAD (void)semGive(DB_GLOBAL(db_global_lock))
#endif
#ifndef DB_BEGIN_SINGLE_THREAD
#define DB_BEGIN_SINGLE_THREAD
#endif
#ifndef DB_END_SINGLE_THREAD
#define DB_END_SINGLE_THREAD
#endif
#if defined(__cplusplus)
}
#endif
#include "dbinc_auto/mutex_ext.h"
#endif