#include "db_config.h"
#include "db_int.h"
#include "dbinc/mutex_int.h"
int
__mutex_alloc(dbenv, alloc_id, flags, indxp)
DB_ENV *dbenv;
int alloc_id;
u_int32_t flags;
db_mutex_t *indxp;
{
int ret;
*indxp = MUTEX_INVALID;
if (alloc_id != MTX_APPLICATION &&
(F_ISSET(dbenv, DB_ENV_NOLOCKING) ||
(!F_ISSET(dbenv, DB_ENV_THREAD) &&
(LF_ISSET(DB_MUTEX_PROCESS_ONLY) ||
F_ISSET(dbenv, DB_ENV_PRIVATE)))))
return (0);
if (MUTEX_ON(dbenv))
return (__mutex_alloc_int(dbenv, 1, alloc_id, flags, indxp));
if (dbenv->mutex_iq == NULL) {
dbenv->mutex_iq_max = 50;
if ((ret = __os_calloc(dbenv, dbenv->mutex_iq_max,
sizeof(dbenv->mutex_iq[0]), &dbenv->mutex_iq)) != 0)
return (ret);
} else if (dbenv->mutex_iq_next == dbenv->mutex_iq_max - 1) {
dbenv->mutex_iq_max *= 2;
if ((ret = __os_realloc(dbenv,
dbenv->mutex_iq_max * sizeof(dbenv->mutex_iq[0]),
&dbenv->mutex_iq)) != 0)
return (ret);
}
*indxp = dbenv->mutex_iq_next + 1;
dbenv->mutex_iq[dbenv->mutex_iq_next].alloc_id = alloc_id;
dbenv->mutex_iq[dbenv->mutex_iq_next].flags = flags;
++dbenv->mutex_iq_next;
return (0);
}
int
__mutex_alloc_int(dbenv, locksys, alloc_id, flags, indxp)
DB_ENV *dbenv;
int locksys, alloc_id;
u_int32_t flags;
db_mutex_t *indxp;
{
DB_MUTEX *mutexp;
DB_MUTEXMGR *mtxmgr;
DB_MUTEXREGION *mtxregion;
int ret;
mtxmgr = dbenv->mutex_handle;
mtxregion = mtxmgr->reginfo.primary;
ret = 0;
if (locksys)
MUTEX_SYSTEM_LOCK(dbenv);
if (mtxregion->mutex_next == MUTEX_INVALID) {
__db_errx(dbenv,
"unable to allocate memory for mutex; resize mutex region");
if (locksys)
MUTEX_SYSTEM_UNLOCK(dbenv);
return (ENOMEM);
}
*indxp = mtxregion->mutex_next;
mutexp = MUTEXP_SET(*indxp);
DB_ASSERT(dbenv, ((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(dbenv);
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(dbenv, *indxp, flags)) != 0)
(void)__mutex_free_int(dbenv, locksys, indxp);
return (ret);
}
int
__mutex_free(dbenv, indxp)
DB_ENV *dbenv;
db_mutex_t *indxp;
{
if (!MUTEX_ON(dbenv) || *indxp == MUTEX_INVALID)
return (0);
return (__mutex_free_int(dbenv, 1, indxp));
}
int
__mutex_free_int(dbenv, locksys, indxp)
DB_ENV *dbenv;
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 = dbenv->mutex_handle;
mtxregion = mtxmgr->reginfo.primary;
mutexp = MUTEXP_SET(mutex);
DB_ASSERT(dbenv, F_ISSET(mutexp, DB_MUTEX_ALLOCATED));
F_CLR(mutexp, DB_MUTEX_ALLOCATED);
ret = __mutex_destroy(dbenv, mutex);
if (locksys)
MUTEX_SYSTEM_LOCK(dbenv);
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(dbenv);
return (ret);
}