#include "db_config.h"
#include "db_int.h"
int
__mutex_alloc_pp(dbenv, flags, indxp)
DB_ENV *dbenv;
u_int32_t flags;
db_mutex_t *indxp;
{
DB_THREAD_INFO *ip;
ENV *env;
int ret;
env = dbenv->env;
if ((ret = __db_fchk(env, "DB_ENV->mutex_alloc",
flags, DB_MUTEX_PROCESS_ONLY | DB_MUTEX_SELF_BLOCK)) != 0)
return (ret);
ENV_ENTER(env, ip);
ret = __mutex_alloc(env, MTX_APPLICATION, flags, indxp);
ENV_LEAVE(env, ip);
return (ret);
}
int
__mutex_free_pp(dbenv, indx)
DB_ENV *dbenv;
db_mutex_t indx;
{
DB_THREAD_INFO *ip;
ENV *env;
int ret;
env = dbenv->env;
if (indx == MUTEX_INVALID)
return (EINVAL);
ENV_ENTER(env, ip);
ret = __mutex_free(env, &indx);
ENV_LEAVE(env, ip);
return (ret);
}
int
__mutex_lock_pp(dbenv, indx)
DB_ENV *dbenv;
db_mutex_t indx;
{
DB_THREAD_INFO *ip;
ENV *env;
int ret;
env = dbenv->env;
if (indx == MUTEX_INVALID)
return (EINVAL);
ENV_ENTER(env, ip);
ret = __mutex_lock(env, indx);
ENV_LEAVE(env, ip);
return (ret);
}
int
__mutex_unlock_pp(dbenv, indx)
DB_ENV *dbenv;
db_mutex_t indx;
{
DB_THREAD_INFO *ip;
ENV *env;
int ret;
env = dbenv->env;
if (indx == MUTEX_INVALID)
return (EINVAL);
ENV_ENTER(env, ip);
ret = __mutex_unlock(env, indx);
ENV_LEAVE(env, ip);
return (ret);
}
int
__mutex_get_align(dbenv, alignp)
DB_ENV *dbenv;
u_int32_t *alignp;
{
ENV *env;
env = dbenv->env;
if (MUTEX_ON(env)) {
*alignp = ((DB_MUTEXREGION *)
env->mutex_handle->reginfo.primary)->stat.st_mutex_align;
} else
*alignp = dbenv->mutex_align;
return (0);
}
int
__mutex_set_align(dbenv, align)
DB_ENV *dbenv;
u_int32_t align;
{
ENV *env;
env = dbenv->env;
ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mutex_align");
if (align == 0 || !POWER_OF_TWO(align)) {
__db_errx(env, DB_STR("2018",
"DB_ENV->mutex_set_align: alignment value must be a non-zero power-of-two"));
return (EINVAL);
}
dbenv->mutex_align = align;
return (0);
}
int
__mutex_get_increment(dbenv, incrementp)
DB_ENV *dbenv;
u_int32_t *incrementp;
{
*incrementp = dbenv->mutex_inc;
return (0);
}
int
__mutex_set_increment(dbenv, increment)
DB_ENV *dbenv;
u_int32_t increment;
{
ENV *env;
env = dbenv->env;
ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mutex_increment");
dbenv->mutex_cnt = 0;
dbenv->mutex_inc = increment;
return (0);
}
int
__mutex_get_init(dbenv, initp)
DB_ENV *dbenv;
u_int32_t *initp;
{
ENV *env;
env = dbenv->env;
if (MUTEX_ON(env)) {
*initp = ((DB_MUTEXREGION *)
env->mutex_handle->reginfo.primary)->stat.st_mutex_init;
} else
*initp = dbenv->mutex_cnt;
return (0);
}
int
__mutex_set_init(dbenv, init)
DB_ENV *dbenv;
u_int32_t init;
{
ENV *env;
env = dbenv->env;
ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mutex_init");
dbenv->mutex_cnt = init;
dbenv->mutex_inc = 0;
return (0);
}
int
__mutex_get_max(dbenv, maxp)
DB_ENV *dbenv;
u_int32_t *maxp;
{
ENV *env;
env = dbenv->env;
if (MUTEX_ON(env)) {
*maxp = ((DB_MUTEXREGION *)
env->mutex_handle->reginfo.primary)->stat.st_mutex_max;
} else
*maxp = dbenv->mutex_max;
return (0);
}
int
__mutex_set_max(dbenv, max)
DB_ENV *dbenv;
u_int32_t max;
{
ENV *env;
env = dbenv->env;
ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mutex_max");
dbenv->mutex_max = max;
dbenv->mutex_inc = 0;
return (0);
}
int
__mutex_get_tas_spins(dbenv, tas_spinsp)
DB_ENV *dbenv;
u_int32_t *tas_spinsp;
{
ENV *env;
env = dbenv->env;
if (MUTEX_ON(env)) {
*tas_spinsp = ((DB_MUTEXREGION *)env->
mutex_handle->reginfo.primary)->stat.st_mutex_tas_spins;
} else
*tas_spinsp = dbenv->mutex_tas_spins;
return (0);
}
int
__mutex_set_tas_spins(dbenv, tas_spins)
DB_ENV *dbenv;
u_int32_t tas_spins;
{
ENV *env;
env = dbenv->env;
if (tas_spins == 0)
tas_spins = 1;
else if (tas_spins > 1000000)
tas_spins = 1000000;
if (MUTEX_ON(env))
((DB_MUTEXREGION *)env->mutex_handle
->reginfo.primary)->stat.st_mutex_tas_spins = tas_spins;
else
dbenv->mutex_tas_spins = tas_spins;
return (0);
}
#if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT)
static inline db_mutex_t atomic_get_mutex(env, v)
ENV *env;
db_atomic_t *v;
{
u_int index;
DB_MUTEXREGION *mtxreg;
if (!MUTEX_ON(env))
return (MUTEX_INVALID);
index = (u_int)(((uintptr_t) (v)) >> 6) % MAX_ATOMIC_MUTEXES;
mtxreg = (DB_MUTEXREGION *)env->mutex_handle->reginfo.primary;
return (mtxreg->mtx_atomic[index]);
}
atomic_value_t
__atomic_inc(env, v)
ENV *env;
db_atomic_t *v;
{
db_mutex_t mtx;
int ret;
mtx = atomic_get_mutex(env, v);
MUTEX_LOCK(env, mtx);
ret = ++v->value;
MUTEX_UNLOCK(env, mtx);
return (ret);
}
atomic_value_t
__atomic_dec(env, v)
ENV *env;
db_atomic_t *v;
{
db_mutex_t mtx;
int ret;
mtx = atomic_get_mutex(env, v);
MUTEX_LOCK(env, mtx);
ret = --v->value;
MUTEX_UNLOCK(env, mtx);
return (ret);
}
int
atomic_compare_exchange(env, v, oldval, newval)
ENV *env;
db_atomic_t *v;
atomic_value_t oldval;
atomic_value_t newval;
{
db_mutex_t mtx;
int ret;
if (atomic_read(v) != oldval)
return (0);
mtx = atomic_get_mutex(env, v);
MUTEX_LOCK(env, mtx);
ret = atomic_read(v) == oldval;
if (ret)
atomic_init(v, newval);
MUTEX_UNLOCK(env, mtx);
return (ret);
}
#endif