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

📄 lockstat.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 3 页
字号:
			break;		case 'R':			g_rates = 1;			break;		case 'p':			g_pflag = 1;			break;		case 'P':			g_Pflag = 1;			break;		case 'o':			if ((out = fopen(optarg, "w")) == NULL)				fail(1, "error opening file");			break;		case 'V':			g_Vflag = 1;			break;		default:			usage();		}	}	if (filt != NULL) {		predicate_add(&g_predicate, filt, NULL, 0);		filter_destroy(&filt);	}	if (ifilt != NULL) {		predicate_add(&g_ipredicate, ifilt, NULL, 0);		filter_destroy(&ifilt);	}	argc -= optind;	argv += optind;	if (g_recsize == 0) {		if (g_gflag) {			g_stkdepth = LS_MAX_STACK_DEPTH;			g_recsize = LS_STACK(g_stkdepth);		} else {			g_recsize = LS_TIME;		}	}	if (g_gflag && g_recsize <= LS_STACK(0))		fail(0, "'-g' requires at least '-s 1' data gathering");	/*	 * Make sure the alignment is reasonable	 */	g_recsize = -(-g_recsize & -sizeof (uint64_t));	for (i = 0; i < LS_MAX_EVENTS; i++) {		/*		 * If no events were specified, enable -C.		 */		if (!events_specified && g_event_info[i].ev_type == 'C')			g_enabled[i] = 1;	}	for (i = 0; i < LS_MAX_EVENTS; i++) {		if (g_enabled[i])			dprog_addevent(i);	}	/*	 * Make sure there is a child command to execute	 */	if (argc <= 0)		usage();	data_buf_size = (g_nrecs + 1) * g_recsize;	/*	 * By default, we set our aggregation size to be the number of records	 * times a slop factor.	 */	(void) sprintf(data_buf_str, "%ld", (long)(g_nrecs * 512));	if (!g_tracing) {		if (dtrace_setopt(g_dtp, "bufsize", "4k") == -1)			dfail("failed to set 'bufsize'");		if (dtrace_setopt(g_dtp, "aggsize", data_buf_str) == -1)			dfail("failed to set 'aggsize'");	} else {		if (dtrace_setopt(g_dtp, "bufsize", data_buf_str) == -1)			dfail("failed to set 'bufsize'");	}	if (dtrace_setopt(g_dtp, "statusrate", "10sec") == -1)		dfail("failed to set 'statusrate'");	if ((data_buf = memalign(sizeof (uint64_t), data_buf_size)) == NULL)		fail(1, "Memory allocation failed");	dprog_compile();	status_init();	g_elapsed = -gethrtime();	/*	 * Spawn the specified command and wait for it to complete.	 */	child = fork();	if (child == -1)		fail(1, "cannot fork");	if (child == 0) {		(void) dtrace_close(g_dtp);		(void) execvp(argv[0], &argv[0]);		exec_errno = errno;		exit(127);	}	while (waitpid(child, &status, WEXITED) != child)		status_check();	g_elapsed += gethrtime();	if (WIFEXITED(status)) {		if (WEXITSTATUS(status) != 0) {			if (exec_errno != 0) {				errno = exec_errno;				fail(1, "could not execute %s", argv[0]);			}			(void) fprintf(stderr,			    "lockstat: warning: %s exited with code %d\n",				argv[0], WEXITSTATUS(status));		}	} else {		(void) fprintf(stderr,		    "lockstat: warning: %s died on signal %d\n",			argv[0], WTERMSIG(status));	}	if (dtrace_stop(g_dtp) == -1)		dfail("failed to stop dtrace");	/*	 * Read out the DTrace data.	 */	g_nrecs_used = process_data(out, data_buf);	if (g_nrecs_used >= g_nrecs || g_dropped)		(void) fprintf(stderr, "lockstat: warning: "		    "ran out of data records (use -n for more)\n");	/* LINTED - alignment */	for (i = 0, lsp = (lsrec_t *)data_buf; i < g_nrecs_used; i++,	    /* LINTED - alignment */	    lsp = (lsrec_t *)((char *)lsp + g_recsize)) {		ev_count[lsp->ls_event] += lsp->ls_count;		ev_time[lsp->ls_event] += lsp->ls_time;	}	/*	 * If -g was specified, convert stacks into individual records.	 */	if (g_gflag) {		lsrec_t *newlsp, *oldlsp;		newlsp = memalign(sizeof (uint64_t),		    g_nrecs_used * LS_TIME * (g_stkdepth + 1));		if (newlsp == NULL)			fail(1, "Cannot allocate space for -g processing");		lsp = newlsp;		/* LINTED - alignment */		for (i = 0, oldlsp = (lsrec_t *)data_buf; i < g_nrecs_used; i++,		    /* LINTED - alignment */		    oldlsp = (lsrec_t *)((char *)oldlsp + g_recsize)) {			int fr;			int caller_in_stack = 0;			if (oldlsp->ls_count == 0)				continue;			for (fr = 0; fr < g_stkdepth; fr++) {				if (oldlsp->ls_stack[fr] == 0)					break;				if (oldlsp->ls_stack[fr] == oldlsp->ls_caller)					caller_in_stack = 1;				bcopy(oldlsp, lsp, LS_TIME);				lsp->ls_caller = oldlsp->ls_stack[fr];				/* LINTED - alignment */				lsp = (lsrec_t *)((char *)lsp + LS_TIME);			}			if (!caller_in_stack) {				bcopy(oldlsp, lsp, LS_TIME);				/* LINTED - alignment */				lsp = (lsrec_t *)((char *)lsp + LS_TIME);			}		}		g_nrecs = g_nrecs_used =		    ((uintptr_t)lsp - (uintptr_t)newlsp) / LS_TIME;		g_recsize = LS_TIME;		g_stkdepth = 0;		free(data_buf);		data_buf = (char *)newlsp;	}	if ((sort_buf = calloc(2 * (g_nrecs + 1),	    sizeof (void *))) == NULL)		fail(1, "Sort buffer allocation failed");	merge_buf = sort_buf + (g_nrecs + 1);	/*	 * Build the sort buffer, discarding zero-count records along the way.	 */	/* LINTED - alignment */	for (i = 0, lsp = (lsrec_t *)data_buf; i < g_nrecs_used; i++,	    /* LINTED - alignment */	    lsp = (lsrec_t *)((char *)lsp + g_recsize)) {		if (lsp->ls_count == 0)			lsp->ls_event = LS_MAX_EVENTS;		sort_buf[i] = lsp;	}	if (g_nrecs_used == 0)		exit(0);	/*	 * Add a sentinel after the last record	 */	sort_buf[i] = lsp;	lsp->ls_event = LS_MAX_EVENTS;	if (g_tracing) {		report_trace(out, sort_buf);		return (0);	}	/*	 * Application of -g may have resulted in multiple records	 * with the same signature; coalesce them.	 */	if (g_gflag) {		mergesort(lockcmp, sort_buf, merge_buf, g_nrecs_used);		coalesce(lockcmp, sort_buf, g_nrecs_used);	}	/*	 * Coalesce locks within the same symbol if -c option specified.	 * Coalesce PCs within the same function if -k option specified.	 */	if (g_cflag || g_kflag) {		for (i = 0; i < g_nrecs_used; i++) {			int fr;			lsp = sort_buf[i];			if (g_cflag)				coalesce_symbol(&lsp->ls_lock);			if (g_kflag) {				for (fr = 0; fr < g_stkdepth; fr++)					coalesce_symbol(&lsp->ls_stack[fr]);				coalesce_symbol(&lsp->ls_caller);			}		}		mergesort(lockcmp, sort_buf, merge_buf, g_nrecs_used);		coalesce(lockcmp, sort_buf, g_nrecs_used);	}	/*	 * Coalesce callers if -w option specified	 */	if (g_wflag) {		mergesort(lock_and_count_cmp_anywhere,		    sort_buf, merge_buf, g_nrecs_used);		coalesce(lockcmp_anywhere, sort_buf, g_nrecs_used);	}	/*	 * Coalesce locks if -W option specified	 */	if (g_Wflag) {		mergesort(site_and_count_cmp_anylock,		    sort_buf, merge_buf, g_nrecs_used);		coalesce(sitecmp_anylock, sort_buf, g_nrecs_used);	}	/*	 * Sort data by contention count (ls_count) or total time (ls_time),	 * depending on g_Pflag.  Override g_Pflag if time wasn't measured.	 */	if (g_recsize < LS_TIME)		g_Pflag = 0;	if (g_Pflag)		mergesort(timecmp, sort_buf, merge_buf, g_nrecs_used);	else		mergesort(countcmp, sort_buf, merge_buf, g_nrecs_used);	/*	 * Display data by event type	 */	first = &sort_buf[0];	while ((event = (*first)->ls_event) < LS_MAX_EVENTS) {		current = first;		while ((lsp = *current)->ls_event == event)			current++;		report_stats(out, first, current - first, ev_count[event],		    ev_time[event]);		first = current;	}	return (0);}static char *format_symbol(char *buf, uintptr_t addr, int show_size){	uintptr_t symoff;	char *symname;	size_t symsize;	symname = addr_to_sym(addr, &symoff, &symsize);	if (show_size && symoff == 0)		(void) sprintf(buf, "%s[%ld]", symname, (long)symsize);	else if (symoff == 0)		(void) sprintf(buf, "%s", symname);	else if (symoff < 16 && bcmp(symname, "cpu[", 4) == 0)	/* CPU+PIL */		(void) sprintf(buf, "%s+%ld", symname, (long)symoff);	else if (symoff <= symsize || (symoff < 256 && addr != symoff))		(void) sprintf(buf, "%s+0x%llx", symname,		    (unsigned long long)symoff);	else		(void) sprintf(buf, "0x%llx", (unsigned long long)addr);	return (buf);}static voidreport_stats(FILE *out, lsrec_t **sort_buf, size_t nrecs, uint64_t total_count,	uint64_t total_time){	uint32_t event = sort_buf[0]->ls_event;	lsrec_t *lsp;	double ptotal = 0.0;	double percent;	int i, j, fr;	int displayed;	int first_bin, last_bin, max_bin_count, total_bin_count;	int rectype;	char buf[256];	char lhdr[80], chdr[80];	rectype = g_recsize;	if (g_topn == 0) {		(void) fprintf(out, "%20llu %s\n",		    g_rates == 0 ? total_count :		    ((unsigned long long)total_count * NANOSEC) / g_elapsed,		    g_event_info[event].ev_desc);		return;	}	(void) sprintf(lhdr, "%s%s",	    g_Wflag ? "Hottest " : "", g_event_info[event].ev_lhdr);	(void) sprintf(chdr, "%s%s",	    g_wflag ? "Hottest " : "", "Caller");	if (!g_pflag)		(void) fprintf(out,		    "\n%s: %.0f events in %.3f seconds (%.0f events/sec)\n\n",		    g_event_info[event].ev_desc, (double)total_count,		    (double)g_elapsed / NANOSEC,		    (double)total_count * NANOSEC / g_elapsed);	if (!g_pflag && rectype < LS_HIST) {		(void) sprintf(buf, "%s", g_event_info[event].ev_units);		(void) fprintf(out, "%5s %4s %4s %4s %8s %-22s %-24s\n",		    g_rates ? "ops/s" : "Count",		    g_gflag ? "genr" : "indv",		    "cuml", "rcnt", rectype >= LS_TIME ? buf : "", lhdr, chdr);		(void) fprintf(out, "---------------------------------"		    "----------------------------------------------\n");	}	displayed = 0;	for (i = 0; i < nrecs; i++) {		lsp = sort_buf[i];		if (displayed++ >= g_topn)			break;		if (g_pflag) {			int j;			(void) fprintf(out, "%u %u",			    lsp->ls_event, lsp->ls_count);			(void) fprintf(out, " %s",			    format_symbol(buf, lsp->ls_lock, g_cflag));			(void) fprintf(out, " %s",			    format_symbol(buf, lsp->ls_caller, 0));			(void) fprintf(out, " %f",			    (double)lsp->ls_refcnt / lsp->ls_count);			if (rectype >= LS_TIME)				(void) fprintf(out, " %llu",				    (unsigned long long)lsp->ls_time);			if (rectype >= LS_HIST) {				for (j = 0; j < 64; j++)					(void) fprintf(out, " %u",					    lsp->ls_hist[j]);			}			for (j = 0; j < LS_MAX_STACK_DEPTH; j++) {				if (rectype <= LS_STACK(j) ||				    lsp->ls_stack[j] == 0)					break;				(void) fprintf(out, " %s",				    format_symbol(buf, lsp->ls_stack[j], 0));			}			(void) fprintf(out, "\n");			continue;		}		if (rectype >= LS_HIST) {			(void) fprintf(out, "---------------------------------"			    "----------------------------------------------\n");			(void) sprintf(buf, "%s",			    g_event_info[event].ev_units);			(void) fprintf(out, "%5s %4s %4s %4s %8s %-22s %-24s\n",			    g_rates ? "ops/s" : "Count",			    g_gflag ? "genr" : "indv",			    "cuml", "rcnt", buf, lhdr, chdr);		}		if (g_Pflag && total_time != 0)			percent = (lsp->ls_time * 100.00) / total_time;		else			percent = (lsp->ls_count * 100.00) / total_count;		ptotal += percent;		if (rectype >= LS_TIME)			(void) sprintf(buf, "%llu",			    (unsigned long long)(lsp->ls_time / lsp->ls_count));		else			buf[0] = '\0';		(void) fprintf(out, "%5llu ",		    g_rates == 0 ? lsp->ls_count :		    ((uint64_t)lsp->ls_count * NANOSEC) / g_elapsed);		(void) fprintf(out, "%3.0f%% ", percent);		if (g_gflag)			(void) fprintf(out, "---- ");		else			(void) fprintf(out, "%3.0f%% ", ptotal);		(void) fprintf(out, "%4.2f %8s ",		    (double)lsp->ls_refcnt / lsp->ls_count, buf);		(void) fprintf(out, "%-22s ",		    format_symbol(buf, lsp->ls_lock, g_cflag));		(void) fprintf(out, "%-24s\n",		    format_symbol(buf, lsp->ls_caller, 0));		if (rectype < LS_HIST)			continue;		(void) fprintf(out, "\n");		(void) fprintf(out, "%10s %31s %-9s %-24s\n",			g_event_info[event].ev_units,			"------ Time Distribution ------",			g_rates ? "ops/s" : "count",			rectype > LS_STACK(0) ? "Stack" : "");		first_bin = 0;		while (lsp->ls_hist[first_bin] == 0)			first_bin++;		last_bin = 63;		while (lsp->ls_hist[last_bin] == 0)			last_bin--;		max_bin_count = 0;		total_bin_count = 0;		for (j = first_bin; j <= last_bin; j++) {			total_bin_count += lsp->ls_hist[j];			if (lsp->ls_hist[j] > max_bin_count)				max_bin_count = lsp->ls_hist[j];		}		/*		 * If we went a few frames below the caller, ignore them		 */		for (fr = 3; fr > 0; fr--)			if (lsp->ls_stack[fr] == lsp->ls_caller)				break;		for (j = first_bin; j <= last_bin; j++) {			uint_t depth = (lsp->ls_hist[j] * 30) / total_bin_count;			(void) fprintf(out, "%10llu |%s%s %-9u ",			    1ULL << j,			    "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" + 30 - depth,			    "                              " + depth,			    g_rates == 0 ? lsp->ls_hist[j] :			    (uint_t)(((uint64_t)lsp->ls_hist[j] * NANOSEC) /			    g_elapsed));			if (rectype <= LS_STACK(fr) || lsp->ls_stack[fr] == 0) {				(void) fprintf(out, "\n");				continue;			}			(void) fprintf(out, "%-24s\n",			    format_symbol(buf, lsp->ls_stack[fr], 0));			fr++;		}		while (rectype > LS_STACK(fr) && lsp->ls_stack[fr] != 0) {			(void) fprintf(out, "%15s %-36s %-24s\n", "", "",			    format_symbol(buf, lsp->ls_stack[fr], 0));			fr++;		}	}	if (!g_pflag)		(void) fprintf(out, "---------------------------------"		    "----------------------------------------------\n");	(void) fflush(out);}static voidreport_trace(FILE *out, lsrec_t **sort_buf){	lsrec_t *lsp;	int i, fr;	int rectype;	char buf[256], buf2[256];	rectype = g_recsize;	if (!g_pflag) {		(void) fprintf(out, "%5s  %7s  %11s  %-24s  %-24s\n",		    "Event", "Time", "Owner", "Lock", "Caller");		(void) fprintf(out, "---------------------------------"		    "----------------------------------------------\n");	}	for (i = 0; i < g_nrecs_used; i++) {		lsp = sort_buf[i];		if (lsp->ls_event >= LS_MAX_EVENTS || lsp->ls_count == 0)			continue;		(void) fprintf(out, "%2d  %10llu  %11p  %-24s  %-24s\n",		    lsp->ls_event, (unsigned long long)lsp->ls_time,		    (void *)lsp->ls_next,		    format_symbol(buf, lsp->ls_lock, 0),		    format_symbol(buf2, lsp->ls_caller, 0));		if (rectype <= LS_STACK(0))			continue;		/*		 * If we went a few frames below the caller, ignore them		 */		for (fr = 3; fr > 0; fr--)			if (lsp->ls_stack[fr] == lsp->ls_caller)				break;		while (rectype > LS_STACK(fr) && lsp->ls_stack[fr] != 0) {			(void) fprintf(out, "%53s  %-24s\n", "",			    format_symbol(buf, lsp->ls_stack[fr], 0));			fr++;		}		(void) fprintf(out, "\n");	}	(void) fflush(out);}

⌨️ 快捷键说明

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