#include "db_config.h"
#include "db_int.h"
#include "dbinc/mutex_int.h"
int
__mutex_alloc(env, alloc_id, flags, indxp)
ENV *env;
int alloc_id;
u_int32_t flags;
db_mutex_t *indxp;
{
int ret;
*indxp = MUTEX_INVALID;
if (alloc_id != MTX_APPLICATION &&
(F_ISSET(env->dbenv, DB_ENV_NOLOCKING) ||
(!F_ISSET(env, ENV_THREAD) &&
(LF_ISSET(DB_MUTEX_PROCESS_ONLY) ||
F_ISSET(env, ENV_PRIVATE)))))
return (0);
if (F_ISSET(env, ENV_PRIVATE))
LF_SET(DB_MUTEX_PROCESS_ONLY);
if (MUTEX_ON(env))
return (__mutex_alloc_int(env, 1, alloc_id, flags, indxp));
if (env->mutex_iq == NULL) {
env->mutex_iq_max = 50;
if ((ret = __os_calloc(env, env->mutex_iq_max,
sizeof(env->mutex_iq[0]), &env->mutex_iq)) != 0)
return (ret);
} else if (env->mutex_iq_next == env->mutex_iq_max - 1) {
env->mutex_iq_max *= 2;
if ((ret = __os_realloc(env,
env->mutex_iq_max * sizeof(env->mutex_iq[0]),
&env->mutex_iq)) != 0)
return (ret);
}
*indxp = env->mutex_iq_next + 1;
env->mutex_iq[env->mutex_iq_next].alloc_id = alloc_id;
env->mutex_iq[env->mutex_iq_next].flags = flags;
++env->mutex_iq_next;
return (0);
}
int
__mutex_alloc_int(env, locksys, alloc_id, flags, indxp)
ENV *env;
int locksys, alloc_id;
u_int32_t flags;
db_mutex_t *indxp;
{
DB_ENV *dbenv;
DB_MUTEX *mutexp;
DB_MUTEXMGR *mtxmgr;
DB_MUTEXREGION *mtxregion;
int ret;
dbenv = env->dbenv;
mtxmgr = env->mutex_handle;
mtxregion = mtxmgr->reginfo.primary;
ret = 0;
if (locksys)
MUTEX_SYSTEM_LOCK(env);
if (mtxregion->mutex_next == MUTEX_INVALID) {
__db_errx(env,
"unable to allocate memory for mutex; resize mutex region");
if (locksys)
MUTEX_SYSTEM_UNLOCK(env);
return (ENOMEM);
}
*indxp = mtxregion->mutex_next;
mutexp = MUTEXP_SET(*indxp);
DB_ASSERT(env,
((uintptr_t)mutexp & (dbenv->mutex_align - 1)) == 0);
mtxregion->mutex_next = mutexp->mutex_next_link;
--mtxregion->stat.st_mutex_free;
++mtxregion->stat.st_mutex_inuse;
if (mtxregion->stat.st_mutex_inuse > mtxregion->stat.st_mutex_inuse_max)
mtxregion->stat.st_mutex_inuse_max =
mtxregion->stat.st_mutex_inuse;
if (locksys)
MUTEX_SYSTEM_UNLOCK(env);
memset(mutexp, 0, sizeof(*mutexp));
F_SET(mutexp, DB_MUTEX_ALLOCATED |
LF_ISSET(DB_MUTEX_LOGICAL_LOCK | DB_MUTEX_PROCESS_ONLY));
if (LF_ISSET(DB_MUTEX_PROCESS_ONLY))
dbenv->thread_id(dbenv, &mutexp->pid, NULL);
#ifdef HAVE_STATISTICS
mutexp->alloc_id = alloc_id;
#else
COMPQUIET(alloc_id, 0);
#endif
if ((ret = __mutex_init(env, *indxp, flags)) != 0)
(void)__mutex_free_int(env, locksys, indxp);
return (ret);
}
int
__mutex_free(env, indxp)
ENV *env;
db_mutex_t *indxp;
{
if (!MUTEX_ON(env) || *indxp == MUTEX_INVALID)
return (0);
return (__mutex_free_int(env, 1, indxp));
}
int
__mutex_free_int(env, locksys, indxp)
ENV *env;
int locksys;
db_mutex_t *indxp;
{
DB_MUTEX *mutexp;
DB_MUTEXMGR *mtxmgr;
DB_MUTEXREGION *mtxregion;
db_mutex_t mutex;
int ret;
mutex = *indxp;
*indxp = MUTEX_INVALID;
mtxmgr = env->mutex_handle;
mtxregion = mtxmgr->reginfo.primary;
mutexp = MUTEXP_SET(mutex);
DB_ASSERT(env, F_ISSET(mutexp, DB_MUTEX_ALLOCATED));
F_CLR(mutexp, DB_MUTEX_ALLOCATED);
ret = __mutex_destroy(env, mutex);
if (locksys)
MUTEX_SYSTEM_LOCK(env);
mutexp->mutex_next_link = mtxregion->mutex_next;
mtxregion->mutex_next = mutex;
++mtxregion->stat.st_mutex_free;
--mtxregion->stat.st_mutex_inuse;
if (locksys)
MUTEX_SYSTEM_UNLOCK(env);
return (ret);
}