📄 plockstat.c
字号:
/* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only. * See the file usr/src/LICENSING.NOTICE in this distribution or * http://www.opensolaris.org/license/ for details. */#pragma ident "@(#)plockstat.c 1.3 04/12/06 SMI"#include <assert.h>#include <dtrace.h>#include <link.h>#include <priv.h>#include <signal.h>#include <stdlib.h>#include <stdarg.h>#include <stdio.h>#include <string.h>#include <strings.h>#include <errno.h>#include <sys/wait.h>#include <libproc.h>static char *g_pname;static dtrace_hdl_t *g_dtp;struct ps_prochandle *g_pr;#define E_SUCCESS 0#define E_ERROR 1#define E_USAGE 2/* * For hold times we use a global associative array since for mutexes, in * user-land, it's not invalid to release a sychonization primitive that * another thread acquired; rwlocks require a thread-local associative array * since multiple thread can hold the same lock for reading. Note that we * ignore recursive mutex acquisitions and releases as they don't truly * affect lock contention. */static const char *g_hold_init ="plockstat$target:::rw-acquire\n""{\n"" self->rwhold[arg0] = timestamp;\n""}\n""plockstat$target:::mutex-acquire\n""/arg1 == 0/\n""{\n"" mtxhold[arg0] = timestamp;\n""}\n";static const char *g_hold_histogram ="plockstat$target:::rw-release\n""/self->rwhold[arg0] && arg1 == 1/\n""{\n"" @rw_w_hold[arg0, ustack()] =\n"" quantize(timestamp - self->rwhold[arg0]);\n"" self->rwhold[arg0] = 0;\n""}\n""plockstat$target:::rw-release\n""/self->rwhold[arg0]/\n""{\n"" @rw_r_hold[arg0, ustack()] =\n"" quantize(timestamp - self->rwhold[arg0]);\n"" self->rwhold[arg0] = 0;\n""}\n""plockstat$target:::mutex-release\n""/mtxhold[arg0] && arg1 == 0/\n""{\n"" @mtx_hold[arg0, ustack()] = quantize(timestamp - mtxhold[arg0]);\n"" mtxhold[arg0] = 0;\n""}\n";static const char *g_hold_times ="plockstat$target:::rw-release\n""/self->rwhold[arg0] && arg1 == 1/\n""{\n"" @rw_w_hold[arg0, ustack(5)] = avg(timestamp - self->rwhold[arg0]);\n"" self->rwhold[arg0] = 0;\n""}\n""plockstat$target:::rw-release\n""/self->rwhold[arg0]/\n""{\n"" @rw_r_hold[arg0, ustack(5)] = avg(timestamp - self->rwhold[arg0]);\n"" self->rwhold[arg0] = 0;\n""}\n""plockstat$target:::mutex-release\n""/mtxhold[arg0] && arg1 == 0/\n""{\n"" @mtx_hold[arg0, ustack(5)] = avg(timestamp - mtxhold[arg0]);\n"" mtxhold[arg0] = 0;\n""}\n";/* * For contention, we use thread-local associative arrays since we're tracing * a single thread's activity in libc and multiple threads can be blocking or * spinning on the same sychonization primitive. */static const char *g_ctnd_init ="plockstat$target:::rw-block\n""{\n"" self->rwblock[arg0] = timestamp;\n""}\n""plockstat$target:::mutex-block\n""{\n"" self->mtxblock[arg0] = timestamp;\n""}\n""plockstat$target:::mutex-spin\n""{\n"" self->mtxspin[arg0] = timestamp;\n""}\n";static const char *g_ctnd_histogram ="plockstat$target:::rw-acquire\n""/self->rwblock[arg0] && arg1 == 1/\n""{\n"" @rw_w_block[arg0, ustack()] =\n"" quantize(timestamp - self->rwblock[arg0]);\n"" self->rwblock[arg0] = 0;\n""}\n""plockstat$target:::rw-acquire\n""/self->rwblock[arg0]/\n""{\n"" @rw_r_block[arg0, ustack()] =\n"" quantize(timestamp - self->rwblock[arg0]);\n"" self->rwblock[arg0] = 0;\n""}\n""plockstat$target:::mutex-block\n""/self->mtxspin[arg0]/\n""{\n"" @mtx_vain_spin[arg0, ustack()] =\n"" quantize(timestamp - self->mtxspin[arg0]);\n"" self->mtxspin[arg0] = 0;\n""}\n""plockstat$target:::mutex-acquire\n""/self->mtxspin[arg0]/\n""{\n"" @mtx_spin[arg0, ustack()] =\n"" quantize(timestamp - self->mtxspin[arg0]);\n"" self->mtxspin[arg0] = 0;\n""}\n""plockstat$target:::mutex-acquire\n""/self->mtxblock[arg0]/\n""{\n"" @mtx_block[arg0, ustack()] =\n"" quantize(timestamp - self->mtxblock[arg0]);\n"" self->mtxblock[arg0] = 0;\n""}\n""plockstat$target:::mutex-error\n""/self->mtxblock[arg0]/\n""{\n"" self->mtxblock[arg0] = 0;\n""}\n""plockstat$target:::rw-error\n""/self->rwblock[arg0]/\n""{\n"" self->rwblock[arg0] = 0;\n""}\n""plockstat$target:::mutex-error\n""/self->mtxspin[arg0]/\n""{\n"" self->mtxspin[arg0] = 0;\n""}\n";static const char *g_ctnd_times ="plockstat$target:::rw-acquire\n""/self->rwblock[arg0] && arg1 == 1/\n""{\n"" @rw_w_block[arg0, ustack(5)] =\n"" avg(timestamp - self->rwblock[arg0]);\n"" self->rwblock[arg0] = 0;\n""}\n""plockstat$target:::rw-acquire\n""/self->rwblock[arg0]/\n""{\n"" @rw_r_block[arg0, ustack(5)] =\n"" avg(timestamp - self->rwblock[arg0]);\n"" self->rwblock[arg0] = 0;\n""}\n""plockstat$target:::mutex-block\n""/self->mtxspin[arg0]/\n""{\n"" @mtx_vain_spin[arg0, ustack(5)] =\n"" avg(timestamp - self->mtxspin[arg0]);\n"" self->mtxspin[arg0] = 0;\n""}\n""plockstat$target:::mutex-acquire\n""/self->mtxspin[arg0]/\n""{\n"" @mtx_spin[arg0, ustack(5)] =\n"" avg(timestamp - self->mtxspin[arg0]);\n"" self->mtxspin[arg0] = 0;\n""}\n""plockstat$target:::mutex-acquire\n""/self->mtxblock[arg0]/\n""{\n"" @mtx_block[arg0, ustack(5)] =\n"" avg(timestamp - self->mtxblock[arg0]);\n"" self->mtxblock[arg0] = 0;\n""}\n""plockstat$target:::mutex-error\n""/self->mtxblock[arg0]/\n""{\n"" self->mtxblock[arg0] = 0;\n""}\n""plockstat$target:::rw-error\n""/self->rwblock[arg0]/\n""{\n"" self->rwblock[arg0] = 0;\n""}\n""plockstat$target:::mutex-error\n""/self->mtxspin[arg0]/\n""{\n"" self->mtxspin[arg0] = 0;\n""}\n";static char g_prog[2048];static size_t g_proglen;static int g_opt_V;static char *g_opt_s;static int g_intr;static dtrace_optval_t g_nframes;static voidusage(void){ (void) fprintf(stderr, "Usage:\n" "\t%s [-ACHV] [-s depth] command [arg...]\n" "\t%s [-ACHV] [-s depth] -p pid\n", g_pname, g_pname); exit(E_USAGE);}static voidverror(const char *fmt, va_list ap){ int error = errno; (void) fprintf(stderr, "%s: ", g_pname); (void) vfprintf(stderr, fmt, ap); if (fmt[strlen(fmt) - 1] != '\n') (void) fprintf(stderr, ": %s\n", strerror(error));}/*PRINTFLIKE1*/static voidfatal(const char *fmt, ...){ va_list ap; va_start(ap, fmt); verror(fmt, ap); va_end(ap); if (g_pr != NULL && g_dtp != NULL) dtrace_proc_release(g_dtp, g_pr); exit(E_ERROR);}/*PRINTFLIKE1*/static voiddfatal(const char *fmt, ...){ va_list ap; va_start(ap, fmt); (void) fprintf(stderr, "%s: ", g_pname); if (fmt != NULL) (void) vfprintf(stderr, fmt, ap); va_end(ap); if (fmt != NULL && fmt[strlen(fmt) - 1] != '\n') { (void) fprintf(stderr, ": %s\n", dtrace_errmsg(g_dtp, dtrace_errno(g_dtp))); } else if (fmt == NULL) { (void) fprintf(stderr, "%s\n", dtrace_errmsg(g_dtp, dtrace_errno(g_dtp))); } if (g_pr != NULL) dtrace_proc_release(g_dtp, g_pr); exit(E_ERROR);}/*PRINTFLIKE1*/static voidnotice(const char *fmt, ...){ va_list ap; va_start(ap, fmt); verror(fmt, ap); va_end(ap);}static voiddprog_add(const char *prog){ size_t len = strlen(prog); bcopy(prog, g_prog + g_proglen, len + 1); g_proglen += len;}static voiddprog_compile(void){ dtrace_prog_t *prog; dtrace_proginfo_t info; if (g_opt_V) { (void) fprintf(stderr, "%s: vvvv D program vvvv\n", g_pname); (void) fputs(g_prog, stderr); (void) fprintf(stderr, "%s: ^^^^ D program ^^^^\n", g_pname); } if ((prog = dtrace_program_strcompile(g_dtp, g_prog, DTRACE_PROBESPEC_NAME, 0, 0, NULL)) == NULL) dfatal("failed to compile program"); if (dtrace_program_exec(g_dtp, prog, &info) == -1) dfatal("failed to enable probes");}static voidprint_header(const char *aggname){ if (strcmp(aggname, "mtx_hold") == 0) { (void) printf("\nMutex hold\n\n"); } else if (strcmp(aggname, "mtx_block") == 0) { (void) printf("\nMutex block\n\n"); } else if (strcmp(aggname, "mtx_spin") == 0) { (void) printf("\nMutex spin\n\n"); } else if (strcmp(aggname, "mtx_vain_spin") == 0) { (void) printf("\nMutex unsuccessful spin\n\n"); } else if (strcmp(aggname, "rw_r_hold") == 0) { (void) printf("\nR/W reader hold\n\n"); } else if (strcmp(aggname, "rw_w_hold") == 0) { (void) printf("\nR/W writer hold\n\n"); } else if (strcmp(aggname, "rw_r_block") == 0) { (void) printf("\nR/W reader block\n\n"); } else if (strcmp(aggname, "rw_w_block") == 0) { (void) printf("\nR/W writer block\n\n"); }}voidprint_legend(void){ (void) printf("%5s %8s %-28s %s\n", "Count", "nsec", "Lock", "Caller");}voidprint_bar(void){ (void) printf("---------------------------------------" "----------------------------------------\n");}voidprint_histogram_header(void){ (void) printf("\n%10s ---- Time Distribution --- %5s %s\n", "nsec", "count", "Stack");}/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -