summaryrefslogtreecommitdiff
path: root/src/mutex/mut_stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mutex/mut_stat.c')
-rw-r--r--src/mutex/mut_stat.c119
1 files changed, 88 insertions, 31 deletions
diff --git a/src/mutex/mut_stat.c b/src/mutex/mut_stat.c
index b64207fa..af622c7d 100644
--- a/src/mutex/mut_stat.c
+++ b/src/mutex/mut_stat.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved.
*
* $Id$
*/
@@ -19,6 +19,17 @@ static int __mutex_print_stats __P((ENV *, u_int32_t));
static void __mutex_print_summary __P((ENV *));
static int __mutex_stat __P((ENV *, DB_MUTEX_STAT **, u_int32_t));
+static const FN MutexFlagNames[] = {
+ { DB_MUTEX_ALLOCATED, "alloc" },
+ { DB_MUTEX_LOCKED, "locked" },
+ { DB_MUTEX_LOGICAL_LOCK, "logical" },
+ { DB_MUTEX_OWNER_DEAD, "ower-dead" },
+ { DB_MUTEX_PROCESS_ONLY, "process-private" },
+ { DB_MUTEX_SELF_BLOCK, "self-block" },
+ { DB_MUTEX_SHARED, "shared" },
+ { 0, NULL }
+};
+
/*
* __mutex_stat_pp --
* ENV->mutex_stat pre/post processing.
@@ -170,11 +181,12 @@ __mutex_print_summary(env)
size = 0;
if (F_ISSET(env, ENV_PRIVATE)) {
- mutexp = (DB_MUTEX *)mtxmgr->mutex_array + 1;
+ mutexp = (DB_MUTEX *)((uintptr_t)mtxmgr->mutex_array +
+ mtxregion->mutex_size);
chunk = NULL;
size = __env_elem_size(env,
ROFF_TO_P(mtxregion->mutex_off_alloc));
- size -= sizeof(*mutexp);
+ size -= mtxregion->mutex_size;
} else
mutexp = MUTEXP_SET(env, 1);
for (i = 1; i <= mtxregion->stat.st_mutex_cnt; ++i) {
@@ -185,13 +197,15 @@ __mutex_print_summary(env)
else
counts[mutexp->alloc_id]++;
- mutexp++;
+ mutexp = (DB_MUTEX *)((uintptr_t)mutexp +
+ mtxregion->mutex_size);
if (F_ISSET(env, ENV_PRIVATE) &&
(size -= sizeof(*mutexp)) < sizeof(*mutexp)) {
mutexp =
__env_get_chunk(&mtxmgr->reginfo, &chunk, &size);
+ mutexp = ALIGNP_INC(mutexp,
+ mtxregion->stat.st_mutex_align);
}
- mutexp = ALIGNP_INC(mutexp, mtxregion->stat.st_mutex_align);
}
__db_msg(env, "Mutex counts");
__db_msg(env, "%d\tUnallocated", counts[0]);
@@ -252,14 +266,6 @@ __mutex_print_all(env, flags)
ENV *env;
u_int32_t flags;
{
- static const FN fn[] = {
- { DB_MUTEX_ALLOCATED, "alloc" },
- { DB_MUTEX_LOCKED, "locked" },
- { DB_MUTEX_LOGICAL_LOCK, "logical" },
- { DB_MUTEX_PROCESS_ONLY, "process-private" },
- { DB_MUTEX_SELF_BLOCK, "self-block" },
- { 0, NULL }
- };
DB_MSGBUF mb, *mbp;
DB_MUTEX *mutexp;
DB_MUTEXMGR *mtxmgr;
@@ -294,37 +300,32 @@ __mutex_print_all(env, flags)
__db_msg(env, "mutex\twait/nowait, pct wait, holder, flags");
size = 0;
if (F_ISSET(env, ENV_PRIVATE)) {
- mutexp = (DB_MUTEX *)mtxmgr->mutex_array + 1;
+ mutexp = (DB_MUTEX *)((uintptr_t)mtxmgr->mutex_array +
+ mtxregion->mutex_size);
chunk = NULL;
size = __env_elem_size(env,
ROFF_TO_P(mtxregion->mutex_off_alloc));
- size -= sizeof(*mutexp);
+ size -= mtxregion->mutex_size;
} else
mutexp = MUTEXP_SET(env, 1);
for (i = 1; i <= mtxregion->stat.st_mutex_cnt; ++i) {
if (F_ISSET(mutexp, DB_MUTEX_ALLOCATED)) {
__db_msgadd(env, mbp, "%5lu\t", (u_long)i);
-
__mutex_print_debug_stats(env, mbp,
F_ISSET(env, ENV_PRIVATE) ?
(db_mutex_t)mutexp : i, flags);
-
- if (mutexp->alloc_id != 0)
- __db_msgadd(env, mbp,
- ", %s", __mutex_print_id(mutexp->alloc_id));
-
- __db_prflags(env, mbp, mutexp->flags, fn, " (", ")");
-
DB_MSGBUF_FLUSH(env, mbp);
}
- mutexp++;
+ mutexp = (DB_MUTEX *)((uintptr_t)mutexp +
+ mtxregion->mutex_size);
if (F_ISSET(env, ENV_PRIVATE) &&
- (size -= sizeof(*mutexp)) < sizeof(*mutexp)) {
+ (size -= mtxregion->mutex_size) < mtxregion->mutex_size) {
mutexp =
__env_get_chunk(&mtxmgr->reginfo, &chunk, &size);
+ mutexp = ALIGNP_INC(mutexp,
+ mtxregion->stat.st_mutex_align);
}
- mutexp = ALIGNP_INC(mutexp, mtxregion->stat.st_mutex_align);
}
return (0);
@@ -332,8 +333,7 @@ __mutex_print_all(env, flags)
/*
* __mutex_print_debug_single --
- * Print mutex internal debugging statistics for a single mutex on a
- * single output line.
+ * Print mutex internal debugging statistics for a single mutex.
*
* PUBLIC: void __mutex_print_debug_single
* PUBLIC: __P((ENV *, const char *, db_mutex_t, u_int32_t));
@@ -359,8 +359,9 @@ __mutex_print_debug_single(env, tag, mutex, flags)
/*
* __mutex_print_debug_stats --
- * Print mutex internal debugging statistics, that is, the statistics
- * in the [] square brackets.
+ * Print the mutex internal debugging statistics in square bracket,s on a
+ * followed by the allocation id and flags, on single line. When MUTEX_DIAG
+ * is on and the mutex is held, append the owner's stack trace.
*
* PUBLIC: void __mutex_print_debug_stats
* PUBLIC: __P((ENV *, DB_MSGBUF *, db_mutex_t, u_int32_t));
@@ -380,6 +381,9 @@ __mutex_print_debug_stats(env, mbp, mutex, flags)
!defined(HAVE_MUTEX_PTHREADS))
int sharecount;
#endif
+#ifdef MUTEX_DIAG
+ char timestr[CTIME_BUFLEN];
+#endif
if (mutex == MUTEX_INVALID) {
__db_msgadd(env, mbp, "[!Set]");
@@ -448,6 +452,22 @@ __mutex_print_debug_stats(env, mbp, mutex, flags)
mutexp->hybrid_wait, mutexp->hybrid_wakeup);
#endif
+ if (mutexp->alloc_id != 0)
+ __db_msgadd(env,
+ mbp, ", %s", __mutex_print_id(mutexp->alloc_id));
+
+ __db_prflags(env, mbp, mutexp->flags, MutexFlagNames, " (", ")");
+#ifdef MUTEX_DIAG
+ if (mutexp->alloc_id != MTX_LOGICAL_LOCK &&
+ timespecisset(&mutexp->mutex_history.when)) {
+ __db_ctimespec(&mutexp->mutex_history.when, timestr);
+ __db_msgadd(env, mbp, "\nLocked %s", timestr);
+ if (mutexp->mutex_history.stacktext[0] != '\0')
+ __db_msgadd(env, mbp, "\n%.*s",
+ (int)sizeof(mutexp->mutex_history.stacktext) - 1,
+ mutexp->mutex_history.stacktext);
+ }
+#endif
if (LF_ISSET(DB_STAT_CLEAR))
__mutex_clear(env, mutex);
}
@@ -495,7 +515,8 @@ __mutex_print_id(alloc_id)
case MTX_TXN_COMMIT: return ("txn commit");
case MTX_TXN_MVCC: return ("txn mvcc");
case MTX_TXN_REGION: return ("txn region");
- default: return ("unknown mutex type");
+ case 0: return ("invalid 0 mutex type");
+ default: return ("unknown non-zero mutex type");
/* NOTREACHED */
}
}
@@ -577,3 +598,39 @@ __mutex_stat_print_pp(dbenv, flags)
return (__db_stat_not_built(dbenv->env));
}
#endif
+
+/*
+ * __mutex_describe
+ * Fill in a buffer with the mutex #, alloc_id, and any other
+ * characteristics which are likely to be useful for diagnostics. The
+ * destination buffer must hold at least DB_MUTEX_DESCRIBE_STRLEN bytes.
+ *
+ * PUBLIC: char *__mutex_describe __P((ENV *, db_mutex_t, char *));
+ */
+char *
+__mutex_describe(env, mutex, dest)
+ ENV *env;
+ db_mutex_t mutex;
+ char *dest;
+{
+ DB_MUTEX *mutexp;
+ DB_MSGBUF mb, *mbp;
+ const char *type;
+
+ DB_MSGBUF_INIT(&mb);
+ mbp = &mb;
+ mutexp = MUTEXP_SET(env, mutex);
+ type = F_ISSET(mutexp, DB_MUTEX_SHARED) ? "latch" : "mutex";
+#ifdef HAVE_STATISTICS
+ __db_msgadd(env, mbp, "%s %s id %ld ",
+ __mutex_print_id(mutexp->alloc_id), type, (long)mutex);
+ __db_prflags(env, mbp, mutexp->flags, MutexFlagNames, " (", ")");
+#else
+ __db_msgadd(env, mbp, "%s flags %x id %ld ",
+ type, mutexp->flags, (long)mutex);
+#endif
+ (void)snprintf(dest, DB_MUTEX_DESCRIBE_STRLEN - 1,
+ "%.*s", (int)(mbp->cur - mbp->buf), mbp->buf);
+ dest[DB_MUTEX_DESCRIBE_STRLEN - 1] = '\0';
+ return (dest);
+}