From 19884892c015cd7371f0b2cee666484f159fbf43 Mon Sep 17 00:00:00 2001 From: jbj Date: Fri, 24 Jan 2003 17:11:36 +0000 Subject: [PATCH] Apply patches 9+10, equivalent to db-4.1.25 now. CVS patchset: 6024 CVS date: 2003/01/24 17:11:36 --- db/dbinc/mutex.h | 13 ++--- db/dbinc_auto/fileops_ext.h | 2 +- db/fileops/fop_rec.c | 23 +++++--- db/fileops/fop_util.c | 139 ++++++++++++++++++++++++++++++++------------ db/mutex/mut_win32.c | 134 +++++++++++++++++++----------------------- 5 files changed, 182 insertions(+), 129 deletions(-) diff --git a/db/dbinc/mutex.h b/db/dbinc/mutex.h index 8b5f5ad..e95036c 100644 --- a/db/dbinc/mutex.h +++ b/db/dbinc/mutex.h @@ -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 diff --git a/db/dbinc_auto/fileops_ext.h b/db/dbinc_auto/fileops_ext.h index 66d80e6..5edf7bd 100644 --- a/db/dbinc_auto/fileops_ext.h +++ b/db/dbinc_auto/fileops_ext.h @@ -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 *)); diff --git a/db/fileops/fop_rec.c b/db/fileops/fop_rec.c index 8150a81..766b741 100644 --- a/db/fileops/fop_rec.c +++ b/db/fileops/fop_rec.c @@ -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 { diff --git a/db/fileops/fop_util.c b/db/fileops/fop_util.c index 2c89f61..329ec3f 100644 --- a/db/fileops/fop_util.c +++ b/db/fileops/fop_util.c @@ -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) diff --git a/db/mutex/mut_win32.c b/db/mutex/mut_win32.c index 00eddc4..8bf183b 100644 --- a/db/mutex/mut_win32.c +++ b/db/mutex/mut_win32.c @@ -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); } -- 2.7.4