From cc162ed413d79df06b67e1e69c43de72035324ec Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Fri, 19 Oct 2012 04:37:53 -0400 Subject: [PATCH] Internal performance measurement support code. The dt_perf provider implements a few probes that are used in performance (or more accurately put, overhead) measurements. It uses an ioctl() interface to trigger N-count interations of invoking probes through various mechanisms, and a probe to post the results back to userspace. This code also adds an SDT probe in the DTrace kernel support code, just to measure overhead for triggering trap based SDT probes. Signed-off-by: Kris Van Hees --- dtrace/dt_perf.h | 40 ++++++++++++ dtrace/dt_perf_dev.c | 150 +++++++++++++++++++++++++++++++++++++++++++ dtrace/dt_perf_mod.c | 62 ++++++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 dtrace/dt_perf.h create mode 100644 dtrace/dt_perf_dev.c create mode 100644 dtrace/dt_perf_mod.c diff --git a/dtrace/dt_perf.h b/dtrace/dt_perf.h new file mode 100644 index 000000000000..d84352eebcf2 --- /dev/null +++ b/dtrace/dt_perf.h @@ -0,0 +1,40 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2011 Oracle, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _DT_PERF_H_ +#define _DT_PERF_H_ + +extern void dt_perf_provide(void *, const dtrace_probedesc_t *); +extern int _dt_perf_enable(void *arg, dtrace_id_t, void *); +extern void _dt_perf_disable(void *arg, dtrace_id_t, void *); +extern void dt_perf_destroy(void *, dtrace_id_t, void *); + +extern dtrace_provider_id_t dt_perf_id; + +extern int dt_perf_dev_init(void); +extern void dt_perf_dev_exit(void); + +#endif /* _DT_PERF_H_ */ diff --git a/dtrace/dt_perf_dev.c b/dtrace/dt_perf_dev.c new file mode 100644 index 000000000000..36f9ca250a4d --- /dev/null +++ b/dtrace/dt_perf_dev.c @@ -0,0 +1,150 @@ +/* + * FILE: dt_pref_dev.c + * DESCRIPTION: DTrace Performance Test Probe: device file handling + * + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Copyright 2011 Oracle, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include +#include +#include +#include + +#include "dtrace.h" +#include "dtrace_dev.h" +#include "dt_perf.h" + +static dtrace_id_t invoke_pid = 0; +static dtrace_id_t result_pid = 0; +static int enabled = 0; + +void dt_perf_provide(void *arg, const dtrace_probedesc_t *desc) +{ + if (dtrace_probe_lookup(dt_perf_id, "dt_perf", NULL, "invoke") != 0) + return; + + invoke_pid = dtrace_probe_create(dt_perf_id, + "dt_perf", NULL, "invoke", 0, NULL); + result_pid = dtrace_probe_create(dt_perf_id, + "dt_perf", NULL, "result", 0, NULL); +} + +int _dt_perf_enable(void *arg, dtrace_id_t id, void *parg) +{ + enabled = 1; + + return 0; +} + +void _dt_perf_disable(void *arg, dtrace_id_t id, void *parg) +{ + enabled = 0; +} + +void dt_perf_destroy(void *arg, dtrace_id_t id, void *parg) +{ +} + +static long dt_perf_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + unsigned long i; + ktime_t tm0, tm1; + + if (!enabled) + return -EAGAIN; + + switch (cmd) { + case _IOW(1, 1, int): + tm0 = dtrace_gethrtime(); + for (i = 0; i < arg; i++) + dtrace_probe(invoke_pid, cmd, arg, 2, 3, 4); + + tm1 = dtrace_gethrtime(); + tm1.tv64 -= tm0.tv64; + + dtrace_probe(result_pid, cmd, arg, tm1.tv64, tm1.tv64 >> 32, 0); + break; + + case _IOW(1, 2, int): { + extern void dtrace_sdt_perf(void); + + tm0 = dtrace_gethrtime(); + for (i = 0; i < arg; i++) + dtrace_sdt_perf(); + + tm1 = dtrace_gethrtime(); + tm1.tv64 -= tm0.tv64; + + dtrace_probe(result_pid, cmd, arg, tm1.tv64, tm1.tv64 >> 32, 0); + break; + } + + default: + return -EINVAL; + } + + return 0; +} + +static int dt_perf_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int dt_perf_close(struct inode *inode, struct file *file) +{ + return 0; +} + +static const struct file_operations dt_perf_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = dt_perf_ioctl, + .open = dt_perf_open, + .release = dt_perf_close, +}; + +static struct miscdevice dt_perf_dev = { + .minor = DT_DEV_DT_TEST_MINOR, + .name = "dt_perf", + .nodename = "dtrace/provider/dt_perf", + .fops = &dt_perf_fops, +}; + +int dt_perf_dev_init(void) +{ + int ret = 0; + + ret = misc_register(&dt_perf_dev); + if (ret) + pr_err("%s: Can't register misc device %d\n", + dt_perf_dev.name, dt_perf_dev.minor); + + return ret; +} + +void dt_perf_dev_exit(void) +{ + misc_deregister(&dt_perf_dev); +} diff --git a/dtrace/dt_perf_mod.c b/dtrace/dt_perf_mod.c new file mode 100644 index 000000000000..18285acfaacb --- /dev/null +++ b/dtrace/dt_perf_mod.c @@ -0,0 +1,62 @@ +/* + * FILE: dt_perf_mod.c + * DESCRIPTION: DTrace Performance Test Probe: module handling + * + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Copyright 2011 Oracle, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include + +#include "dtrace.h" +#include "dtrace_dev.h" +#include "dt_perf.h" + +MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)"); +MODULE_DESCRIPTION("DTrace Performance Test Probe"); +MODULE_VERSION("v0.1"); +MODULE_LICENSE("CDDL"); + +static const dtrace_pattr_t dt_perf_attr = { +{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON }, +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, +{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON }, +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, +}; + +DT_PROVIDER_POPS(dt_perf) + +static dtrace_pops_t dt_perf_pops = { + dt_perf_provide, + NULL, + dt_perf_enable, + dt_perf_disable, + NULL, + NULL, + NULL, + NULL, + NULL, + dt_perf_destroy +}; + +DT_PROVIDER_MODULE(dt_perf, DTRACE_PRIV_USER) -- 2.50.1