Apply patches 9+10, equivalent to db-4.1.25 now.
authorjbj <devnull@localhost>
Fri, 24 Jan 2003 17:11:36 +0000 (17:11 +0000)
committerjbj <devnull@localhost>
Fri, 24 Jan 2003 17:11:36 +0000 (17:11 +0000)
CVS patchset: 6024
CVS date: 2003/01/24 17:11:36

db/dbinc/mutex.h
db/dbinc_auto/fileops_ext.h
db/fileops/fop_rec.c
db/fileops/fop_util.c
db/mutex/mut_win32.c

index 8b5f5ad..e95036c 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 1996-2002
  *     Sleepycat Software.  All rights reserved.
  *
- * Id: mutex.h,v 11.69 2002/08/08 03:19:45 bostic Exp 
+ * Id: mutex.h,v 11.71 2002/09/10 01:36:48 bostic Exp 
  */
 
 #ifndef _DB_MUTEX_H_
@@ -298,16 +298,13 @@ typedef unsigned int tsl_t;
 #ifdef HAVE_MUTEX_WIN32
 #define        MUTEX_FIELDS                                                    \
        LONG tas;                                                       \
-       union {                                                         \
-               HANDLE event;   /* Windows event HANDLE for wakeups */  \
-               u_int32_t id;   /* ID used for shared mutexes */        \
-       } /* anonymous */;                                              \
-       LONG nwaiters;
+       LONG nwaiters;                                                  \
+       u_int32_t id;   /* ID used for creating events */               \
 
 #if defined(LOAD_ACTUAL_MUTEX_CODE)
-#define        MUTEX_INIT(x)           0
 #define        MUTEX_SET(tsl)          (!InterlockedExchange((PLONG)tsl, 1))
 #define        MUTEX_UNSET(tsl)        (*(tsl) = 0)
+#define        MUTEX_INIT(tsl)         MUTEX_UNSET(tsl)
 #endif
 #endif
 
@@ -435,7 +432,7 @@ typedef u_int32_t tsl_t;
 })
 
 #define        MUTEX_UNSET(tsl)        (*(tsl) = -1)
-#define        MUTEX_INIT(tsl)         MUTEX_UNSET(tsl)
+#define        MUTEX_INIT(tsl)         (MUTEX_UNSET(tsl), 0)
 #endif
 #endif
 
index 66d80e6..5edf7bd 100644 (file)
@@ -42,7 +42,7 @@ int __fop_lock_handle __P((DB_ENV *, DB *, u_int32_t, db_lockmode_t, DB_LOCK *,
 int __fop_file_setup __P((DB *, DB_TXN *, const char *, int, u_int32_t, u_int32_t *));
 int __fop_subdb_setup __P((DB *, DB_TXN *, const char *, const char *, int, u_int32_t));
 int __fop_remove_setup __P((DB *, DB_TXN *, const char *, u_int32_t));
-int __fop_read_meta __P((DB_ENV *, const char *, u_int8_t *, size_t, DB_FH *, int, u_int32_t));
+int __fop_read_meta __P((DB_ENV *, const char *, u_int8_t *, size_t, DB_FH *, int, size_t *, u_int32_t));
 int __fop_dummy __P((DB *, DB_TXN *, const char *, const char *, u_int32_t));
 int __fop_dbrename __P((DB *, const char *, const char *));
 
index 8150a81..766b741 100644 (file)
@@ -8,7 +8,7 @@
 #include "db_config.h"
 
 #ifndef lint
-static const char revid[] = "Id: fop_rec.c,v 1.16 2002/07/08 19:54:51 margo Exp ";
+static const char revid[] = "Id: fop_rec.c,v 1.18 2002/08/14 20:27:01 bostic Exp ";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -156,7 +156,7 @@ __fop_rename_recover(dbenv, dbtp, lsnp, op, info)
        __fop_rename_args *argp;
        DBMETA *meta;
        char *real_new, *real_old, *src;
-       int ret, t_ret;
+       int ret;
        u_int8_t *fileid, mbuf[DBMETASIZE];
 
        real_new = NULL;
@@ -189,12 +189,10 @@ __fop_rename_recover(dbenv, dbtp, lsnp, op, info)
                 * way, shape or form, incorrect, so that we should not restore
                 * it.
                 */
-               if ((ret = __fop_read_meta(dbenv,
-                   src, mbuf, DBMETASIZE, NULL, 1, 0)) != 0) {
-                       ret = 0;
+               if (__fop_read_meta(
+                   dbenv, src, mbuf, DBMETASIZE, NULL, 1, NULL, 0) != 0)
                        goto done;
-               }
-               if ((t_ret = __db_chk_meta(dbenv, NULL, meta, 1)) != 0)
+               if (__db_chk_meta(dbenv, NULL, meta, 1) != 0)
                        goto done;
                if (memcmp(argp->fileid.data, meta->uid, DB_FILE_ID_LEN) != 0)
                        goto done;
@@ -239,6 +237,7 @@ __fop_file_remove_recover(dbenv, dbtp, lsnp, op, info)
        DBMETA *meta;
        char *real_name;
        int is_real, is_tmp, ret;
+       size_t len;
        u_int8_t mbuf[DBMETASIZE];
        u_int32_t cstat;
 
@@ -262,7 +261,15 @@ __fop_file_remove_recover(dbenv, dbtp, lsnp, op, info)
 
        /* Verify that we are manipulating the correct file.  */
        if ((ret = __fop_read_meta(dbenv,
-           real_name, mbuf, DBMETASIZE, NULL, 1, 0)) != 0) {
+           real_name, mbuf, DBMETASIZE, NULL, 1, &len, 0)) != 0) {
+               /*
+                * If len is non-zero, then the file exists and has something
+                * in it, but that something isn't a full meta-data page, so
+                * this is very bad.  Bail out!
+                */
+               if (len != 0)
+                       goto out;
+
                /* File does not exist. */
                cstat = TXN_EXPECTED;
        } else {
index 2c89f61..329ec3f 100644 (file)
@@ -8,7 +8,7 @@
 #include "db_config.h"
 
 #ifndef lint
-static const char revid[] = "Id: fop_util.c,v 1.49 2002/08/07 15:40:06 margo Exp ";
+static const char revid[] = "Id: fop_util.c,v 1.52 2002/09/10 02:41:42 bostic Exp ";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -61,8 +61,11 @@ static int __fop_set_pgsize __P((DB *, DB_FH *, const char *));
        if (F_ISSET((F), DB_FH_VALID)) {                                \
                if (LF_ISSET(DB_FCNTL_LOCKING))                         \
                        (D)->saved_open_fhp = (F);                      \
-               else if ((ret = __os_closehandle((D)->dbenv,(F))) != 0) \
+               else if ((t_ret = __os_closehandle((D)->dbenv,(F))) != 0) { \
+                       if (ret == 0)                                   \
+                               ret = t_ret;                            \
                        goto err;                                       \
+               }                                                       \
        }                                                               \
 }
 
@@ -167,13 +170,13 @@ __fop_file_setup(dbp, txn, name, mode, flags, retidp)
        DB_ENV *dbenv;
        DB_FH fh, *fhp;
        DB_LOCK elock, tmp_lock;
-       DB_LSN lsn;
        DB_TXN *stxn;
+       char *real_name, *real_tmpname, *tmpname;
        db_lockmode_t lmode;
+       int created_fhp, created_locker, ret, tmp_created, t_ret, truncating;
+       size_t len;
        u_int32_t locker, oflags;
        u_int8_t mbuf[DBMETASIZE];
-       int created_fhp, created_locker, ret, tmp_created, truncating;
-       char *real_name, *real_tmpname, *tmpname;
 
        DB_ASSERT(name != NULL);
 
@@ -190,7 +193,7 @@ __fop_file_setup(dbp, txn, name, mode, flags, retidp)
        /*
         * If we open a file handle and our caller is doing fcntl(2) locking,
         * we can't close it because that would discard the caller's lock.
-        * Save it until we close the DB handle.
+        * Save it until we close or refresh the DB handle.
         */
        if (LF_ISSET(DB_FCNTL_LOCKING)) {
                if ((ret = __os_malloc(dbenv, sizeof(*fhp), &fhp)) != 0)
@@ -234,8 +237,40 @@ retry:     if (!F_ISSET(dbp, DB_AM_COMPENSATE))
                        ret = EEXIST;
                        goto err;
                }
-reopen:                if ((ret = __fop_read_meta(dbenv, real_name,
-                   mbuf, sizeof(mbuf), fhp, 0, oflags)) != 0)
+
+               /*
+                * This is special handling for applications that
+                * are locking outside of Berkeley DB (e.g., Sendmail,
+                * Postfix).  If we are relying on external FCNTL
+                * locking and we're going to truncate the file, we
+                * cannot first open the file to verify that it is
+                * a DB file and then close/reopen to do the truncate
+                * since that will lose the external FCNTL lock.
+                * So, we special case it and leap right into the
+                * truncate code.
+                */
+               if (LF_ISSET(DB_FCNTL_LOCKING) && LF_ISSET(DB_TRUNCATE))
+                       goto do_trunc;
+
+reopen:                ret = __fop_read_meta(dbenv, real_name,
+                   mbuf, sizeof(mbuf), fhp,
+                   LF_ISSET(DB_FCNTL_LOCKING) && txn == NULL ? 1 : 0,
+                   &len, oflags);
+               /*
+                * This is special handling for applications that are doing
+                * file locking outside of Berkeley DB (e.g., Sendmail,
+                * Postfix).  So, if you're doing FCNTL_LOCKING and are non
+                * transactional, we're going to treat 0-length files as a
+                * special case and let you proceed.
+                */
+               if (ret != 0 &&
+                   LF_ISSET(DB_FCNTL_LOCKING) && txn == NULL && len == 0) {
+                       tmpname = (char *)real_name;
+                       real_name = NULL;
+                       goto creat2;
+               }
+
+               if (ret != 0)
                        goto err;
 
                if ((ret = __db_meta_setup(dbenv,
@@ -249,7 +284,14 @@ reopen:            if ((ret = __fop_read_meta(dbenv, real_name,
                        if ((ret = REL_ENVLOCK(dbenv, &elock)) != 0)
                                goto err;
                } else {
-                       /* Someone else has file locked; need to wait. */
+                       /*
+                        * If someone is doing FCNTL locking outside of us,
+                        * then we should never have a lock conflict and
+                        * should never get to here.  We need to assert that
+                        * because we are about to close the fd which will
+                        * release the FCNTL locks.
+                        */
+                       DB_ASSERT(!LF_ISSET(DB_FCNTL_LOCKING));
                        if ((ret = __os_closehandle(dbenv, fhp)) != 0)
                                goto err;
                        ret = __fop_lock_handle(dbenv,
@@ -281,7 +323,7 @@ reopen:             if ((ret = __fop_read_meta(dbenv, real_name,
                         */
                        if ((ret = __os_closehandle(dbenv, fhp)) != 0)
                                goto err;
-                       if ((ret = __os_open(dbenv,
+do_trunc:              if ((ret = __os_open(dbenv,
                            real_name, DB_OSO_TRUNC, 0, fhp)) != 0)
                                goto err;
                        /*
@@ -324,11 +366,7 @@ reopen:            if ((ret = __fop_read_meta(dbenv, real_name,
        if ((ret = REL_ENVLOCK(dbenv, &elock)) != 0)
                goto err;
 
-create:        if (txn == NULL)
-               ZERO_LSN(lsn);
-       else
-               lsn = txn->last_lsn;
-       if ((ret = __db_backup_name(dbenv, name, txn, &tmpname, &lsn)) != 0)
+create:        if ((ret = __db_backup_name(dbenv, name, txn, &tmpname)) != 0)
                goto err;
        if (TXN_ON(dbenv) && txn != NULL &&
            (ret = dbenv->txn_begin(dbenv, txn, &stxn, 0)) != 0)
@@ -413,7 +451,7 @@ err:                if (stxn != NULL)
                        (void)__fop_remove(dbenv,
                            NULL, NULL, tmpname, DB_APP_DATA);
                if (F_ISSET(fhp, DB_FH_VALID))
-                       (void)__os_closehandle(dbenv, fhp);
+                       CLOSE_HANDLE(dbp, fhp);
                if (LOCK_ISSET(tmp_lock))
                        __lock_put(dbenv, &tmp_lock);
                if (LOCK_ISSET(dbp->handle_lock) && txn == NULL)
@@ -424,11 +462,16 @@ err:              if (stxn != NULL)
                        (void)__lock_id_free(dbenv, dbp->lid);
                        dbp->lid = DB_LOCK_INVALIDID;
                }
-               if (created_fhp)
+               if (created_fhp && !F_ISSET(fhp, DB_FH_VALID))
                        __os_free(dbenv, fhp);
        }
 
-done:  if (!truncating && tmpname != NULL)
+done:  /*
+        * There are cases where real_name and tmpname take on the
+        * exact same string, so we need to make sure that we do not
+        * free twice.
+        */
+       if (!truncating && tmpname != NULL && tmpname != real_name)
                __os_free(dbenv, tmpname);
        if (real_name != NULL)
                __os_free(dbenv, real_name);
@@ -509,7 +552,7 @@ __fop_subdb_setup(dbp, txn, mname, name, mode, flags)
 {
        DB *mdbp;
        DB_ENV *dbenv;
-       int remove, ret;
+       int do_remove, ret;
 
        mdbp = NULL;
        dbenv = dbp->dbenv;
@@ -581,7 +624,7 @@ __fop_subdb_setup(dbp, txn, mname, name, mode, flags)
 
        /*
         * The master's handle lock is under the control of the
-        * subdb (it acquired the master's locker.  We want to
+        * subdb (it acquired the master's locker).  We want to
         * keep the master's handle lock so that no one can remove
         * the file while the subdb is open.  If we register the
         * trade event and then invalidate the copy of the lock
@@ -610,11 +653,11 @@ DB_TEST_RECOVERY_LABEL
 
        /* If we created the master file then we need to remove it.  */
        if (mdbp != NULL) {
-               remove = F_ISSET(mdbp, DB_AM_CREATED) ? 1 : 0;
-               if (remove)
+               do_remove = F_ISSET(mdbp, DB_AM_CREATED) ? 1 : 0;
+               if (do_remove)
                        F_SET(mdbp, DB_AM_DISCARD);
                (void)__db_close_i(mdbp, txn, 0);
-               if (remove) {
+               if (do_remove) {
                        (void)db_create(&mdbp, dbp->dbenv, 0);
                        (void)__db_remove_i(mdbp, txn, mname, NULL);
                }
@@ -637,6 +680,7 @@ __fop_remove_setup(dbp, txn, name, flags)
        u_int32_t flags;
 {
        DB_ENV *dbenv;
+       DB_FH *fhp;
        DB_LOCK elock;
        u_int8_t mbuf[DBMETASIZE];
        int ret;
@@ -657,13 +701,27 @@ __fop_remove_setup(dbp, txn, name, flags)
        }
 
        /*
+        * We are about to open a file handle and then possibly close it.
+        * We cannot close handles if we are doing FCNTL locking.  However,
+        * there is no way to pass the FCNTL flag into this routine via the
+        * user API.  The only way we can get in here and be doing FCNTL
+        * locking is if we are trying to clean up an open that was called
+        * with FCNTL locking.  In that case, the save_fhp should already be
+        * set.  So, we use that field to tell us if we need to make sure
+        * that we shouldn't close the handle.
+        */
+       fhp = dbp->saved_open_fhp;
+       DB_ASSERT(LF_ISSET(DB_FCNTL_LOCKING) ||
+           fhp == NULL || !F_ISSET(fhp, DB_FH_VALID));
+
+       /*
         * Lock environment to protect file open.  That will enable us to
         * read the meta-data page and get the fileid so that we can lock
         * the handle.
         */
        GET_ENVLOCK(dbenv, dbp->lid, &elock);
        if ((ret = __fop_read_meta(dbenv,
-           name, mbuf, sizeof(mbuf), NULL, 0, 0)) != 0)
+           name, mbuf, sizeof(mbuf), fhp, 0, NULL, 0)) != 0)
                goto err;
 
        if ((ret =
@@ -686,26 +744,30 @@ err:      (void)REL_ENVLOCK(dbenv, &elock);
  *     Read the meta-data page from a file and return it in buf.  The
  * open file handle is returned in fhp.
  *
- * PUBLIC: int __fop_read_meta __P((DB_ENV *,
- * PUBLIC:     const char *, u_int8_t *, size_t, DB_FH *, int, u_int32_t));
+ * PUBLIC: int __fop_read_meta __P((DB_ENV *, const char *,
+ * PUBLIC:     u_int8_t *, size_t, DB_FH *, int, size_t *, u_int32_t));
  */
 int
-__fop_read_meta(dbenv, name, buf, size, fhp, errok, flags)
+__fop_read_meta(dbenv, name, buf, size, fhp, errok, nbytesp, flags)
        DB_ENV *dbenv;
        const char *name;
        u_int8_t *buf;
        size_t size;
        DB_FH *fhp;
        int errok;
+       size_t *nbytesp;
        u_int32_t flags;
 {
        DB_FH fh, *lfhp;
        size_t nr;
-       int ret;
+       int myfhp, ret;
 
+       nr = 0;
+       myfhp = 0;
+       memset(&fh, 0, sizeof(fh));
        lfhp = fhp == NULL ? &fh : fhp;
-       memset(lfhp, 0, sizeof(*fhp));
-       if ((ret = __os_open(dbenv, name, flags, 0, lfhp)) != 0)
+       myfhp = F_ISSET(lfhp, DB_FH_VALID);
+       if (!myfhp && (ret = __os_open(dbenv, name, flags, 0, lfhp)) != 0)
                goto err;
        if ((ret = __os_read(dbenv, lfhp, buf, size, &nr)) != 0) {
                if (!errok)
@@ -722,13 +784,15 @@ __fop_read_meta(dbenv, name, buf, size, fhp, errok, flags)
        }
 
 err:   /*
-        * On error, we always close the handle.  If there is no error,
-        * then we only return the handle if the user didn't pass us
-        * a handle into which to return it.  If fhp is valid, then
-        * lfhp is the same as fhp.
+        * On error, we would like to close the handle.  However, if the
+        * handle was opened in the caller, we cannot.  If there is no error,
+        * then we only close the handle if we opened it here.
         */
-       if (F_ISSET(lfhp, DB_FH_VALID) && (ret != 0 || fhp == NULL))
+       if (!myfhp && F_ISSET((lfhp), DB_FH_VALID) && (ret != 0 || fhp == NULL))
                __os_closehandle(dbenv, lfhp);
+
+       if (nbytesp != NULL)
+               *nbytesp = nr;
        return (ret);
 }
 
@@ -778,8 +842,7 @@ __fop_dummy(dbp, txn, old, new, flags)
                goto err;
 
        /* We need to create a dummy file as a place holder. */
-       if ((ret =
-           __db_backup_name(dbenv, new, txn, &back, &txn->last_lsn)) != 0)
+       if ((ret = __db_backup_name(dbenv, new, stxn, &back)) != 0)
                goto err;
        if ((ret = __db_appname(dbenv,
            DB_APP_DATA, back, flags, NULL, &realback)) != 0)
@@ -847,7 +910,7 @@ __fop_dummy(dbp, txn, old, new, flags)
                tmpdbt.data = tmpdbp->fileid;
                tmpdbt.size = DB_FILE_ID_LEN;
                namedbt.data = (void *)old;
-               namedbt.size = strlen(old) + 1;
+               namedbt.size = (u_int32_t)strlen(old) + 1;
                if ((t_ret =
                    __fop_file_remove_log(dbenv, txn, &lsn, 0, &fiddbt,
                    &tmpdbt, &namedbt, DB_APP_DATA, stxnid)) != 0 && ret == 0)
index 00eddc4..8bf183b 100644 (file)
@@ -8,7 +8,7 @@
 #include "db_config.h"
 
 #ifndef lint
-static const char revid[] = "Id: mut_win32.c,v 1.6 2002/07/12 04:05:00 mjc Exp ";
+static const char revid[] = "Id: mut_win32.c,v 1.8 2002/09/10 02:37:25 bostic Exp ";
 #endif /* not lint */
 
 #ifndef NO_SYSTEM_INCLUDES
@@ -24,29 +24,18 @@ static const char revid[] = "Id: mut_win32.c,v 1.6 2002/07/12 04:05:00 mjc Exp "
 #define        LOAD_ACTUAL_MUTEX_CODE
 #include "db_int.h"
 
+/* We don't want to run this code even in "ordinary" diagnostic mode. */
+#undef MUTEX_DIAG
+
 #define        GET_HANDLE(mutexp, event) do {                                  \
-       int i;                                                          \
        char idbuf[13];                                                 \
                                                                        \
-       if (F_ISSET(mutexp, MUTEX_THREAD)) {                            \
-               event = mutexp->event;                                  \
-               return (0);                                             \
-       }                                                               \
-                                                                       \
-       for (i = 0; i < 8; i++)                                         \
-               idbuf[(sizeof(idbuf) - 1) - i] =                        \
-                   "0123456789abcdef"[(mutexp->id >> (i * 4)) & 0xf];  \
-       event = CreateEvent(NULL, TRUE, FALSE, idbuf);                  \
+       snprintf(idbuf, sizeof idbuf, "db.m%08x", mutexp->id);          \
+       event = CreateEvent(NULL, FALSE, FALSE, idbuf);                 \
        if (event == NULL)                                              \
                return (__os_win32_errno());                            \
 } while (0)
 
-#define        RELEASE_HANDLE(mutexp, event)                                   \
-       if (!F_ISSET(mutexp, MUTEX_THREAD) && event != NULL) {          \
-               CloseHandle(event);                                     \
-               event = NULL;                                           \
-       }
-
 /*
  * __db_win32_mutex_init --
  *     Initialize a DB_MUTEX.
@@ -74,24 +63,17 @@ __db_win32_mutex_init(dbenv, mutexp, flags)
 
        /*
         * If this is a thread lock or the process has told us that there are
-        * no other processes in the environment, use thread-only locks, they
-        * are faster in some cases.
-        *
-        * This is where we decide to ignore locks we don't need to set -- if
-        * the application isn't threaded, there aren't any threads to block.
+        * no other processes in the environment, and the application isn't
+        * threaded, there aren't any threads to block.
         */
        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);
                }
-               F_SET(mutexp, MUTEX_THREAD);
-               mutexp->event = CreateEvent(NULL, TRUE, FALSE, NULL);
-               if (mutexp->event == NULL)
-                       return (__os_win32_errno());
-       } else
-               mutexp->id = ((getpid() & 0xffff) << 16) ^ (u_int32_t)mutexp;
+       }
 
+       mutexp->id = ((getpid() & 0xffff) << 16) ^ P_TO_UINT32(mutexp);
        mutexp->spins = __os_spin(dbenv);
        F_SET(mutexp, MUTEX_INITED);
 
@@ -110,56 +92,67 @@ __db_win32_mutex_lock(dbenv, mutexp)
        DB_MUTEX *mutexp;
 {
        HANDLE event;
-       u_long ms;
-       int nspins;
+       int ret, ms, nspins;
+#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:  /* Attempt to acquire the resource for N spins. */
        for (nspins = mutexp->spins; nspins > 0; --nspins) {
                if (!MUTEX_SET(&mutexp->tas))
                        continue;
 
-               if (mutexp->locked) {
-                       /*
-                        * If we are about to block for the first time,
-                        * increment the waiter count while we still hold
-                        * the mutex.
-                        */
-                       if (nspins == 1 && event == NULL)
-                               ++mutexp->nwaiters;
-                       MUTEX_UNSET(&mutexp->tas);
-                       continue;
-               }
+#ifdef DIAGNOSTIC
+               if (mutexp->locked)
+                       __db_err(dbenv,
+                           "__db_win32_mutex_lock: mutex double-locked!");
 
-               mutexp->locked = 1;
+               __os_id(&mutexp->locked);
+#endif
 
                if (event == NULL)
                        ++mutexp->mutex_set_nowait;
                else {
                        ++mutexp->mutex_set_wait;
-                       --mutexp->nwaiters;
+                       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
                }
-               MUTEX_UNSET(&mutexp->tas);
-               RELEASE_HANDLE(mutexp, event);
 
                return (0);
        }
 
        /*
-        * Yield the processor; wait 50 ms initially, up to 1 second.
-        * This loop is needed to work around an unlikely race where the signal
-        * from the unlocking thread gets lost.
+        * Yield the processor; wait 50 ms initially, up to 1 second.  This
+        * loop is needed to work around a race where the signal from the
+        * unlocking thread gets lost.  We start at 50 ms because it's unlikely
+        * to happen often and we want to avoid wasting CPU.
         */
-       if (event == NULL)
+       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 (WaitForSingleObject(event, ms) == WAIT_FAILED)
+       }
+       if ((ret = WaitForSingleObject(event, ms)) == WAIT_FAILED)
                return (__os_win32_errno());
-
        if ((ms <<= 1) > MS_PER_SEC)
                ms = MS_PER_SEC;
 
@@ -179,35 +172,40 @@ __db_win32_mutex_unlock(dbenv, 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->locked)
+       if (!mutexp->tas || !mutexp->locked)
                __db_err(dbenv,
                    "__db_win32_mutex_unlock: ERROR: lock already unlocked");
-#endif
-
-       ret = 0;
 
-       /* We have to drop the mutex inside a critical section */
-       while (!MUTEX_SET(&mutexp->tas))
-               ;
        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();
 
-               RELEASE_HANDLE(mutexp, event);
+               CloseHandle(event);
        }
 
 #ifdef DIAGNOSTIC
-       if (ret)
+       if (ret != 0)
                __db_err(dbenv,
                    "__db_win32_mutex_unlock: ERROR: unlock failed");
 #endif
@@ -217,7 +215,7 @@ __db_win32_mutex_unlock(dbenv, mutexp)
 
 /*
  * __db_win32_mutex_destroy --
- *     Destroy a DB_MUTEX.
+ *     Destroy a DB_MUTEX - noop with this implementation.
  *
  * PUBLIC: int __db_win32_mutex_destroy __P((DB_MUTEX *));
  */
@@ -225,17 +223,5 @@ int
 __db_win32_mutex_destroy(mutexp)
        DB_MUTEX *mutexp;
 {
-       int ret;
-
-       if (F_ISSET(mutexp, MUTEX_IGNORE) || !F_ISSET(mutexp, MUTEX_THREAD))
-               return (0);
-
-       ret = 0;
-       if (mutexp->event != NULL) {
-               if (!CloseHandle(mutexp->event))
-                       ret = __os_win32_errno();
-               mutexp->event = NULL;
-       }
-
-       return (ret);
+       return (0);
 }