Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

mut_stat.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996-2004
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: mut_stat.c,v 12.10 2005/11/01 00:44:28 bostic Exp $
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  * __mutex_stat --
00032  *      DB_ENV->mutex_stat.
00033  *
00034  * PUBLIC: int __mutex_stat __P((DB_ENV *, DB_MUTEX_STAT **, u_int32_t));
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          * Most fields are maintained in the underlying region structure.
00064          * Region size and region mutex are not.
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  * __mutex_stat_print
00081  *      DB_ENV->mutex_stat_print method.
00082  *
00083  * PUBLIC: int __mutex_stat_print __P((DB_ENV *, u_int32_t));
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  * __mutex_print_stats --
00151  *      Display default mutex region statistics.
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          * Dump out the info we have on thread tracking, we do it here only
00188          * because we share the region.
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  * __mutex_print_all --
00205  *      Display debugging mutex region statistics.
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          * The OOB mutex (MUTEX_INVALID) is 0, skip it.
00242          *
00243          * We're not holding the mutex region lock, so we're racing threads of
00244          * control allocating mutexes.  That's OK, it just means we display or
00245          * clear statistics while mutexes are moving.
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  * __mutex_print_debug_single --
00273  *      Print mutex internal debugging statistics for a single mutex on a
00274  *      single output line.
00275  *
00276  * PUBLIC: void __mutex_print_debug_single
00277  * PUBLIC:          __P((DB_ENV *, const char *, db_mutex_t, u_int32_t));
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  * __mutex_print_debug_stats --
00298  *      Print mutex internal debugging statistics, that is, the statistics
00299  *      in the [] square brackets.
00300  *
00301  * PUBLIC: void __mutex_print_debug_stats
00302  * PUBLIC:          __P((DB_ENV *, DB_MSGBUF *, db_mutex_t, u_int32_t));
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         /* NOTREACHED */
00382 }
00383 
00384 /*
00385  * __mutex_set_wait_info --
00386  *      Return mutex statistics.
00387  *
00388  * PUBLIC: void __mutex_set_wait_info
00389  * PUBLIC:      __P((DB_ENV *, db_mutex_t, u_int32_t *, u_int32_t *));
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  * __mutex_clear --
00411  *      Clear mutex statistics.
00412  *
00413  * PUBLIC: void __mutex_clear __P((DB_ENV *, db_mutex_t));
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 /* !HAVE_STATISTICS */
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

Generated on Sun Dec 25 12:14:41 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2