⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 plockstat.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 2 页
字号:
 * Convert an address to a symbolic string or a numeric string. If nolocks * is set, we return an error code if this symbol appears to be a mutex- or * rwlock-related symbol in libc so the caller has a chance to find a more * helpful symbol. */static intgetsym(struct ps_prochandle *P, uintptr_t addr, char *buf, size_t size,    int nolocks){	char name[256];	GElf_Sym sym;	prsyminfo_t info;	size_t len;	if (P == NULL || Pxlookup_by_addr(P, addr, name, sizeof (name),	    &sym, &info) != 0) {		(void) snprintf(buf, size, "%#lx", addr);		return (0);	}	if (info.prs_lmid != LM_ID_BASE) {		len = snprintf(buf, size, "LM%lu`", info.prs_lmid);		buf += len;		size -= len;	}	len = snprintf(buf, size, "%s`%s", info.prs_object, info.prs_name);	buf += len;	size -= len;	if (sym.st_value != addr)		len = snprintf(buf, size, "+%#lx", addr - sym.st_value);	if (nolocks && strcmp("libc.so.1", info.prs_object) == 0 &&	    (strstr("mutex", info.prs_name) == 0 ||	    strstr("rw", info.prs_name) == 0))		return (-1);	return (0);}/*ARGSUSED*/static intprocess_aggregate(dtrace_aggdata_t *agg, void *arg){	static dtrace_aggid_t last = DTRACE_AGGIDNONE;	dtrace_aggdesc_t *aggdesc = agg->dtada_desc;	caddr_t data = agg->dtada_data;	dtrace_recdesc_t *rec;	uint64_t *a, count, avg;	char buf[40];	uintptr_t lock;	pid_t pid;	uint64_t *stack;	struct ps_prochandle *P;	int i, j;	if (aggdesc->dtagd_id != last)		print_header(aggdesc->dtagd_name);	rec = aggdesc->dtagd_rec;	/*LINTED - alignment*/	lock = (uintptr_t)*(uint64_t *)(data + rec[1].dtrd_offset);	/*LINTED - alignment*/	stack = (uint64_t *)(data + rec[2].dtrd_offset);	/*LINTED - alignment*/	a = (uint64_t *)(data + rec[aggdesc->dtagd_nrecs - 1].dtrd_offset);	if (g_opt_s == NULL) {		if (aggdesc->dtagd_id != last) {			print_legend();			print_bar();		}		count = a[0];		avg = a[1] / a[0];	} else {		print_bar();		print_legend();		count = avg = 0;		for (i = DTRACE_QUANTIZE_ZEROBUCKET, j = 0;		    i < DTRACE_QUANTIZE_NBUCKETS; i++, j++) {			count += a[i];			avg += a[i] << (j - 64);		}		avg /= count;	}	(void) printf("%5llu %8llu ", (u_longlong_t)count, (u_longlong_t)avg);	pid = stack[0];	P = dtrace_proc_grab(g_dtp, pid, PGRAB_RDONLY);	(void) getsym(P, lock, buf, sizeof (buf), 0);	(void) printf("%-28s ", buf);	for (i = 2; i <= 5; i++) {		if (getsym(P, stack[i], buf, sizeof (buf), 1) == 0)			break;	}	(void) printf("%s\n", buf);	if (g_opt_s != NULL) {		int stack_done = 0;		int quant_done = 0;		int first_bin, last_bin;		uint64_t bin_size;		print_histogram_header();		for (first_bin = DTRACE_QUANTIZE_ZEROBUCKET;		    a[first_bin] == 0; first_bin++)			continue;		for (last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 63;		    a[last_bin] == 0; last_bin--)			continue;		for (i = 0; !stack_done || !quant_done; i++) {			if (!stack_done) {				(void) getsym(P, stack[i + 2], buf,				    sizeof (buf), 0);			} else {				buf[0] = '\0';			}			if (!quant_done) {				bin_size = a[first_bin];				(void) printf("%10llu |%-24.*s| %5llu %s\n",				    1ULL <<				    (first_bin - DTRACE_QUANTIZE_ZEROBUCKET),				    (int)(24.0 * bin_size / count),				    "@@@@@@@@@@@@@@@@@@@@@@@@@@",				    (u_longlong_t)bin_size, buf);			} else {				(void) printf("%43s %s\n", "", buf);			}			if (i + 1 >= g_nframes || stack[i + 3] == 0)				stack_done = 1;			if (first_bin++ == last_bin)				quant_done = 1;		}	}	dtrace_proc_release(g_dtp, P);	last = aggdesc->dtagd_id;	return (DTRACE_AGGWALK_NEXT);}static intprochandler(struct ps_prochandle *P){	const psinfo_t *prp = Ppsinfo(P);	int pid = Pstatus(P)->pr_pid;	char name[SIG2STR_MAX];	switch (Pstate(P)) {	case PS_UNDEAD:		/*		 * Ideally we would like to always report pr_wstat here, but it		 * isn't possible given current /proc semantics.  If we grabbed		 * the process, Ppsinfo() will either fail or return a zeroed		 * psinfo_t depending on how far the parent is in reaping it.		 * When /proc provides a stable pr_wstat in the status file,		 * this code can be improved by examining this new pr_wstat.		 */		if (prp != NULL && WIFSIGNALED(prp->pr_wstat)) {			notice("pid %d terminated by %s\n", pid,			    proc_signame(WTERMSIG(prp->pr_wstat),			    name, sizeof (name)));		} else if (prp != NULL && WEXITSTATUS(prp->pr_wstat) != 0) {			notice("pid %d exited with status %d\n",			    pid, WEXITSTATUS(prp->pr_wstat));		} else {			notice("pid %d has exited\n", pid);		}		return (1);	case PS_LOST:		notice("pid %d exec'd a set-id or unobservable program\n", pid);		return (1);	}	return (0);}/*ARGSUSED*/static voidintr(int signo){	g_intr = 1;}intmain(int argc, char **argv){	ucred_t *ucp;	int err;	int opt_C = 0, opt_H = 0, opt_p = 0;	char c;	struct sigaction act;	int done = 0;	if ((g_pname = strrchr(argv[0], '/')) == NULL)		g_pname = argv[0];	else		argv[0] = ++g_pname;		/* for getopt() */	/*	 * Make sure we have the required dtrace_proc privilege.	 */	if ((ucp = ucred_get(getpid())) != NULL) {		const priv_set_t *psp;		if ((psp = ucred_getprivset(ucp, PRIV_EFFECTIVE)) != NULL &&		    !priv_ismember(psp, PRIV_DTRACE_PROC)) {			fatal("dtrace_proc privilege required\n");		}		ucred_free(ucp);	}	while ((c = getopt(argc, argv, "ACHs:pV")) != EOF) {		switch (c) {		case 'A':			opt_C = opt_H = 1;			break;		case 'C':			opt_C = 1;			break;		case 'H':			opt_H = 1;			break;		case 's':			g_opt_s = optarg;			break;		case 'p':			errno = 0;			opt_p = 1;			break;		case 'V':			g_opt_V = 1;			break;		default:			usage();		}	}	argc -= optind;	argv += optind;	/*	 * We need a command or at least one pid.	 */	if (argc == 0)		usage();	if (opt_C == 0 && opt_H == 0)		opt_C = 1;	if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL)		fatal("failed to initialize dtrace: %s\n",		    dtrace_errmsg(NULL, err));	if (g_opt_s != NULL)		(void) dtrace_setopt(g_dtp, "ustackframes", g_opt_s);	if (opt_H) {		dprog_add(g_hold_init);		if (g_opt_s == NULL)			dprog_add(g_hold_times);		else			dprog_add(g_hold_histogram);	}	if (opt_C) {		dprog_add(g_ctnd_init);		if (g_opt_s == NULL)			dprog_add(g_ctnd_times);		else			dprog_add(g_ctnd_histogram);	}	if (opt_p) {		ulong_t pid;		char *end;		if (argc > 1) {			(void) fprintf(stderr, "%s: only one pid is allowed\n",			    g_pname);			usage();		}		errno = 0;		pid = strtoul(argv[0], &end, 10);		if (*end != '\0' || errno != 0 || (pid_t)pid != pid) {			(void) fprintf(stderr, "%s: invalid pid '%s'\n",			    g_pname, argv[0]);			usage();		}		if ((g_pr = dtrace_proc_grab(g_dtp, (pid_t)pid, 0)) == NULL)			dfatal(NULL);	} else {		if ((g_pr = dtrace_proc_create(g_dtp, argv[0], argv)) == NULL)			dfatal(NULL);	}	dprog_compile();	(void) sigemptyset(&act.sa_mask);	act.sa_flags = 0;	act.sa_handler = intr;	(void) sigaction(SIGINT, &act, NULL);	(void) sigaction(SIGTERM, &act, NULL);	if (dtrace_setopt(g_dtp, "aggsize", "128k") == -1)		dfatal("failed to set 'aggsize'");	if (dtrace_setopt(g_dtp, "aggrate", "10sec") == -1)		dfatal("failed to set 'aggrate'");	if (dtrace_go(g_dtp) != 0)		dfatal("dtrace_go()");	if (dtrace_getopt(g_dtp, "ustackframes", &g_nframes) != 0)		dfatal("failed to get 'ustackframes'");	dtrace_proc_continue(g_dtp, g_pr);	while (!done) {		(void) sleep(1);		(void) dtrace_status(g_dtp);		/* Done if the user hits control-C. */		if (g_intr)			done = 1;		if (prochandler(g_pr) == 1)			done = 1;		if (dtrace_aggregate_snap(g_dtp) != 0)			dfatal("failed to add to aggregate");	}	if (dtrace_aggregate_snap(g_dtp) != 0)		dfatal("failed to add to aggregate");	if (dtrace_aggregate_walk_valrevsorted(g_dtp,	    process_aggregate, NULL) != 0)		dfatal("failed to print aggregations");	dtrace_close(g_dtp);	return (0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -