#include "db_config.h"
#ifndef lint
static const char revid[] = "$Id: mut_win32.c,v 1.2 2004/03/30 01:23:45 jtownsen Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#define LOAD_ACTUAL_MUTEX_CODE
#include "db_int.h"
#undef MUTEX_DIAG
#define GET_HANDLE(mutexp, event) do { \
char idbuf[13]; \
\
snprintf(idbuf, sizeof idbuf, "db.m%08x", mutexp->id); \
event = CreateEvent(NULL, FALSE, FALSE, idbuf); \
if (event == NULL) \
return (__os_win32_errno()); \
} while (0)
int
__db_win32_mutex_init(dbenv, mutexp, flags)
DB_ENV *dbenv;
DB_MUTEX *mutexp;
u_int32_t flags;
{
u_int32_t save;
save = F_ISSET(mutexp, MUTEX_MPOOL);
memset(mutexp, 0, sizeof(*mutexp));
F_SET(mutexp, save);
if (LF_ISSET(MUTEX_THREAD) || F_ISSET(dbenv, DB_ENV_PRIVATE)) {
if (!F_ISSET(dbenv, DB_ENV_THREAD)) {
F_SET(mutexp, MUTEX_IGNORE);
return (0);
}
}
mutexp->id = ((getpid() & 0xffff) << 16) ^ P_TO_UINT32(mutexp);
F_SET(mutexp, MUTEX_INITED);
return (0);
}
int
__db_win32_mutex_lock(dbenv, mutexp)
DB_ENV *dbenv;
DB_MUTEX *mutexp;
{
HANDLE event;
u_int32_t nspins;
int ret, ms;
#ifdef MUTEX_DIAG
LARGE_INTEGER now;
#endif
if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
return (0);
event = NULL;
ms = 50;
ret = 0;
loop:
for (nspins = dbenv->tas_spins; nspins > 0; --nspins) {
if (!MUTEX_SET(&mutexp->tas)) {
#ifdef MUTEX_PAUSE
MUTEX_PAUSE
#endif
continue;
}
#ifdef DIAGNOSTIC
if (mutexp->locked)
__db_err(dbenv,
"__db_win32_mutex_lock: mutex double-locked!");
__os_id(&mutexp->locked);
#endif
if (event == NULL)
++mutexp->mutex_set_nowait;
else {
++mutexp->mutex_set_wait;
CloseHandle(event);
InterlockedDecrement(&mutexp->nwaiters);
#ifdef MUTEX_DIAG
if (ret != WAIT_OBJECT_0) {
QueryPerformanceCounter(&now);
printf("[%I64d]: Lost signal on mutex %p, "
"id %d, ms %d\n",
now.QuadPart, mutexp, mutexp->id, ms);
}
#endif
}
return (0);
}
if (event == NULL) {
#ifdef MUTEX_DIAG
QueryPerformanceCounter(&now);
printf("[%I64d]: Waiting on mutex %p, id %d\n",
now.QuadPart, mutexp, mutexp->id);
#endif
InterlockedIncrement(&mutexp->nwaiters);
GET_HANDLE(mutexp, event);
}
if ((ret = WaitForSingleObject(event, ms)) == WAIT_FAILED)
return (__os_win32_errno());
if ((ms <<= 1) > MS_PER_SEC)
ms = MS_PER_SEC;
goto loop;
}
int
__db_win32_mutex_unlock(dbenv, mutexp)
DB_ENV *dbenv;
DB_MUTEX *mutexp;
{
int ret;
HANDLE event;
#ifdef MUTEX_DIAG
LARGE_INTEGER now;
#endif
if (F_ISSET(dbenv, DB_ENV_NOLOCKING) || F_ISSET(mutexp, MUTEX_IGNORE))
return (0);
#ifdef DIAGNOSTIC
if (!mutexp->tas || !mutexp->locked)
__db_err(dbenv,
"__db_win32_mutex_unlock: ERROR: lock already unlocked");
mutexp->locked = 0;
#endif
MUTEX_UNSET(&mutexp->tas);
ret = 0;
if (mutexp->nwaiters > 0) {
GET_HANDLE(mutexp, event);
#ifdef MUTEX_DIAG
QueryPerformanceCounter(&now);
printf("[%I64d]: Signalling mutex %p, id %d\n",
now.QuadPart, mutexp, mutexp->id);
#endif
if (!PulseEvent(event))
ret = __os_win32_errno();
CloseHandle(event);
}
#ifdef DIAGNOSTIC
if (ret != 0)
__db_err(dbenv,
"__db_win32_mutex_unlock: ERROR: unlock failed");
#endif
return (ret);
}
int
__db_win32_mutex_destroy(mutexp)
DB_MUTEX *mutexp;
{
return (0);
}