2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996-2009 Oracle. All rights reserved.
12 #include "dbinc/db_page.h"
13 #include "dbinc/db_am.h"
15 #ifdef HAVE_STATISTICS
16 static int __mutex_print_all __P((ENV *, u_int32_t));
17 static const char *__mutex_print_id __P((int));
18 static int __mutex_print_stats __P((ENV *, u_int32_t));
19 static void __mutex_print_summary __P((ENV *));
20 static int __mutex_stat __P((ENV *, DB_MUTEX_STAT **, u_int32_t));
24 * ENV->mutex_stat pre/post processing.
26 * PUBLIC: int __mutex_stat_pp __P((DB_ENV *, DB_MUTEX_STAT **, u_int32_t));
29 __mutex_stat_pp(dbenv, statp, flags)
31 DB_MUTEX_STAT **statp;
40 if ((ret = __db_fchk(env,
41 "DB_ENV->mutex_stat", flags, DB_STAT_CLEAR)) != 0)
45 REPLICATION_WRAP(env, (__mutex_stat(env, statp, flags)), 0, ret);
55 __mutex_stat(env, statp, flags)
57 DB_MUTEX_STAT **statp;
61 DB_MUTEXREGION *mtxregion;
66 mtxmgr = env->mutex_handle;
67 mtxregion = mtxmgr->reginfo.primary;
69 if ((ret = __os_umalloc(env, sizeof(DB_MUTEX_STAT), &stats)) != 0)
72 MUTEX_SYSTEM_LOCK(env);
75 * Most fields are maintained in the underlying region structure.
76 * Region size and region mutex are not.
78 *stats = mtxregion->stat;
79 stats->st_regsize = mtxmgr->reginfo.rp->size;
80 __mutex_set_wait_info(env, mtxregion->mtx_region,
81 &stats->st_region_wait, &stats->st_region_nowait);
82 if (LF_ISSET(DB_STAT_CLEAR))
83 __mutex_clear(env, mtxregion->mtx_region);
85 MUTEX_SYSTEM_UNLOCK(env);
92 * __mutex_stat_print_pp --
93 * ENV->mutex_stat_print pre/post processing.
95 * PUBLIC: int __mutex_stat_print_pp __P((DB_ENV *, u_int32_t));
98 __mutex_stat_print_pp(dbenv, flags)
108 if ((ret = __db_fchk(env, "DB_ENV->mutex_stat_print",
109 flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0)
113 REPLICATION_WRAP(env, (__mutex_stat_print(env, flags)), 0, ret);
120 * ENV->mutex_stat_print method.
122 * PUBLIC: int __mutex_stat_print __P((ENV *, u_int32_t));
125 __mutex_stat_print(env, flags)
129 u_int32_t orig_flags;
133 LF_CLR(DB_STAT_CLEAR | DB_STAT_SUBSYSTEM);
134 if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
135 ret = __mutex_print_stats(env, orig_flags);
136 __mutex_print_summary(env);
137 if (flags == 0 || ret != 0)
141 if (LF_ISSET(DB_STAT_ALL))
142 ret = __mutex_print_all(env, orig_flags);
148 __mutex_print_summary(env)
153 DB_MUTEXREGION *mtxregion;
155 u_int32_t counts[MTX_MAX_ENTRY + 2];
158 mtxmgr = env->mutex_handle;
159 mtxregion = mtxmgr->reginfo.primary;
160 memset(counts, 0, sizeof(counts));
162 for (i = 1; i <= mtxregion->stat.st_mutex_cnt; ++i, ++mutexp) {
163 mutexp = MUTEXP_SET(mtxmgr, i);
165 if (!F_ISSET(mutexp, DB_MUTEX_ALLOCATED))
167 else if (mutexp->alloc_id > MTX_MAX_ENTRY)
168 counts[MTX_MAX_ENTRY + 1]++;
170 counts[mutexp->alloc_id]++;
172 __db_msg(env, "Mutex counts");
173 __db_msg(env, "%d\tUnallocated", counts[0]);
174 for (alloc_id = 1; alloc_id <= MTX_TXN_REGION + 1; alloc_id++)
175 if (counts[alloc_id] != 0)
176 __db_msg(env, "%lu\t%s",
177 (u_long)counts[alloc_id],
178 __mutex_print_id(alloc_id));
183 * __mutex_print_stats --
184 * Display default mutex region statistics.
187 __mutex_print_stats(env, flags)
194 if ((ret = __mutex_stat(env, &sp, LF_ISSET(DB_STAT_CLEAR))) != 0)
197 if (LF_ISSET(DB_STAT_ALL))
198 __db_msg(env, "Default mutex region information:");
200 __db_dlbytes(env, "Mutex region size",
201 (u_long)0, (u_long)0, (u_long)sp->st_regsize);
203 "The number of region locks that required waiting",
204 (u_long)sp->st_region_wait, DB_PCT(sp->st_region_wait,
205 sp->st_region_wait + sp->st_region_nowait), NULL);
206 STAT_ULONG("Mutex alignment", sp->st_mutex_align);
207 STAT_ULONG("Mutex test-and-set spins", sp->st_mutex_tas_spins);
208 STAT_ULONG("Mutex total count", sp->st_mutex_cnt);
209 STAT_ULONG("Mutex free count", sp->st_mutex_free);
210 STAT_ULONG("Mutex in-use count", sp->st_mutex_inuse);
211 STAT_ULONG("Mutex maximum in-use count", sp->st_mutex_inuse_max);
219 * __mutex_print_all --
220 * Display debugging mutex region statistics.
223 __mutex_print_all(env, flags)
227 static const FN fn[] = {
228 { DB_MUTEX_ALLOCATED, "alloc" },
229 { DB_MUTEX_LOCKED, "locked" },
230 { DB_MUTEX_LOGICAL_LOCK, "logical" },
231 { DB_MUTEX_PROCESS_ONLY, "process-private" },
232 { DB_MUTEX_SELF_BLOCK, "self-block" },
238 DB_MUTEXREGION *mtxregion;
244 mtxmgr = env->mutex_handle;
245 mtxregion = mtxmgr->reginfo.primary;
247 __db_print_reginfo(env, &mtxmgr->reginfo, "Mutex", flags);
248 __db_msg(env, "%s", DB_GLOBAL(db_line));
250 __db_msg(env, "DB_MUTEXREGION structure:");
251 __mutex_print_debug_single(env,
252 "DB_MUTEXREGION region mutex", mtxregion->mtx_region, flags);
253 STAT_ULONG("Size of the aligned mutex", mtxregion->mutex_size);
254 STAT_ULONG("Next free mutex", mtxregion->mutex_next);
257 * The OOB mutex (MUTEX_INVALID) is 0, skip it.
259 * We're not holding the mutex region lock, so we're racing threads of
260 * control allocating mutexes. That's OK, it just means we display or
261 * clear statistics while mutexes are moving.
263 __db_msg(env, "%s", DB_GLOBAL(db_line));
264 __db_msg(env, "mutex\twait/nowait, pct wait, holder, flags");
265 for (i = 1; i <= mtxregion->stat.st_mutex_cnt; ++i, ++mutexp) {
266 mutexp = MUTEXP_SET(mtxmgr, i);
268 if (!F_ISSET(mutexp, DB_MUTEX_ALLOCATED))
271 __db_msgadd(env, mbp, "%5lu\t", (u_long)i);
273 __mutex_print_debug_stats(env, mbp, i, flags);
275 if (mutexp->alloc_id != 0)
277 mbp, ", %s", __mutex_print_id(mutexp->alloc_id));
279 __db_prflags(env, mbp, mutexp->flags, fn, " (", ")");
281 DB_MSGBUF_FLUSH(env, mbp);
288 * __mutex_print_debug_single --
289 * Print mutex internal debugging statistics for a single mutex on a
290 * single output line.
292 * PUBLIC: void __mutex_print_debug_single
293 * PUBLIC: __P((ENV *, const char *, db_mutex_t, u_int32_t));
296 __mutex_print_debug_single(env, tag, mutex, flags)
307 if (LF_ISSET(DB_STAT_SUBSYSTEM))
308 LF_CLR(DB_STAT_CLEAR);
309 __db_msgadd(env, mbp, "%lu\t%s ", (u_long)mutex, tag);
310 __mutex_print_debug_stats(env, mbp, mutex, flags);
311 DB_MSGBUF_FLUSH(env, mbp);
315 * __mutex_print_debug_stats --
316 * Print mutex internal debugging statistics, that is, the statistics
317 * in the [] square brackets.
319 * PUBLIC: void __mutex_print_debug_stats
320 * PUBLIC: __P((ENV *, DB_MSGBUF *, db_mutex_t, u_int32_t));
323 __mutex_print_debug_stats(env, mbp, mutex, flags)
333 char buf[DB_THREADID_STRLEN];
334 #if defined(HAVE_SHARED_LATCHES) && defined(HAVE_MUTEX_HYBRID)
338 if (mutex == MUTEX_INVALID) {
339 __db_msgadd(env, mbp, "[!Set]");
344 mtxmgr = env->mutex_handle;
345 mutexp = MUTEXP_SET(mtxmgr, mutex);
347 __db_msgadd(env, mbp, "[");
348 if ((value = mutexp->mutex_set_wait) < 10000000)
349 __db_msgadd(env, mbp, "%lu", value);
351 __db_msgadd(env, mbp, "%luM", value / 1000000);
352 if ((value = mutexp->mutex_set_nowait) < 10000000)
353 __db_msgadd(env, mbp, "/%lu", value);
355 __db_msgadd(env, mbp, "/%luM", value / 1000000);
357 __db_msgadd(env, mbp, " %d%% ",
358 DB_PCT(mutexp->mutex_set_wait,
359 mutexp->mutex_set_wait + mutexp->mutex_set_nowait));
361 #if defined(HAVE_SHARED_LATCHES)
362 if (F_ISSET(mutexp, DB_MUTEX_SHARED)) {
363 __db_msgadd(env, mbp, " rd ");
364 if ((value = mutexp->mutex_set_rd_wait) < 10000000)
365 __db_msgadd(env, mbp, "%lu", value);
367 __db_msgadd(env, mbp, "%luM", value / 1000000);
368 if ((value = mutexp->mutex_set_rd_nowait) < 10000000)
369 __db_msgadd(env, mbp, "/%lu", value);
371 __db_msgadd(env, mbp, "/%luM", value / 1000000);
372 __db_msgadd(env, mbp, " %d%% ",
373 DB_PCT(mutexp->mutex_set_rd_wait,
374 mutexp->mutex_set_rd_wait + mutexp->mutex_set_rd_nowait));
378 if (F_ISSET(mutexp, DB_MUTEX_LOCKED))
379 __db_msgadd(env, mbp, "%s]",
380 dbenv->thread_id_string(dbenv,
381 mutexp->pid, mutexp->tid, buf));
382 /* Only hybrid shared latches expose the share count. */
383 #if defined(HAVE_SHARED_LATCHES) && defined(HAVE_MUTEX_HYBRID)
384 else if (F_ISSET(mutexp, DB_MUTEX_SHARED) &&
385 (sharecount = atomic_read(&mutexp->sharecount)) != 0) {
387 __db_msgadd(env, mbp, "1 reader");
389 __db_msgadd(env, mbp, "%d readers", sharecount);
390 /* Show the thread which last acquired the latch. */
391 __db_msgadd(env, mbp, "%s]",
392 dbenv->thread_id_string(dbenv,
393 mutexp->pid, mutexp->tid, buf));
397 __db_msgadd(env, mbp, "!Own]");
399 #ifdef HAVE_MUTEX_HYBRID
400 if (mutexp->hybrid_wait != 0 || mutexp->hybrid_wakeup != 0)
401 __db_msgadd(env, mbp, " <wakeups %d/%d>",
402 mutexp->hybrid_wait, mutexp->hybrid_wakeup);
405 if (LF_ISSET(DB_STAT_CLEAR))
406 __mutex_clear(env, mutex);
410 __mutex_print_id(alloc_id)
414 case MTX_APPLICATION: return ("application allocated");
415 case MTX_ATOMIC_EMULATION: return ("atomic emulation");
416 case MTX_DB_HANDLE: return ("db handle");
417 case MTX_ENV_DBLIST: return ("env dblist");
418 case MTX_ENV_HANDLE: return ("env handle");
419 case MTX_ENV_REGION: return ("env region");
420 case MTX_LOCK_REGION: return ("lock region");
421 case MTX_LOGICAL_LOCK: return ("logical lock");
422 case MTX_LOG_FILENAME: return ("log filename");
423 case MTX_LOG_FLUSH: return ("log flush");
424 case MTX_LOG_HANDLE: return ("log handle");
425 case MTX_LOG_REGION: return ("log region");
426 case MTX_MPOOLFILE_HANDLE: return ("mpoolfile handle");
427 case MTX_MPOOL_BH: return ("mpool buffer");
428 case MTX_MPOOL_FH: return ("mpool filehandle");
429 case MTX_MPOOL_FILE_BUCKET: return ("mpool file bucket");
430 case MTX_MPOOL_HANDLE: return ("mpool handle");
431 case MTX_MPOOL_HASH_BUCKET: return ("mpool hash bucket");
432 case MTX_MPOOL_REGION: return ("mpool region");
433 case MTX_MUTEX_REGION: return ("mutex region");
434 case MTX_MUTEX_TEST: return ("mutex test");
435 case MTX_REPMGR: return ("replication manager");
436 case MTX_REP_CHKPT: return ("replication checkpoint");
437 case MTX_REP_DATABASE: return ("replication database");
438 case MTX_REP_EVENT: return ("replication event");
439 case MTX_REP_REGION: return ("replication region");
440 case MTX_SEQUENCE: return ("sequence");
441 case MTX_TWISTER: return ("twister");
442 case MTX_TXN_ACTIVE: return ("txn active list");
443 case MTX_TXN_CHKPT: return ("transaction checkpoint");
444 case MTX_TXN_COMMIT: return ("txn commit");
445 case MTX_TXN_MVCC: return ("txn mvcc");
446 case MTX_TXN_REGION: return ("txn region");
447 default: return ("unknown mutex type");
453 * __mutex_set_wait_info --
454 * Return mutex statistics.
456 * PUBLIC: void __mutex_set_wait_info
457 * PUBLIC: __P((ENV *, db_mutex_t, uintmax_t *, uintmax_t *));
460 __mutex_set_wait_info(env, mutex, waitp, nowaitp)
463 uintmax_t *waitp, *nowaitp;
468 mtxmgr = env->mutex_handle;
469 mutexp = MUTEXP_SET(mtxmgr, mutex);
471 *waitp = mutexp->mutex_set_wait;
472 *nowaitp = mutexp->mutex_set_nowait;
477 * Clear mutex statistics.
479 * PUBLIC: void __mutex_clear __P((ENV *, db_mutex_t));
482 __mutex_clear(env, mutex)
489 mtxmgr = env->mutex_handle;
490 mutexp = MUTEXP_SET(mtxmgr, mutex);
492 mutexp->mutex_set_wait = mutexp->mutex_set_nowait = 0;
493 #ifdef HAVE_MUTEX_HYBRID
494 mutexp->hybrid_wait = mutexp->hybrid_wakeup = 0;
498 #else /* !HAVE_STATISTICS */
501 __mutex_stat_pp(dbenv, statp, flags)
503 DB_MUTEX_STAT **statp;
506 COMPQUIET(statp, NULL);
509 return (__db_stat_not_built(dbenv->env));
513 __mutex_stat_print_pp(dbenv, flags)
519 return (__db_stat_not_built(dbenv->env));