Example #1
0
int
dtrace_status(dtrace_hdl_t *dtp)
{
	int gen = dtp->dt_statusgen;
	dtrace_optval_t interval = dtp->dt_options[DTRACEOPT_STATUSRATE];
	hrtime_t now = gethrtime();

	if (!dtp->dt_active)
		return (DTRACE_STATUS_NONE);

	if (dtp->dt_stopped)
		return (DTRACE_STATUS_STOPPED);

	if (dtp->dt_laststatus != 0) {
		if (now - dtp->dt_laststatus < interval)
			return (DTRACE_STATUS_NONE);

		dtp->dt_laststatus += interval;
	} else {
		dtp->dt_laststatus = now;
	}

	if (dt_ioctl(dtp, DTRACEIOC_STATUS, &dtp->dt_status[gen]) == -1)
		return (dt_set_errno(dtp, errno));

	dtp->dt_statusgen ^= 1;

	if (dt_handle_status(dtp, &dtp->dt_status[dtp->dt_statusgen],
	    &dtp->dt_status[gen]) == -1)
		return (-1);

	if (dtp->dt_status[gen].dtst_exiting) {
		if (!dtp->dt_stopped)
			(void) dtrace_stop(dtp);

		return (DTRACE_STATUS_EXITED);
	}

	if (dtp->dt_status[gen].dtst_filled == 0)
		return (DTRACE_STATUS_OKAY);

	if (dtp->dt_options[DTRACEOPT_BUFPOLICY] != DTRACEOPT_BUFPOLICY_FILL)
		return (DTRACE_STATUS_OKAY);

	if (!dtp->dt_stopped) {
		if (dtrace_stop(dtp) == -1)
			return (-1);
	}

	return (DTRACE_STATUS_FILLED);
}
Example #2
0
int main( void ) {
    int err;
    dtrace_hdl_t * dh = dtrace_open(DTRACE_VERSION, 0, &err);
    
    if (dh == NULL) {
        printf("Cannot open dtrace library: %s\n", dtrace_errmsg(dh, err));
        return -1;
    }
    
    // Set a few necessary options
    dtrace_setopt(dh, "strsize", "4096");
    dtrace_setopt(dh, "bufsize", "4m");
    
    // Compile my program
    const char * script = "syscall::*exit*:entry { printf(\"%s %d\\n\", execname, curpsinfo->pr_pid); }";
    dtrace_prog_t *prog = dtrace_program_strcompile(dh, script, DTRACE_PROBESPEC_NAME, 0, 0, NULL);
    if( prog == NULL ) {
        printf("Cannot compile program: %s\n", dtrace_errmsg(dh, err));
        return -1;
    }
    
    // Add buffered output handler, as this is the only way I can get data out of Dtrace?
    if (dtrace_handle_buffered(dh, dtrace_dcmdbuffered, NULL) == -1) {
        printf("Couldn't add buffered handler");
        return -1;
    }

    dtrace_proginfo_t info;
    if( dtrace_program_exec(dh, prog, &info) == -1 ) {
        printf("Cannot exec program: %s\n", dtrace_errmsg(dh, err));
        return -1;
    }
    
    if( dtrace_go(dh) == -1 ) {
        printf("Cannot go: %s\n", dtrace_errmsg(NULL, err));
        return -1;
    }
    
    while(1) {
        dtrace_sleep(dh);
        switch (dtrace_work(dh, NULL, chew, chewrec, NULL)) {
            case DTRACE_WORKSTATUS_DONE:
                if (dtrace_stop(dh) == -1)
                    printf("couldn't stop tracing");
                break;
                break;
            case DTRACE_WORKSTATUS_OKAY:
                break;
            case DTRACE_WORKSTATUS_ERROR:
                printf("WARNING: DTRACE_WORKSTATUS_ERROR!\n");
                break;
            default:
                printf("Unknown return value from dtrace_work()\n");
        }
    }
    
    dtrace_close(dh);
    return 0;
}
Example #3
0
int
main(int argc, char **argv)
{
	int err;
	int opt_C = 0, opt_H = 0, opt_p = 0, opt_v = 0;
	char c, *p, *end;
	struct sigaction act;
	int done = 0;

	g_pname = basename(argv[0]);
	argv[0] = g_pname; /* rewrite argv[0] for getopt errors */

	while ((c = getopt(argc, argv, PLOCKSTAT_OPTSTR)) != EOF) {
		switch (c) {
		case 'n':
			errno = 0;
			g_nent = strtoul(optarg, &end, 10);
			if (*end != '\0' || errno != 0) {
				(void) fprintf(stderr, "%s: invalid count "
				    "'%s'\n", g_pname, optarg);
				usage();
			}
			break;

		case 'p':
			opt_p = 1;
			break;

		case 'v':
			opt_v = 1;
			break;

		case 'A':
			opt_C = opt_H = 1;
			break;

		case 'C':
			opt_C = 1;
			break;

		case 'H':
			opt_H = 1;
			break;

		case 'V':
			g_opt_V = 1;
			break;

		default:
			if (strchr(PLOCKSTAT_OPTSTR, c) == NULL)
				usage();
		}
	}

	/*
	 * We need a command or at least one pid.
	 */
	if (argc == optind)
		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));

	/*
	 * The longest string we trace is 23 bytes long -- so 32 is plenty.
	 */
	if (dtrace_setopt(g_dtp, "strsize", "32") == -1)
		dfatal("failed to set 'strsize'");

	/*
	 * 1k should be more than enough for all trace() and printa() actions.
	 */
	if (dtrace_setopt(g_dtp, "bufsize", "1k") == -1)
		dfatal("failed to set 'bufsize'");

	/*
	 * The table we produce has the hottest locks at the top.
	 */
	if (dtrace_setopt(g_dtp, "aggsortrev", NULL) == -1)
		dfatal("failed to set 'aggsortrev'");

	/*
	 * These are two reasonable defaults which should suffice.
	 */
	if (dtrace_setopt(g_dtp, "aggsize", "256k") == -1)
		dfatal("failed to set 'aggsize'");
	if (dtrace_setopt(g_dtp, "aggrate", "1sec") == -1)
		dfatal("failed to set 'aggrate'");

	/*
	 * Take a second pass through to look for options that set options now
	 * that we have an open dtrace handle.
	 */
	optind = 1;
	while ((c = getopt(argc, argv, PLOCKSTAT_OPTSTR)) != EOF) {
		switch (c) {
		case 's':
			g_opt_s = 1;
			if (dtrace_setopt(g_dtp, "ustackframes", optarg) == -1)
				dfatal("failed to set 'ustackframes'");
			break;

		case 'x':
			if ((p = strchr(optarg, '=')) != NULL)
				*p++ = '\0';

			if (dtrace_setopt(g_dtp, optarg, p) != 0)
				dfatal("failed to set -x %s", optarg);
			break;

		case 'e':
			errno = 0;
			(void) strtoul(optarg, &end, 10);
			if (*optarg == '-' || *end != '\0' || errno != 0) {
				(void) fprintf(stderr, "%s: invalid timeout "
				    "'%s'\n", g_pname, optarg);
				usage();
			}

			/*
			 * Construct a DTrace enabling that will exit after
			 * the specified number of seconds.
			 */
			dprog_add("BEGIN\n{\n\tend = timestamp + ");
			dprog_add(optarg);
			dprog_add(" * 1000000000;\n}\n");
			dprog_add("tick-10hz\n/timestamp >= end/\n");
			dprog_add("{\n\texit(0);\n}\n");
			break;
		}
	}

	argc -= optind;
	argv += optind;

	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;

		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();

	if (dtrace_handle_proc(g_dtp, &prochandler, NULL) == -1)
		dfatal("failed to establish proc handler");

	(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_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);

	if (opt_v)
		(void) printf("%s: tracing enabled for pid %d\n", g_pname,
		    (int)Pstatus(g_pr)->pr_pid);

	do {
		if (!g_intr && !done)
			dtrace_sleep(g_dtp);

		if (done || g_intr || g_exited) {
			done = 1;
			if (dtrace_stop(g_dtp) == -1)
				dfatal("couldn't stop tracing");
		}

		switch (dtrace_work(g_dtp, stdout, NULL, chewrec, NULL)) {
		case DTRACE_WORKSTATUS_DONE:
			done = 1;
			break;
		case DTRACE_WORKSTATUS_OKAY:
			break;
		default:
			dfatal("processing aborted");
		}

	} while (!done);

	dtrace_close(g_dtp);

	return (0);
}