Remove definition of builtin function
[platform/upstream/db4.git] / mutex / mut_stat.c
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1996-2009 Oracle.  All rights reserved.
5  *
6  * $Id$
7  */
8
9 #include "db_config.h"
10
11 #include "db_int.h"
12 #include "dbinc/db_page.h"
13 #include "dbinc/db_am.h"
14
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));
21
22 /*
23  * __mutex_stat_pp --
24  *      ENV->mutex_stat pre/post processing.
25  *
26  * PUBLIC: int __mutex_stat_pp __P((DB_ENV *, DB_MUTEX_STAT **, u_int32_t));
27  */
28 int
29 __mutex_stat_pp(dbenv, statp, flags)
30         DB_ENV *dbenv;
31         DB_MUTEX_STAT **statp;
32         u_int32_t flags;
33 {
34         DB_THREAD_INFO *ip;
35         ENV *env;
36         int ret;
37
38         env = dbenv->env;
39
40         if ((ret = __db_fchk(env,
41             "DB_ENV->mutex_stat", flags, DB_STAT_CLEAR)) != 0)
42                 return (ret);
43
44         ENV_ENTER(env, ip);
45         REPLICATION_WRAP(env, (__mutex_stat(env, statp, flags)), 0, ret);
46         ENV_LEAVE(env, ip);
47         return (ret);
48 }
49
50 /*
51  * __mutex_stat --
52  *      ENV->mutex_stat.
53  */
54 static int
55 __mutex_stat(env, statp, flags)
56         ENV *env;
57         DB_MUTEX_STAT **statp;
58         u_int32_t flags;
59 {
60         DB_MUTEXMGR *mtxmgr;
61         DB_MUTEXREGION *mtxregion;
62         DB_MUTEX_STAT *stats;
63         int ret;
64
65         *statp = NULL;
66         mtxmgr = env->mutex_handle;
67         mtxregion = mtxmgr->reginfo.primary;
68
69         if ((ret = __os_umalloc(env, sizeof(DB_MUTEX_STAT), &stats)) != 0)
70                 return (ret);
71
72         MUTEX_SYSTEM_LOCK(env);
73
74         /*
75          * Most fields are maintained in the underlying region structure.
76          * Region size and region mutex are not.
77          */
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);
84
85         MUTEX_SYSTEM_UNLOCK(env);
86
87         *statp = stats;
88         return (0);
89 }
90
91 /*
92  * __mutex_stat_print_pp --
93  *      ENV->mutex_stat_print pre/post processing.
94  *
95  * PUBLIC: int __mutex_stat_print_pp __P((DB_ENV *, u_int32_t));
96  */
97 int
98 __mutex_stat_print_pp(dbenv, flags)
99         DB_ENV *dbenv;
100         u_int32_t flags;
101 {
102         DB_THREAD_INFO *ip;
103         ENV *env;
104         int ret;
105
106         env = dbenv->env;
107
108         if ((ret = __db_fchk(env, "DB_ENV->mutex_stat_print",
109             flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0)
110                 return (ret);
111
112         ENV_ENTER(env, ip);
113         REPLICATION_WRAP(env, (__mutex_stat_print(env, flags)), 0, ret);
114         ENV_LEAVE(env, ip);
115         return (ret);
116 }
117
118 /*
119  * __mutex_stat_print
120  *      ENV->mutex_stat_print method.
121  *
122  * PUBLIC: int __mutex_stat_print __P((ENV *, u_int32_t));
123  */
124 int
125 __mutex_stat_print(env, flags)
126         ENV *env;
127         u_int32_t flags;
128 {
129         u_int32_t orig_flags;
130         int ret;
131
132         orig_flags = 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)
138                         return (ret);
139         }
140
141         if (LF_ISSET(DB_STAT_ALL))
142                 ret = __mutex_print_all(env, orig_flags);
143
144         return (0);
145 }
146
147 static void
148 __mutex_print_summary(env)
149         ENV *env;
150 {
151         DB_MUTEX *mutexp;
152         DB_MUTEXMGR *mtxmgr;
153         DB_MUTEXREGION *mtxregion;
154         db_mutex_t i;
155         u_int32_t counts[MTX_MAX_ENTRY + 2];
156         int alloc_id;
157
158         mtxmgr = env->mutex_handle;
159         mtxregion = mtxmgr->reginfo.primary;
160         memset(counts, 0, sizeof(counts));
161
162         for (i = 1; i <= mtxregion->stat.st_mutex_cnt; ++i, ++mutexp) {
163                 mutexp = MUTEXP_SET(mtxmgr, i);
164
165                 if (!F_ISSET(mutexp, DB_MUTEX_ALLOCATED))
166                         counts[0]++;
167                 else if (mutexp->alloc_id > MTX_MAX_ENTRY)
168                         counts[MTX_MAX_ENTRY + 1]++;
169                 else
170                         counts[mutexp->alloc_id]++;
171         }
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));
179
180 }
181
182 /*
183  * __mutex_print_stats --
184  *      Display default mutex region statistics.
185  */
186 static int
187 __mutex_print_stats(env, flags)
188         ENV *env;
189         u_int32_t flags;
190 {
191         DB_MUTEX_STAT *sp;
192         int ret;
193
194         if ((ret = __mutex_stat(env, &sp, LF_ISSET(DB_STAT_CLEAR))) != 0)
195                 return (ret);
196
197         if (LF_ISSET(DB_STAT_ALL))
198                 __db_msg(env, "Default mutex region information:");
199
200         __db_dlbytes(env, "Mutex region size",
201             (u_long)0, (u_long)0, (u_long)sp->st_regsize);
202         __db_dl_pct(env,
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);
212
213         __os_ufree(env, sp);
214
215         return (0);
216 }
217
218 /*
219  * __mutex_print_all --
220  *      Display debugging mutex region statistics.
221  */
222 static int
223 __mutex_print_all(env, flags)
224         ENV *env;
225         u_int32_t flags;
226 {
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" },
233                 { 0,                            NULL }
234         };
235         DB_MSGBUF mb, *mbp;
236         DB_MUTEX *mutexp;
237         DB_MUTEXMGR *mtxmgr;
238         DB_MUTEXREGION *mtxregion;
239         db_mutex_t i;
240
241         DB_MSGBUF_INIT(&mb);
242         mbp = &mb;
243
244         mtxmgr = env->mutex_handle;
245         mtxregion = mtxmgr->reginfo.primary;
246
247         __db_print_reginfo(env, &mtxmgr->reginfo, "Mutex", flags);
248         __db_msg(env, "%s", DB_GLOBAL(db_line));
249
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);
255
256         /*
257          * The OOB mutex (MUTEX_INVALID) is 0, skip it.
258          *
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.
262          */
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);
267
268                 if (!F_ISSET(mutexp, DB_MUTEX_ALLOCATED))
269                         continue;
270
271                 __db_msgadd(env, mbp, "%5lu\t", (u_long)i);
272
273                 __mutex_print_debug_stats(env, mbp, i, flags);
274
275                 if (mutexp->alloc_id != 0)
276                         __db_msgadd(env,
277                             mbp, ", %s", __mutex_print_id(mutexp->alloc_id));
278
279                 __db_prflags(env, mbp, mutexp->flags, fn, " (", ")");
280
281                 DB_MSGBUF_FLUSH(env, mbp);
282         }
283
284         return (0);
285 }
286
287 /*
288  * __mutex_print_debug_single --
289  *      Print mutex internal debugging statistics for a single mutex on a
290  *      single output line.
291  *
292  * PUBLIC: void __mutex_print_debug_single
293  * PUBLIC:          __P((ENV *, const char *, db_mutex_t, u_int32_t));
294  */
295 void
296 __mutex_print_debug_single(env, tag, mutex, flags)
297         ENV *env;
298         const char *tag;
299         db_mutex_t mutex;
300         u_int32_t flags;
301 {
302         DB_MSGBUF mb, *mbp;
303
304         DB_MSGBUF_INIT(&mb);
305         mbp = &mb;
306
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);
312 }
313
314 /*
315  * __mutex_print_debug_stats --
316  *      Print mutex internal debugging statistics, that is, the statistics
317  *      in the [] square brackets.
318  *
319  * PUBLIC: void __mutex_print_debug_stats
320  * PUBLIC:          __P((ENV *, DB_MSGBUF *, db_mutex_t, u_int32_t));
321  */
322 void
323 __mutex_print_debug_stats(env, mbp, mutex, flags)
324         ENV *env;
325         DB_MSGBUF *mbp;
326         db_mutex_t mutex;
327         u_int32_t flags;
328 {
329         DB_ENV *dbenv;
330         DB_MUTEX *mutexp;
331         DB_MUTEXMGR *mtxmgr;
332         u_long value;
333         char buf[DB_THREADID_STRLEN];
334 #if defined(HAVE_SHARED_LATCHES) && defined(HAVE_MUTEX_HYBRID)
335         int sharecount;
336 #endif
337
338         if (mutex == MUTEX_INVALID) {
339                 __db_msgadd(env, mbp, "[!Set]");
340                 return;
341         }
342
343         dbenv = env->dbenv;
344         mtxmgr = env->mutex_handle;
345         mutexp = MUTEXP_SET(mtxmgr, mutex);
346
347         __db_msgadd(env, mbp, "[");
348         if ((value = mutexp->mutex_set_wait) < 10000000)
349                 __db_msgadd(env, mbp, "%lu", value);
350         else
351                 __db_msgadd(env, mbp, "%luM", value / 1000000);
352         if ((value = mutexp->mutex_set_nowait) < 10000000)
353                 __db_msgadd(env, mbp, "/%lu", value);
354         else
355                 __db_msgadd(env, mbp, "/%luM", value / 1000000);
356
357         __db_msgadd(env, mbp, " %d%% ",
358             DB_PCT(mutexp->mutex_set_wait,
359             mutexp->mutex_set_wait + mutexp->mutex_set_nowait));
360
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);
366                 else
367                         __db_msgadd(env, mbp, "%luM", value / 1000000);
368                 if ((value = mutexp->mutex_set_rd_nowait) < 10000000)
369                         __db_msgadd(env, mbp, "/%lu", value);
370                 else
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));
375         }
376 #endif
377
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) {
386                 if (sharecount == 1)
387                         __db_msgadd(env, mbp, "1 reader");
388                 else
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));
394         }
395 #endif
396         else
397                 __db_msgadd(env, mbp, "!Own]");
398
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);
403 #endif
404
405         if (LF_ISSET(DB_STAT_CLEAR))
406                 __mutex_clear(env, mutex);
407 }
408
409 static const char *
410 __mutex_print_id(alloc_id)
411         int alloc_id;
412 {
413         switch (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");
448         /* NOTREACHED */
449         }
450 }
451
452 /*
453  * __mutex_set_wait_info --
454  *      Return mutex statistics.
455  *
456  * PUBLIC: void __mutex_set_wait_info
457  * PUBLIC:      __P((ENV *, db_mutex_t, uintmax_t *, uintmax_t *));
458  */
459 void
460 __mutex_set_wait_info(env, mutex, waitp, nowaitp)
461         ENV *env;
462         db_mutex_t mutex;
463         uintmax_t *waitp, *nowaitp;
464 {
465         DB_MUTEX *mutexp;
466         DB_MUTEXMGR *mtxmgr;
467
468         mtxmgr = env->mutex_handle;
469         mutexp = MUTEXP_SET(mtxmgr, mutex);
470
471         *waitp = mutexp->mutex_set_wait;
472         *nowaitp = mutexp->mutex_set_nowait;
473 }
474
475 /*
476  * __mutex_clear --
477  *      Clear mutex statistics.
478  *
479  * PUBLIC: void __mutex_clear __P((ENV *, db_mutex_t));
480  */
481 void
482 __mutex_clear(env, mutex)
483         ENV *env;
484         db_mutex_t mutex;
485 {
486         DB_MUTEX *mutexp;
487         DB_MUTEXMGR *mtxmgr;
488
489         mtxmgr = env->mutex_handle;
490         mutexp = MUTEXP_SET(mtxmgr, mutex);
491
492         mutexp->mutex_set_wait = mutexp->mutex_set_nowait = 0;
493 #ifdef HAVE_MUTEX_HYBRID
494         mutexp->hybrid_wait = mutexp->hybrid_wakeup = 0;
495 #endif
496 }
497
498 #else /* !HAVE_STATISTICS */
499
500 int
501 __mutex_stat_pp(dbenv, statp, flags)
502         DB_ENV *dbenv;
503         DB_MUTEX_STAT **statp;
504         u_int32_t flags;
505 {
506         COMPQUIET(statp, NULL);
507         COMPQUIET(flags, 0);
508
509         return (__db_stat_not_built(dbenv->env));
510 }
511
512 int
513 __mutex_stat_print_pp(dbenv, flags)
514         DB_ENV *dbenv;
515         u_int32_t flags;
516 {
517         COMPQUIET(flags, 0);
518
519         return (__db_stat_not_built(dbenv->env));
520 }
521 #endif