00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #endif
00018
00019 #include "db_int.h"
00020 #include "dbinc/db_page.h"
00021 #include "dbinc/db_am.h"
00022 #include "dbinc/mutex_int.h"
00023
00024 #ifdef HAVE_STATISTICS
00025 static int __mutex_print_all __P((DB_ENV *, u_int32_t));
00026 static const char *__mutex_print_id __P((int));
00027 static int __mutex_print_stats __P((DB_ENV *, u_int32_t));
00028 static void __mutex_print_summary __P((DB_ENV *));
00029
00030
00031
00032
00033
00034
00035
00036 int
00037 __mutex_stat(dbenv, statp, flags)
00038 DB_ENV *dbenv;
00039 DB_MUTEX_STAT **statp;
00040 u_int32_t flags;
00041 {
00042 DB_MUTEXMGR *mtxmgr;
00043 DB_MUTEXREGION *mtxregion;
00044 DB_MUTEX_STAT *stats;
00045 int ret;
00046
00047 PANIC_CHECK(dbenv);
00048
00049 if ((ret = __db_fchk(dbenv,
00050 "DB_ENV->mutex_stat", flags, DB_STAT_CLEAR)) != 0)
00051 return (ret);
00052
00053 *statp = NULL;
00054 mtxmgr = dbenv->mutex_handle;
00055 mtxregion = mtxmgr->reginfo.primary;
00056
00057 if ((ret = __os_umalloc(dbenv, sizeof(DB_MUTEX_STAT), &stats)) != 0)
00058 return (ret);
00059
00060 MUTEX_SYSTEM_LOCK(dbenv);
00061
00062
00063
00064
00065
00066 *stats = mtxregion->stat;
00067 stats->st_regsize = mtxmgr->reginfo.rp->size;
00068 __mutex_set_wait_info(dbenv, mtxregion->mtx_region,
00069 &stats->st_region_wait, &stats->st_region_nowait);
00070 if (LF_ISSET(DB_STAT_CLEAR))
00071 __mutex_clear(dbenv, mtxregion->mtx_region);
00072
00073 MUTEX_SYSTEM_UNLOCK(dbenv);
00074
00075 *statp = stats;
00076 return (0);
00077 }
00078
00079
00080
00081
00082
00083
00084
00085 int
00086 __mutex_stat_print(dbenv, flags)
00087 DB_ENV *dbenv;
00088 u_int32_t flags;
00089 {
00090 u_int32_t orig_flags;
00091 int ret;
00092
00093 PANIC_CHECK(dbenv);
00094
00095 if ((ret = __db_fchk(dbenv, "DB_ENV->mutex_stat_print",
00096 flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0)
00097 return (ret);
00098
00099 orig_flags = flags;
00100 LF_CLR(DB_STAT_CLEAR);
00101 if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
00102 ret = __mutex_print_stats(dbenv, orig_flags);
00103 __mutex_print_summary(dbenv);
00104 if (flags == 0 || ret != 0)
00105 return (ret);
00106 }
00107
00108 if (LF_ISSET(DB_STAT_ALL))
00109 ret = __mutex_print_all(dbenv, orig_flags);
00110
00111 return (0);
00112 }
00113
00114 static void
00115 __mutex_print_summary(dbenv)
00116 DB_ENV *dbenv;
00117 {
00118 DB_MUTEX *mutexp;
00119 DB_MUTEXMGR *mtxmgr;
00120 DB_MUTEXREGION *mtxregion;
00121 db_mutex_t i;
00122 u_int32_t counts[MTX_MAX_ENTRY + 2];
00123 int alloc_id;
00124
00125 mtxmgr = dbenv->mutex_handle;
00126 mtxregion = mtxmgr->reginfo.primary;
00127 memset(counts, 0, sizeof(counts));
00128
00129 for (i = 1; i <= mtxregion->stat.st_mutex_cnt; ++i, ++mutexp) {
00130 mutexp = MUTEXP_SET(i);
00131
00132 if (!F_ISSET(mutexp, DB_MUTEX_ALLOCATED))
00133 counts[0]++;
00134 else if (mutexp->alloc_id > MTX_MAX_ENTRY)
00135 counts[MTX_MAX_ENTRY + 1]++;
00136 else
00137 counts[mutexp->alloc_id]++;
00138 }
00139 __db_msg(dbenv, "Mutex counts");
00140 __db_msg(dbenv, "%d\tUnallocated", counts[0]);
00141 for (alloc_id = 1; alloc_id <= MTX_TXN_REGION + 1; alloc_id++)
00142 if (counts[alloc_id] != 0)
00143 __db_msg(dbenv, "%lu\t%s",
00144 (u_long)counts[alloc_id],
00145 __mutex_print_id(alloc_id));
00146
00147 }
00148
00149
00150
00151
00152
00153 static int
00154 __mutex_print_stats(dbenv, flags)
00155 DB_ENV *dbenv;
00156 u_int32_t flags;
00157 {
00158 DB_MUTEX_STAT *sp;
00159 DB_MUTEXMGR *mtxmgr;
00160 DB_MUTEXREGION *mtxregion;
00161 REGINFO *infop;
00162 THREAD_INFO *thread;
00163 int ret;
00164
00165 if ((ret = __mutex_stat(dbenv, &sp, LF_ISSET(DB_STAT_CLEAR))) != 0)
00166 return (ret);
00167
00168 if (LF_ISSET(DB_STAT_ALL))
00169 __db_msg(dbenv, "Default mutex region information:");
00170
00171 __db_dlbytes(dbenv, "Mutex region size",
00172 (u_long)0, (u_long)0, (u_long)sp->st_regsize);
00173 __db_dl_pct(dbenv,
00174 "The number of region locks that required waiting",
00175 (u_long)sp->st_region_wait, DB_PCT(sp->st_region_wait,
00176 sp->st_region_wait + sp->st_region_nowait), NULL);
00177 STAT_ULONG("Mutex alignment", sp->st_mutex_align);
00178 STAT_ULONG("Mutex test-and-set spins", sp->st_mutex_tas_spins);
00179 STAT_ULONG("Mutex total count", sp->st_mutex_cnt);
00180 STAT_ULONG("Mutex free count", sp->st_mutex_free);
00181 STAT_ULONG("Mutex in-use count", sp->st_mutex_inuse);
00182 STAT_ULONG("Mutex maximum in-use count", sp->st_mutex_inuse_max);
00183
00184 __os_ufree(dbenv, sp);
00185
00186
00187
00188
00189
00190 if (dbenv->thr_hashtab != NULL) {
00191 mtxmgr = dbenv->mutex_handle;
00192 mtxregion = mtxmgr->reginfo.primary;
00193 infop = &mtxmgr->reginfo;
00194 thread = R_ADDR(infop, mtxregion->thread_off);
00195 STAT_ULONG("Thread blocks allocated", thread->thr_count);
00196 STAT_ULONG("Thread allocation threshold", thread->thr_max);
00197 STAT_ULONG("Thread hash buckets", thread->thr_nbucket);
00198 }
00199
00200 return (0);
00201 }
00202
00203
00204
00205
00206
00207 static int
00208 __mutex_print_all(dbenv, flags)
00209 DB_ENV *dbenv;
00210 u_int32_t flags;
00211 {
00212 static const FN fn[] = {
00213 { DB_MUTEX_ALLOCATED, "alloc" },
00214 { DB_MUTEX_LOGICAL_LOCK, "logical" },
00215 { DB_MUTEX_SELF_BLOCK, "self-block" },
00216 { DB_MUTEX_THREAD, "thread" },
00217 { 0, NULL }
00218 };
00219 DB_MSGBUF mb, *mbp;
00220 DB_MUTEX *mutexp;
00221 DB_MUTEXMGR *mtxmgr;
00222 DB_MUTEXREGION *mtxregion;
00223 db_mutex_t i;
00224
00225 DB_MSGBUF_INIT(&mb);
00226 mbp = &mb;
00227
00228 mtxmgr = dbenv->mutex_handle;
00229 mtxregion = mtxmgr->reginfo.primary;
00230
00231 __db_print_reginfo(dbenv, &mtxmgr->reginfo, "Mutex");
00232 __db_msg(dbenv, "%s", DB_GLOBAL(db_line));
00233
00234 __db_msg(dbenv, "DB_MUTEXREGION structure:");
00235 __mutex_print_debug_single(dbenv,
00236 "DB_MUTEXREGION region mutex", mtxregion->mtx_region, flags);
00237 STAT_ULONG("Size of the aligned mutex", mtxregion->mutex_size);
00238 STAT_ULONG("Next free mutex", mtxregion->mutex_next);
00239
00240
00241
00242
00243
00244
00245
00246
00247 __db_msg(dbenv, "%s", DB_GLOBAL(db_line));
00248 __db_msg(dbenv, "mutex\twait/nowait, pct wait, holder, flags");
00249 for (i = 1; i <= mtxregion->stat.st_mutex_cnt; ++i, ++mutexp) {
00250 mutexp = MUTEXP_SET(i);
00251
00252 if (!F_ISSET(mutexp, DB_MUTEX_ALLOCATED))
00253 continue;
00254
00255 __db_msgadd(dbenv, mbp, "%5lu\t", (u_long)i);
00256
00257 __mutex_print_debug_stats(dbenv, mbp, i, flags);
00258
00259 if (mutexp->alloc_id != 0)
00260 __db_msgadd(dbenv,
00261 mbp, ", %s", __mutex_print_id(mutexp->alloc_id));
00262
00263 __db_prflags(dbenv, mbp, mutexp->flags, fn, " (", ")");
00264
00265 DB_MSGBUF_FLUSH(dbenv, mbp);
00266 }
00267
00268 return (0);
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 void
00280 __mutex_print_debug_single(dbenv, tag, mutex, flags)
00281 DB_ENV *dbenv;
00282 const char *tag;
00283 db_mutex_t mutex;
00284 u_int32_t flags;
00285 {
00286 DB_MSGBUF mb, *mbp;
00287
00288 DB_MSGBUF_INIT(&mb);
00289 mbp = &mb;
00290
00291 __db_msgadd(dbenv, mbp, "%lu\t%s ", (u_long)mutex, tag);
00292 __mutex_print_debug_stats(dbenv, mbp, mutex, flags);
00293 DB_MSGBUF_FLUSH(dbenv, mbp);
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 void
00305 __mutex_print_debug_stats(dbenv, mbp, mutex, flags)
00306 DB_ENV *dbenv;
00307 DB_MSGBUF *mbp;
00308 db_mutex_t mutex;
00309 u_int32_t flags;
00310 {
00311 DB_MUTEX *mutexp;
00312 DB_MUTEXMGR *mtxmgr;
00313 DB_MUTEXREGION *mtxregion;
00314 u_long value;
00315 char buf[DB_THREADID_STRLEN];
00316
00317 if (mutex == MUTEX_INVALID) {
00318 __db_msgadd(dbenv, mbp, "[!Set]");
00319 return;
00320 }
00321
00322 mtxmgr = dbenv->mutex_handle;
00323 mtxregion = mtxmgr->reginfo.primary;
00324 mutexp = MUTEXP_SET(mutex);
00325
00326 __db_msgadd(dbenv, mbp, "[");
00327 if ((value = mutexp->mutex_set_wait) < 10000000)
00328 __db_msgadd(dbenv, mbp, "%lu", value);
00329 else
00330 __db_msgadd(dbenv, mbp, "%luM", value / 1000000);
00331 if ((value = mutexp->mutex_set_nowait) < 10000000)
00332 __db_msgadd(dbenv, mbp, "/%lu", value);
00333 else
00334 __db_msgadd(dbenv, mbp, "/%luM", value / 1000000);
00335
00336 __db_msgadd(dbenv, mbp, " %d%%",
00337 DB_PCT(mutexp->mutex_set_wait,
00338 mutexp->mutex_set_wait + mutexp->mutex_set_nowait));
00339
00340 if (F_ISSET(mutexp, DB_MUTEX_LOCKED))
00341 __db_msgadd(dbenv, mbp, " %s]",
00342 dbenv->thread_id_string(dbenv,
00343 mutexp->pid, mutexp->tid, buf));
00344 else
00345 __db_msgadd(dbenv, mbp, " !Own]");
00346
00347 if (LF_ISSET(DB_STAT_CLEAR))
00348 __mutex_clear(dbenv, mutex);
00349 }
00350
00351 static const char *
00352 __mutex_print_id(alloc_id)
00353 int alloc_id;
00354 {
00355 switch (alloc_id) {
00356 case MTX_APPLICATION: return ("application allocated");
00357 case MTX_DB_HANDLE: return ("db handle");
00358 case MTX_ENV_DBLIST: return ("env dblist");
00359 case MTX_ENV_REGION: return ("env region");
00360 case MTX_LOCK_REGION: return ("lock region");
00361 case MTX_LOGICAL_LOCK: return ("logical lock");
00362 case MTX_LOG_FILENAME: return ("log filename");
00363 case MTX_LOG_FLUSH: return ("log flush");
00364 case MTX_LOG_HANDLE: return ("log handle");
00365 case MTX_LOG_REGION: return ("log region");
00366 case MTX_MPOOLFILE_HANDLE: return ("mpoolfile handle");
00367 case MTX_MPOOL_BUFFER: return ("mpool buffer");
00368 case MTX_MPOOL_FH: return ("mpool filehandle");
00369 case MTX_MPOOL_HANDLE: return ("mpool handle");
00370 case MTX_MPOOL_HASH_BUCKET: return ("mpool hash bucket");
00371 case MTX_MPOOL_REGION: return ("mpool region");
00372 case MTX_REP_DATABASE: return ("replication database");
00373 case MTX_REP_REGION: return ("replication region");
00374 case MTX_SEQUENCE: return ("sequence");
00375 case MTX_TWISTER: return ("twister");
00376 case MTX_TXN_ACTIVE: return ("txn active list");
00377 case MTX_TXN_COMMIT: return ("txn commit");
00378 case MTX_TXN_REGION: return ("txn region");
00379 default: return ("unknown mutex type");
00380 }
00381
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391 void
00392 __mutex_set_wait_info(dbenv, mutex, waitp, nowaitp)
00393 DB_ENV *dbenv;
00394 db_mutex_t mutex;
00395 u_int32_t *waitp, *nowaitp;
00396 {
00397 DB_MUTEX *mutexp;
00398 DB_MUTEXMGR *mtxmgr;
00399 DB_MUTEXREGION *mtxregion;
00400
00401 mtxmgr = dbenv->mutex_handle;
00402 mtxregion = mtxmgr->reginfo.primary;
00403 mutexp = MUTEXP_SET(mutex);
00404
00405 *waitp = mutexp->mutex_set_wait;
00406 *nowaitp = mutexp->mutex_set_nowait;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415 void
00416 __mutex_clear(dbenv, mutex)
00417 DB_ENV *dbenv;
00418 db_mutex_t mutex;
00419 {
00420 DB_MUTEX *mutexp;
00421 DB_MUTEXMGR *mtxmgr;
00422 DB_MUTEXREGION *mtxregion;
00423
00424 mtxmgr = dbenv->mutex_handle;
00425 mtxregion = mtxmgr->reginfo.primary;
00426 mutexp = MUTEXP_SET(mutex);
00427
00428 mutexp->mutex_set_wait = mutexp->mutex_set_nowait = 0;
00429 }
00430
00431 #else
00432
00433 int
00434 __mutex_stat(dbenv, statp, flags)
00435 DB_ENV *dbenv;
00436 DB_MUTEX_STAT **statp;
00437 u_int32_t flags;
00438 {
00439 COMPQUIET(statp, NULL);
00440 COMPQUIET(flags, 0);
00441
00442 return (__db_stat_not_built(dbenv));
00443 }
00444
00445 int
00446 __mutex_stat_print(dbenv, flags)
00447 DB_ENV *dbenv;
00448 u_int32_t flags;
00449 {
00450 COMPQUIET(flags, 0);
00451
00452 return (__db_stat_not_built(dbenv));
00453 }
00454 #endif