=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/cddl/contrib/opensolaris/cmd/dtrace/test/cmd/jdtrace/exception.lst 2008-04-25 16:56:23.000000000 +1000
+++ /u/p4/dtrace/src/cddl/contrib/opensolaris/cmd/dtrace/test/cmd/jdtrace/exception.lst 2008-05-24 13:30:44.000000000 +1000
@@ -23,7 +23,7 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
+# ident "%Z%%M% %I% %E% SMI"
# Exception list: names tests that are bypassed when running in Java
# mode (relative to /opt/SUNWdtrt/tst)
@@ -49,6 +49,7 @@
common/usdt/tst.dlclose3.ksh
common/usdt/tst.eliminate.ksh
common/usdt/tst.enabled.ksh
+common/usdt/tst.enabled2.ksh
common/usdt/tst.entryreturn.ksh
common/usdt/tst.fork.ksh
common/usdt/tst.header.ksh
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/cddl/contrib/opensolaris/cmd/dtrace/test/cmd/scripts/dtest.pl 2008-04-26 13:18:38.000000000 +1000
+++ /u/p4/dtrace/src/cddl/contrib/opensolaris/cmd/dtrace/test/cmd/scripts/dtest.pl 2008-05-24 13:28:48.000000000 +1000
@@ -40,6 +40,7 @@
$USAGE = "Usage: $PNAME [-abfghjlnqs] [-d dir] [-i isa] "
. "[-x opt[=arg]] [file | dir ...]\n";
($MACH = `uname -p`) =~ s/\W*\n//;
+($PLATFORM = `uname -i`) =~ s/\W*\n//;
@dtrace_argv = ();
@@ -215,17 +216,17 @@
}
#
-# Iterate over the set of test files specified on the command-line or by
-# a find on "$defdir/common" and "$defdir/$MACH" and execute each one.
-# If the test file is executable, we fork and exec it. If the test is a
-# .ksh file, we run it with $ksh_path. Otherwise we run dtrace -s on it.
-# If the file is named tst.* we assume it should return exit status 0.
-# If the file is named err.* we assume it should return exit status 1.
-# If the file is named err.D_[A-Z0-9]+[.*].d we use dtrace -xerrtags and
-# examine stderr to ensure that a matching error tag was produced.
-# If the file is named drp.[A-Z0-9]+[.*].d we use dtrace -xdroptags and
-# examine stderr to ensure that a matching drop tag was produced.
-# If any *.out or *.err files are found we perform output comparisons.
+# Iterate over the set of test files specified on the command-line or by a find
+# on "$defdir/common", "$defdir/$MACH" and "$defdir/$PLATFORM" and execute each
+# one. If the test file is executable, we fork and exec it. If the test is a
+# .ksh file, we run it with $ksh_path. Otherwise we run dtrace -s on it. If
+# the file is named tst.* we assume it should return exit status 0. If the
+# file is named err.* we assume it should return exit status 1. If the file is
+# named err.D_[A-Z0-9]+[.*].d we use dtrace -xerrtags and examine stderr to
+# ensure that a matching error tag was produced. If the file is named
+# drp.[A-Z0-9]+[.*].d we use dtrace -xdroptags and examine stderr to ensure
+# that a matching drop tag was produced. If any *.out or *.err files are found
+# we perform output comparisons.
#
# run_tests takes two arguments: The first is the pathname of the dtrace
# command to invoke when running the tests. The second is the pathname
@@ -548,6 +549,7 @@
find(\&wanted, "$defdir/common") if (scalar(@ARGV) == 0);
find(\&wanted, "$defdir/$MACH") if (scalar(@ARGV) == 0);
+find(\&wanted, "$defdir/$PLATFORM") if (scalar(@ARGV) == 0);
die $USAGE if (scalar(@files) == 0);
$dtrace_path = '/usr/sbin/dtrace';
=====================================================================
--ditto--
---------------------------------------------------------------------
New file: src/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/usdt/tst.enabled2.ksh
---------------------------------------------------------------------
#
# 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 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
#
# This test is primarily intended to verify a fix for SPARC, but there's no
# harm in running it on other platforms. Here, we verify that is-enabled
# probes don't interfere with return values from previously invoked functions.
#
if [ $# != 1 ]; then
echo expected one argument: '<'dtrace-path'>'
exit 2
fi
dtrace=$1
DIR=/var/tmp/dtest.$$
mkdir $DIR
cd $DIR
cat > prov.d < test.c <
#include "prov.h"
int
foo(void)
{
return (24);
}
int
main(int argc, char **argv)
{
int a = foo();
if (TEST_PROV_GO_ENABLED()) {
TEST_PROV_GO();
}
(void) printf("%d %d %d\n", a, a, a);
return (0);
}
EOF
cc -c -xO2 test.c
if [ $? -ne 0 ]; then
print -u2 "failed to compile test.c"
exit 1
fi
$dtrace -G -32 -s prov.d test.o
if [ $? -ne 0 ]; then
print -u2 "failed to create DOF"
exit 1
fi
cc -o test test.o prov.o
if [ $? -ne 0 ]; then
print -u2 "failed to link final executable"
exit 1
fi
script()
{
./test
$dtrace -c ./test -qs /dev/stdin <'
exit 2
fi
#
# Do not fail the test in a domU
#
if [ ! -c /dev/xen/privcmd ]; then
exit 0
fi
dtrace=$1
script()
{
$dtrace -qs /dev/stdin <on++;
}
xdt:sched::off-cpu
/arg1 == 0 && self->on/
{
self->off++;
}
xdt:sched::off-cpu
/self->on > 50 && self->off > 50/
{
exit(0);
}
profile:::tick-1sec
/n++ > 10/
{
exit(1);
}
EOF
}
script
status=$?
exit $status
=====================================================================
--ditto--
---------------------------------------------------------------------
New file: src/cddl/contrib/opensolaris/cmd/dtrace/test/tst/i86xpv/xdt/tst.hvmenable.ksh
---------------------------------------------------------------------
#
# 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 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
#
# ASSERTION: HVM probes should enable successfully.
#
if [ $# != 1 ]; then
echo expected one argument: '<'dtrace-path'>'
exit 2
fi
#
# Do not fail the test in a domU
#
if [ ! -c /dev/xen/privcmd ]; then
exit 0
fi
dtrace=$1
script()
{
$dtrace -qs /dev/stdin <'
exit 2
fi
#
# Do not fail the test in a domU
#
if [ ! -c /dev/xen/privcmd ]; then
exit 0
fi
dtrace=$1
script()
{
$dtrace -qs /dev/stdin <'
exit 2
fi
#
# do not fail test in a domU
#
if [ ! -c /dev/xen/privcmd ]; then
exit 0
fi
dtrace=$1
outf=/tmp/sched.args.$$
script()
{
$dtrace -c '/usr/bin/sleep 10' -o $outf -qs /dev/stdin < 1) {
for (pcpu = p[1]; pcpu <= p[2];\
pcpu++) {
cpumap[domid, vcpu,
pcpu] = 1
}
} else {
cpumap[domid, vcpu,
affinity[i]] = 1
}
}
}
}
}
/^$/ { next }
/wake/ {
if (vcpumap[$1, $2]) {
next
} else {
print "error: " $0
exit 1
}
}
{
if (cpumap[$1, $2, "any"] || cpumap[$1, $2, $3]) {
next
} else {
print "error: " $0
exit 1
}
}
' $outf
}
script
status=$?
if [ $status == 0 ]; then
validate
status=$?
fi
rm $outf
exit $status
=====================================================================
--ditto--
---------------------------------------------------------------------
New file: src/cddl/contrib/opensolaris/cmd/dtrace/test/tst/i86xpv/xdt/tst.schedenable.ksh
---------------------------------------------------------------------
#
# 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 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
#
# ASSERTION: Sched probes should enable successfully.
#
if [ $# != 1 ]; then
echo expected one argument: '<'dtrace-path'>'
exit 2
fi
#
# do not fail test in a domU
#
if [ ! -c /dev/xen/privcmd ]; then
exit 0
fi
dtrace=$1
script()
{
$dtrace -qs /dev/stdin <(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c 2008-04-26 13:18:38.000000000 +1000
+++ /u/p4/dtrace/src/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c 2008-05-24 13:28:58.000000000 +1000
@@ -868,15 +868,19 @@
/*
* We may have already processed this object file in an earlier linker
* invocation. Check to see if the present instruction sequence matches
- * the one we would install.
+ * the one we would install below.
*/
if (isenabled) {
- if (ip[0] == DT_OP_CLR_O0)
+ if (ip[0] == DT_OP_NOP) {
+ (*off) += sizeof (ip[0]);
return (0);
+ }
} else {
if (DT_IS_RESTORE(ip[1])) {
- if (ip[0] == DT_OP_RET)
+ if (ip[0] == DT_OP_RET) {
+ (*off) += sizeof (ip[0]);
return (0);
+ }
} else if (DT_IS_MOV_O7(ip[1])) {
if (DT_IS_RETL(ip[0]))
return (0);
@@ -910,7 +914,17 @@
return (-1);
}
- ip[0] = DT_OP_CLR_O0;
+
+ /*
+ * On SPARC, we take advantage of the fact that the first
+ * argument shares the same register as for the return value.
+ * The macro handles the work of zeroing that register so we
+ * don't need to do anything special here. We instrument the
+ * instruction in the delay slot as we'll need to modify the
+ * return register after that instruction has been emulated.
+ */
+ ip[0] = DT_OP_NOP;
+ (*off) += sizeof (ip[0]);
} else {
/*
* If the call is followed by a restore, it's a tail call so
@@ -919,11 +933,16 @@
* so change the call to a retl-like instruction that returns
* to that register value + 8 (rather than the typical %o7 +
* 8); the delay slot instruction is left, but should have no
- * effect. Otherwise we change the call to be a nop. In the
- * first and the last case we adjust the offset to land on what
- * was once the delay slot of the call so we correctly get all
- * the arguments as they would have been passed in a normal
- * function call.
+ * effect. Otherwise we change the call to be a nop. We
+ * identify the subsequent instruction as the probe point in
+ * all but the leaf tail-call case to ensure that arguments to
+ * the probe are complete and consistent. An astute, though
+ * largely hypothetical, observer would note that there is the
+ * possibility of a false-positive probe firing if the function
+ * contained a branch to the instruction in the delay slot of
+ * the call. Fixing this would require significant in-kernel
+ * modifications, and isn't worth doing until we see it in the
+ * wild.
*/
if (DT_IS_RESTORE(ip[1])) {
ip[0] = DT_OP_RET;
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c 2008-04-26 13:18:38.000000000 +1000
+++ /u/p4/dtrace/src/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c 2008-05-24 13:29:08.000000000 +1000
@@ -115,8 +115,9 @@
#define DT_VERS_1_5 DT_VERSION_NUMBER(1, 5, 0)
#define DT_VERS_1_6 DT_VERSION_NUMBER(1, 6, 0)
#define DT_VERS_1_6_1 DT_VERSION_NUMBER(1, 6, 1)
-#define DT_VERS_LATEST DT_VERS_1_6_1
-#define DT_VERS_STRING "Sun D 1.6.1"
+#define DT_VERS_1_6_2 DT_VERSION_NUMBER(1, 6, 2)
+#define DT_VERS_LATEST DT_VERS_1_6_2
+#define DT_VERS_STRING "Sun D 1.6.2"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -130,6 +131,7 @@
DT_VERS_1_5, /* D API 1.5 Solaris Express 7/07 */
DT_VERS_1_6, /* D API 1.6 */
DT_VERS_1_6_1, /* D API 1.6.1 */
+ DT_VERS_1_6_2, /* D API 1.6.2 */
0
};
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/cddl/contrib/opensolaris/lib/libdtrace/common/dt_program.c 2008-04-26 13:18:38.000000000 +1000
+++ /u/p4/dtrace/src/cddl/contrib/opensolaris/lib/libdtrace/common/dt_program.c 2008-05-24 13:29:15.000000000 +1000
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -436,8 +436,13 @@
if (fprintf(infop->dthi_out, ");\n") < 0)
return (dt_set_errno(dtp, errno));
- if (fprintf(infop->dthi_out, "extern int "
- "__dtraceenabled_%s___%s(void);\n", infop->dthi_pfname, fname) < 0)
+ if (fprintf(infop->dthi_out,
+ "#ifndef\t__sparc\n"
+ "extern int __dtraceenabled_%s___%s(void);\n"
+ "#else\n"
+ "extern int __dtraceenabled_%s___%s(long);\n"
+ "#endif\n",
+ infop->dthi_pfname, fname, infop->dthi_pfname, fname) < 0)
return (dt_set_errno(dtp, errno));
return (0);
@@ -499,13 +504,20 @@
return (dt_set_errno(dtp, errno));
if (!infop->dthi_empty) {
- if (fprintf(infop->dthi_out, "#define\t%s_%s_ENABLED() \\\n",
- infop->dthi_pmname, mname) < 0)
- return (dt_set_errno(dtp, errno));
-
- if (fprintf(infop->dthi_out, "\t__dtraceenabled_%s___%s()\n",
+ if (fprintf(infop->dthi_out,
+ "#ifndef\t__sparc\n"
+ "#define\t%s_%s_ENABLED() \\\n"
+ "\t__dtraceenabled_%s___%s()\n"
+ "#else\n"
+ "#define\t%s_%s_ENABLED() \\\n"
+ "\t__dtraceenabled_%s___%s(0)\n"
+ "#endif\n",
+ infop->dthi_pmname, mname,
+ infop->dthi_pfname, fname,
+ infop->dthi_pmname, mname,
infop->dthi_pfname, fname) < 0)
return (dt_set_errno(dtp, errno));
+
} else {
if (fprintf(infop->dthi_out, "#define\t%s_%s_ENABLED() (0)\n",
infop->dthi_pmname, mname) < 0)
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/amd64/amd64/exception.S 2007-12-07 19:20:15.000000000 +1100
+++ /u/p4/dtrace/src/sys/amd64/amd64/exception.S 2008-04-19 16:58:08.000000000 +1000
@@ -37,6 +37,7 @@
#include "opt_atpic.h"
#include "opt_compat.h"
#include "opt_hwpmc_hooks.h"
+#include "opt_kdtrace.h"
#include
#include
@@ -44,6 +45,21 @@
#include "assym.s"
+#ifdef KDTRACE_HOOKS
+ .bss
+ .globl dtrace_invop_jump_addr
+ .align 8
+ .type dtrace_invop_jump_addr, @object
+ .size dtrace_invop_jump_addr, 8
+dtrace_invop_jump_addr:
+ .zero 8
+ .globl dtrace_invop_calltrap_addr
+ .align 8
+ .type dtrace_invop_calltrap_addr, @object
+ .size dtrace_invop_calltrap_addr, 8
+dtrace_invop_calltrap_addr:
+ .zero 8
+#endif
.text
#ifdef HWPMC_HOOKS
ENTRY(start_exceptions)
@@ -170,6 +186,30 @@
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
FAKE_MCOUNT(TF_RIP(%rsp))
+#ifdef KDTRACE_HOOKS
+ /*
+ * DTrace Function Boundary Trace (fbt) probes are triggered
+ * by int3 (0xcc) which causes the #BP (T_BPTFLT) breakpoint
+ * interrupt. For all other trap types, just handle them in
+ * the usual way.
+ */
+ cmpq $T_BPTFLT,TF_TRAPNO(%rsp)
+ jne calltrap
+
+ /* Check if there is no DTrace hook registered. */
+ cmpq $0,dtrace_invop_jump_addr
+ je calltrap
+
+ /*
+ * Set our jump address for the jump back in the event that
+ * the breakpoint wasn't caused by DTrace at all.
+ */
+ movq $calltrap, dtrace_invop_calltrap_addr(%rip)
+
+ /* Jump to the code hooked in by DTrace. */
+ movq dtrace_invop_jump_addr, %rax
+ jmpq *dtrace_invop_jump_addr
+#endif
.globl calltrap
.type calltrap,@function
calltrap:
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/amd64/amd64/local_apic.c 2008-03-16 21:58:02.000000000 +1100
+++ /u/p4/dtrace/src/sys/amd64/amd64/local_apic.c 2008-04-19 16:58:09.000000000 +1000
@@ -35,6 +35,7 @@
__FBSDID("$FreeBSD: src/sys/amd64/amd64/local_apic.c,v 1.44 2008/03/16 10:58:02 rwatson Exp $");
#include "opt_hwpmc_hooks.h"
+#include "opt_kdtrace.h"
#include "opt_ddb.h"
@@ -65,6 +66,11 @@
#include
#endif
+#ifdef KDTRACE_HOOKS
+#include
+cyclic_clock_func_t lapic_cyclic_clock_func[MAXCPU];
+#endif
+
/* Sanity checks on IDT vectors. */
CTASSERT(APIC_IO_INTS + APIC_NUM_IOINTS == APIC_TIMER_INT);
CTASSERT(APIC_TIMER_INT < APIC_LOCAL_INTS);
@@ -668,6 +674,17 @@
(*la->la_timer_count)++;
critical_enter();
+#ifdef KDTRACE_HOOKS
+ /*
+ * If the DTrace hooks are configured and a callback function
+ * has been registered, then call it to process the high speed
+ * timers.
+ */
+ int cpu = PCPU_GET(cpuid);
+ if (lapic_cyclic_clock_func[cpu] != NULL)
+ (*lapic_cyclic_clock_func[cpu])(frame);
+#endif
+
/* Fire hardclock at hz. */
la->la_hard_ticks += hz;
if (la->la_hard_ticks >= lapic_timer_hz) {
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/amd64/amd64/trap.c 2008-03-12 21:11:54.000000000 +1100
+++ /u/p4/dtrace/src/sys/amd64/amd64/trap.c 2008-04-19 16:58:12.000000000 +1000
@@ -49,6 +49,7 @@
#include "opt_hwpmc_hooks.h"
#include "opt_isa.h"
#include "opt_kdb.h"
+#include "opt_kdtrace.h"
#include "opt_ktrace.h"
#include
@@ -94,6 +95,26 @@
#endif
#include
+#ifdef KDTRACE_HOOKS
+#include
+
+/*
+ * This is a hook which is initialised by the dtrace module
+ * to handle traps which might occur during DTrace probe
+ * execution.
+ */
+dtrace_trap_func_t dtrace_trap_func;
+
+dtrace_doubletrap_func_t dtrace_doubletrap_func;
+
+/*
+ * This is a hook which is initialised by the systrace module
+ * when it is loaded. This keeps the DTrace syscall provider
+ * implementation opaque.
+ */
+systrace_probe_func_t systrace_probe_func;
+#endif
+
extern void trap(struct trapframe *frame);
extern void syscall(struct trapframe *frame);
void dblfault_handler(struct trapframe *frame);
@@ -199,6 +220,24 @@
goto out;
#endif
+#ifdef KDTRACE_HOOKS
+ /*
+ * A trap can occur while DTrace executes a probe. Before
+ * executing the probe, DTrace blocks re-scheduling and sets
+ * a flag in it's per-cpu flags to indicate that it doesn't
+ * want to fault. On returning from the the probe, the no-fault
+ * flag is cleared and finally re-scheduling is enabled.
+ *
+ * If the DTrace kernel module has registered a trap handler,
+ * call it and if it returns non-zero, assume that it has
+ * handled the trap and modified the trap frame so that this
+ * function can return normally.
+ */
+ if (dtrace_trap_func != NULL)
+ if ((*dtrace_trap_func)(frame, type))
+ goto out;
+#endif
+
if ((frame->tf_rflags & PSL_I) == 0) {
/*
* Buggy application or kernel code has disabled
@@ -730,6 +769,10 @@
void
dblfault_handler(struct trapframe *frame)
{
+#ifdef KDTRACE_HOOKS
+ if (dtrace_doubletrap_func != NULL)
+ (*dtrace_doubletrap_func)();
+#endif
printf("\nFatal double fault\n");
printf("rip = 0x%lx\n", frame->tf_rip);
printf("rsp = 0x%lx\n", frame->tf_rsp);
@@ -839,9 +882,34 @@
PTRACESTOP_SC(p, td, S_PT_SCE);
+#ifdef KDTRACE_HOOKS
+ /*
+ * If the systrace module has registered it's probe
+ * callback and if there is a probe active for the
+ * syscall 'entry', process the probe.
+ */
+ if (systrace_probe_func != NULL && callp->sy_entry != 0)
+ (*systrace_probe_func)(callp->sy_entry, code, callp,
+ args);
+#endif
+
AUDIT_SYSCALL_ENTER(code, td);
error = (*callp->sy_call)(td, argp);
AUDIT_SYSCALL_EXIT(error, td);
+
+ /* Save the latest error return value. */
+ td->td_errno = error;
+
+#ifdef KDTRACE_HOOKS
+ /*
+ * If the systrace module has registered it's probe
+ * callback and if there is a probe active for the
+ * syscall 'return', process the probe.
+ */
+ if (systrace_probe_func != NULL && callp->sy_return != 0)
+ (*systrace_probe_func)(callp->sy_return, code, callp,
+ args);
+#endif
}
switch (error) {
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/boot/common/boot.c 2005-05-20 09:03:01.000000000 +1000
+++ /u/p4/dtrace/src/sys/boot/common/boot.c 2008-04-19 16:58:34.000000000 +1000
@@ -52,6 +52,8 @@
static int
command_boot(int argc, char *argv[])
{
+ int error;
+ int fd;
struct preloaded_file *fp;
/*
@@ -102,6 +104,107 @@
if (archsw.arch_autoload() != 0)
return(CMD_ERROR);
+ /* Check if DTrace is to be loaded prior to boot. */
+ if (getenv("dtrace_boot")) {
+ /*
+ * Load the DTrace modules using the module that
+ * depends on all other modules -- dtraceall.
+ */
+ error = mod_load("dtraceall", NULL, 0, NULL);
+ if (error != 0)
+ printf("dtraceall autoload failed - %s\n", strerror(error));
+
+ /*
+ * Open the DTrace DOF file if it exists. Don't worry if
+ * it doesn't.
+ */
+ if ((fd = open("/boot/dtrace.dof", O_RDONLY)) >= 0) {
+ char *p; /* Temporary pointer. */
+ char *p_buf; /* Ptr to the read buffer. */
+ int n; /* Number of bytes in string. */
+ size_t n_buf; /* Number of characters buffered. */
+ size_t s_buf = 4096; /* Size of the read buffer. */
+
+ /*
+ * Allocate memory for the initial DOF buffer. This
+ * will be re-allocated if necessary.
+ */
+ if ((p_buf = malloc(s_buf)) != NULL) {
+ /*
+ * Enter a loop to read each line in the DOF
+ * file and add it to the environment.
+ */
+ do {
+ /* Start each line with an empty buffer. */
+ n_buf = 0;
+
+ /*
+ * Enter a loop to read the string in the
+ * current line, re-allocating the input
+ * buffer if it is too small.
+ */
+ while ((n = fgetstr(p_buf + n_buf, s_buf - n_buf,
+ fd)) > 0 && n == s_buf - n_buf - 1 &&
+ p_buf[s_buf - 2] != '\n') {
+ /*
+ * Update the number of characters
+ * buffered.
+ */
+ n_buf += n;
+
+ /* Double the buffer size. */
+ s_buf *= 2;
+
+ /* Re-allocate the buffer. */
+ if ((p = realloc(p_buf, s_buf)) == NULL) {
+ /*
+ * Can't re-allocate memory, so
+ * just give up.
+ */
+ n = 0;
+ n_buf = 0;
+ break;
+ }
+
+ /* Use the newly re-allocated buffer. */
+ p_buf = p;
+ }
+
+ /* Update the number of characters buffered. */
+ if (n > 0)
+ n_buf += n;
+
+ /*
+ * If there are characters buffered, add the
+ * input line to the environment.
+ */
+ if (n_buf > 0 && (p = strchr(p_buf, '=')) != NULL) {
+ /* Zero terminate the value. */
+ p_buf[n_buf] = '\0';
+
+ /* Zero terminate the name. */
+ *p = '\0';
+
+ /* Point to the value. */
+ p++;
+
+ /* Set the environment variable. */
+ setenv(p_buf, p, 1);
+ }
+
+ /*
+ * Keep looping until there are no more lines in
+ * the file.
+ */
+ } while (n > 0 && n_buf != 0);
+
+ free(p_buf);
+ }
+
+ close(fd);
+ }
+ }
+
/* Call the exec handler from the loader matching the kernel */
file_formats[fp->f_loader]->l_exec(fp);
return(CMD_ERROR);
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/boot/forth/beastie.4th 2006-04-01 08:36:17.000000000 +1100
+++ /u/p4/dtrace/src/sys/boot/forth/beastie.4th 2008-04-19 16:58:41.000000000 +1000
@@ -40,6 +40,8 @@
variable bootkey
variable bootacpikey
+variable bootdtracekey
+variable bootdtraceskey
variable bootsafekey
variable bootverbosekey
variable bootsinglekey
@@ -194,6 +196,8 @@
printmenuitem ." Boot FreeBSD in Safe Mode" bootsafekey !
printmenuitem ." Boot FreeBSD in single user mode" bootsinglekey !
printmenuitem ." Boot FreeBSD with verbose logging" bootverbosekey !
+ printmenuitem ." Boot FreeBSD with DTrace enabled" bootdtracekey !
+ printmenuitem ." Boot FreeBSD su with DTrace enabled" bootdtraceskey !
printmenuitem ." Escape to loader prompt" escapekey !
printmenuitem ." Reboot" rebootkey !
menuX @ 20 at-xy
@@ -283,6 +287,15 @@
s" YES" s" boot_single" setenv
0 boot
then
+ dup bootdtracekey @ = if
+ s" YES" s" dtrace_boot" setenv
+ 0 boot
+ then
+ dup bootdtraceskey @ = if
+ s" YES" s" dtrace_boot" setenv
+ s" YES" s" boot_single" setenv
+ 0 boot
+ then
dup escapekey @ = if
2drop
s" NO" s" autoboot_delay" setenv
=====================================================================
--ditto--
---------------------------------------------------------------------
New file: src/sys/cddl/dev/lockstat/lockstat.c
---------------------------------------------------------------------
/*
* 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
*
* Portions Copyright (c) 2008 Stacey Son
*
* $FreeBSD$
*
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#define KDTRACE_HOOKS
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if defined(__i386__) || defined(__amd64__)
#define LOCKSTAT_AFRAMES 1
#else
#error "architecture not supported"
#endif
static d_open_t lockstat_open;
static void lockstat_provide(void *, dtrace_probedesc_t *);
static void lockstat_destroy(void *, dtrace_id_t, void *);
static void lockstat_enable(void *, dtrace_id_t, void *);
static void lockstat_disable(void *, dtrace_id_t, void *);
static void lockstat_load(void *);
static int lockstat_unload(void);
typedef struct lockstat_probe {
char *lsp_func;
char *lsp_name;
int lsp_probe;
dtrace_id_t lsp_id;
} lockstat_probe_t;
#ifdef __FreeBSD__
lockstat_probe_t lockstat_probes[] =
{
/* Spin Locks */
{ LS_MTX_SPIN_LOCK, LSS_ACQUIRE, LS_MTX_SPIN_LOCK_ACQUIRE, DTRACE_IDNONE },
{ LS_MTX_SPIN_LOCK, LSS_SPIN, LS_MTX_SPIN_LOCK_SPIN, DTRACE_IDNONE },
{ LS_MTX_SPIN_UNLOCK, LSS_RELEASE, LS_MTX_SPIN_UNLOCK_RELEASE, DTRACE_IDNONE },
/* Adaptive Locks */
{ LS_MTX_LOCK, LSA_ACQUIRE, LS_MTX_LOCK_ACQUIRE, DTRACE_IDNONE },
{ LS_MTX_LOCK, LSA_BLOCK, LS_MTX_LOCK_BLOCK, DTRACE_IDNONE },
{ LS_MTX_LOCK, LSA_SPIN, LS_MTX_LOCK_SPIN, DTRACE_IDNONE },
{ LS_MTX_UNLOCK, LSA_RELEASE, LS_MTX_UNLOCK_RELEASE, DTRACE_IDNONE },
{ LS_MTX_TRYLOCK, LSA_ACQUIRE, LS_MTX_TRYLOCK_ACQUIRE, DTRACE_IDNONE },
/* Reader/Writer Locks */
{ LS_RW_RLOCK, LSR_ACQUIRE, LS_RW_RLOCK_ACQUIRE, DTRACE_IDNONE },
{ LS_RW_RLOCK, LSR_BLOCK, LS_RW_RLOCK_BLOCK, DTRACE_IDNONE },
{ LS_RW_RLOCK, LSR_SPIN, LS_RW_RLOCK_SPIN, DTRACE_IDNONE },
{ LS_RW_RUNLOCK, LSR_RELEASE, LS_RW_RUNLOCK_RELEASE, DTRACE_IDNONE },
{ LS_RW_WLOCK, LSR_ACQUIRE, LS_RW_WLOCK_ACQUIRE, DTRACE_IDNONE },
{ LS_RW_WLOCK, LSR_BLOCK, LS_RW_WLOCK_BLOCK, DTRACE_IDNONE },
{ LS_RW_WLOCK, LSR_SPIN, LS_RW_WLOCK_SPIN, DTRACE_IDNONE },
{ LS_RW_WUNLOCK, LSR_RELEASE, LS_RW_WUNLOCK_RELEASE, DTRACE_IDNONE },
{ LS_RW_TRYUPGRADE, LSR_UPGRADE, LS_RW_TRYUPGRADE_UPGRADE, DTRACE_IDNONE },
{ LS_RW_DOWNGRADE, LSR_DOWNGRADE, LS_RW_DOWNGRADE_DOWNGRADE, DTRACE_IDNONE },
/* Shared/Exclusive Locks */
{ LS_SX_SLOCK, LSX_ACQUIRE, LS_SX_SLOCK_ACQUIRE, DTRACE_IDNONE },
{ LS_SX_SLOCK, LSX_BLOCK, LS_SX_SLOCK_BLOCK, DTRACE_IDNONE },
{ LS_SX_SLOCK, LSX_SPIN, LS_SX_SLOCK_SPIN, DTRACE_IDNONE },
{ LS_SX_SUNLOCK, LSX_RELEASE, LS_SX_SUNLOCK_RELEASE, DTRACE_IDNONE },
{ LS_SX_XLOCK, LSX_ACQUIRE, LS_SX_XLOCK_ACQUIRE, DTRACE_IDNONE },
{ LS_SX_XLOCK, LSX_BLOCK, LS_SX_XLOCK_BLOCK, DTRACE_IDNONE },
{ LS_SX_XLOCK, LSX_SPIN, LS_SX_XLOCK_SPIN, DTRACE_IDNONE },
{ LS_SX_XUNLOCK, LSX_RELEASE, LS_SX_XUNLOCK_RELEASE, DTRACE_IDNONE },
{ LS_SX_TRYUPGRADE, LSX_UPGRADE, LS_SX_TRYUPGRADE_UPGRADE, DTRACE_IDNONE },
{ LS_SX_DOWNGRADE, LSX_DOWNGRADE, LS_SX_DOWNGRADE_DOWNGRADE, DTRACE_IDNONE },
/* Thread Locks */
{ LS_THREAD_LOCK, LST_SPIN, LS_THREAD_LOCK_SPIN, DTRACE_IDNONE },
{ NULL }
};
#else
#error "OS not supported"
#endif
static struct cdevsw lockstat_cdevsw = {
.d_version = D_VERSION,
.d_open = lockstat_open,
.d_name = "lockstat",
};
static struct cdev *lockstat_cdev;
static dtrace_provider_id_t lockstat_id;
/*ARGSUSED*/
static void
lockstat_enable(void *arg, dtrace_id_t id, void *parg)
{
lockstat_probe_t *probe = parg;
ASSERT(!lockstat_probemap[probe->lsp_probe]);
lockstat_probemap[probe->lsp_probe] = id;
#ifdef DOODAD
membar_producer();
#endif
lockstat_probe_func = dtrace_probe;
#ifdef DOODAD
membar_producer();
lockstat_hot_patch();
membar_producer();
#endif
}
/*ARGSUSED*/
static void
lockstat_disable(void *arg, dtrace_id_t id, void *parg)
{
lockstat_probe_t *probe = parg;
int i;
ASSERT(lockstat_probemap[probe->lsp_probe]);
lockstat_probemap[probe->lsp_probe] = 0;
#ifdef DOODAD
lockstat_hot_patch();
membar_producer();
#endif
/*
* See if we have any probes left enabled.
*/
for (i = 0; i < LS_NPROBES; i++) {
if (lockstat_probemap[i]) {
/*
* This probe is still enabled. We don't need to deal
* with waiting for all threads to be out of the
* lockstat critical sections; just return.
*/
return;
}
}
}
/*ARGSUSED*/
static int
lockstat_open(struct cdev *dev __unused, int oflags __unused,
int devtype __unused, struct thread *td __unused)
{
return (0);
}
/*ARGSUSED*/
static void
lockstat_provide(void *arg, dtrace_probedesc_t *desc)
{
int i = 0;
for (i = 0; lockstat_probes[i].lsp_func != NULL; i++) {
lockstat_probe_t *probe = &lockstat_probes[i];
if (dtrace_probe_lookup(lockstat_id, "kernel",
probe->lsp_func, probe->lsp_name) != 0)
continue;
ASSERT(!probe->lsp_id);
probe->lsp_id = dtrace_probe_create(lockstat_id,
"kernel", probe->lsp_func, probe->lsp_name,
LOCKSTAT_AFRAMES, probe);
}
}
/*ARGSUSED*/
static void
lockstat_destroy(void *arg, dtrace_id_t id, void *parg)
{
lockstat_probe_t *probe = parg;
ASSERT(!lockstat_probemap[probe->lsp_probe]);
probe->lsp_id = 0;
}
static dtrace_pattr_t lockstat_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_UNKNOWN },
{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
};
static dtrace_pops_t lockstat_pops = {
lockstat_provide,
NULL,
lockstat_enable,
lockstat_disable,
NULL,
NULL,
NULL,
NULL,
NULL,
lockstat_destroy
};
static void
lockstat_load(void *dummy)
{
/* Create the /dev/dtrace/lockstat entry. */
lockstat_cdev = make_dev(&lockstat_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
"dtrace/lockstat");
if (dtrace_register("lockstat", &lockstat_attr, DTRACE_PRIV_USER,
NULL, &lockstat_pops, NULL, &lockstat_id) != 0)
return;
}
static int
lockstat_unload()
{
int error = 0;
if ((error = dtrace_unregister(lockstat_id)) != 0)
return (error);
destroy_dev(lockstat_cdev);
return (error);
}
/* ARGSUSED */
static int
lockstat_modevent(module_t mod __unused, int type, void *data __unused)
{
int error = 0;
switch (type) {
case MOD_LOAD:
break;
case MOD_UNLOAD:
break;
case MOD_SHUTDOWN:
break;
default:
error = EOPNOTSUPP;
break;
}
return (error);
}
SYSINIT(lockstat_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, lockstat_load, NULL);
SYSUNINIT(lockstat_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, lockstat_unload, NULL);
DEV_MODULE(lockstat, lockstat_modevent, NULL);
MODULE_VERSION(lockstat, 1);
MODULE_DEPEND(lockstat, dtrace, 1, 1, 1);
MODULE_DEPEND(lockstat, opensolaris, 1, 1, 1);
=====================================================================
--ditto--
---------------------------------------------------------------------
New file: src/sys/i386/conf/ONE
---------------------------------------------------------------------
# Yabba dabba doo.
include GENERIC
ident ONE
nooptions SMP
options ALT_BREAK_TO_DEBUGGER
=====================================================================
--ditto--
---------------------------------------------------------------------
New file: src/sys/i386/conf/YABBA
---------------------------------------------------------------------
# Yabba dabba doo.
include GENERIC
ident YABBA
options VFS_AIO
# This panics my Dell 531S. Bad ohci, no biscuit.
nodevice ohci
nodevice uhci # UHCI PCI->USB interface
nodevice ehci # EHCI PCI->USB interface (USB 2.0)
nodevice usb # USB Bus (required)
nodevice ugen # Generic
nodevice uhid # "Human Interface Devices"
nodevice ukbd # Keyboard
nodevice ulpt # Printer
nodevice umass # Disks/Mass storage - Requires scbus and da
nodevice ums # Mouse
nodevice ural # Ralink Technology RT2500USB wireless NICs
nodevice uslcom
nodevice rum # Ralink Technology RT2501USB wireless NICs
nodevice urio # Diamond Rio 500 MP3 player
nodevice uscanner # Scanners
nodevice ucom # Generic com ttys
nodevice uark # Technologies ARK3116 based serial adapters
nodevice ubsa # Belkin F5U103 and compatible serial adapters
nodevice ubser # BWCT console serial adapters
nodevice uftdi # For FTDI usb serial adapters
nodevice uipaq # Some WinCE based devices
nodevice uplcom # Prolific PL-2303 serial adapters
nodevice uvisor # Visor and Palm devices
nodevice uvscom # USB serial support for DDI pocket's PHS
nodevice aue # ADMtek USB Ethernet
nodevice axe # ASIX Electronics USB Ethernet
nodevice cdce # Generic USB over Ethernet
nodevice cue # CATC USB Ethernet
nodevice kue # Kawasaki LSI USB Ethernet
nodevice rue # RealTek RTL8150 USB Ethernet
nodevice udav # Davicom DM9601E USB
nodevice zyd
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/i386/i386/exception.s 2007-12-07 19:20:16.000000000 +1100
+++ /u/p4/dtrace/src/sys/i386/i386/exception.s 2008-04-19 17:07:59.000000000 +1000
@@ -36,6 +36,7 @@
#include "opt_apic.h"
#include "opt_hwpmc_hooks.h"
+#include "opt_kdtrace.h"
#include "opt_npx.h"
#include
@@ -45,7 +46,23 @@
#include "assym.s"
#define SEL_RPL_MASK 0x0003
+#define GSEL_KPL 0x0020 /* GSEL(GCODE_SEL, SEL_KPL) */
+#ifdef KDTRACE_HOOKS
+ .bss
+ .globl dtrace_invop_jump_addr
+ .align 4
+ .type dtrace_invop_jump_addr, @object
+ .size dtrace_invop_jump_addr, 4
+dtrace_invop_jump_addr:
+ .zero 4
+ .globl dtrace_invop_calltrap_addr
+ .align 4
+ .type dtrace_invop_calltrap_addr, @object
+ .size dtrace_invop_calltrap_addr, 4
+dtrace_invop_calltrap_addr:
+ .zero 8
+#endif
.text
#ifdef HWPMC_HOOKS
ENTRY(start_exceptions)
@@ -95,8 +112,6 @@
pushl $0; TRAP(T_OFLOW)
IDTVEC(bnd)
pushl $0; TRAP(T_BOUND)
-IDTVEC(ill)
- pushl $0; TRAP(T_PRIVINFLT)
IDTVEC(dna)
pushl $0; TRAP(T_DNA)
IDTVEC(fpusegm)
@@ -153,6 +168,43 @@
jmp doreti
/*
+ * Privileged instruction fault.
+ */
+ SUPERALIGN_TEXT
+IDTVEC(ill)
+ /* Check if there is no DTrace hook registered. */
+ cmpl $0,dtrace_invop_jump_addr
+ je norm_ill
+
+ /* Check if this is a user fault. */
+ cmpl $GSEL_KPL, 4(%esp) /* Check the code segment. */
+
+ /* If so, just handle it as a normal trap. */
+ jne norm_ill
+
+ /*
+ * This is a kernel instruction fault that might have been caused
+ * by a DTrace provider.
+ */
+ pushal /* Push all registers onto the stack. */
+
+ /*
+ * Set our jump address for the jump back in the event that
+ * the exception wasn't caused by DTrace at all.
+ */
+ movl $norm_ill, dtrace_invop_calltrap_addr
+
+ /* Jump to the code hooked in by DTrace. */
+ jmpl *dtrace_invop_jump_addr
+
+ /*
+ * Process the instruction fault in the normal way.
+ */
+norm_ill:
+ pushl $0
+ TRAP(T_PRIVINFLT)
+
+/*
* SYSCALL CALL GATE (old entry point for a.out binaries)
*
* The intersegment call has been set up to specify one dummy parameter.
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/i386/i386/local_apic.c 2008-03-16 21:58:03.000000000 +1100
+++ /u/p4/dtrace/src/sys/i386/i386/local_apic.c 2008-04-19 17:08:00.000000000 +1000
@@ -35,6 +35,7 @@
__FBSDID("$FreeBSD: src/sys/i386/i386/local_apic.c,v 1.45 2008/03/16 10:58:03 rwatson Exp $");
#include "opt_hwpmc_hooks.h"
+#include "opt_kdtrace.h"
#include "opt_ddb.h"
@@ -65,6 +66,11 @@
#include
#endif
+#ifdef KDTRACE_HOOKS
+#include
+cyclic_clock_func_t lapic_cyclic_clock_func[MAXCPU];
+#endif
+
/* Sanity checks on IDT vectors. */
CTASSERT(APIC_IO_INTS + APIC_NUM_IOINTS == APIC_TIMER_INT);
CTASSERT(APIC_TIMER_INT < APIC_LOCAL_INTS);
@@ -670,6 +676,17 @@
(*la->la_timer_count)++;
critical_enter();
+#ifdef KDTRACE_HOOKS
+ /*
+ * If the DTrace hooks are configured and a callback function
+ * has been registered, then call it to process the high speed
+ * timers.
+ */
+ int cpu = PCPU_GET(cpuid);
+ if (lapic_cyclic_clock_func[cpu] != NULL)
+ (*lapic_cyclic_clock_func[cpu])(frame);
+#endif
+
/* Fire hardclock at hz. */
la->la_hard_ticks += hz;
if (la->la_hard_ticks >= lapic_timer_hz) {
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/i386/i386/trap.c 2008-03-27 07:09:19.000000000 +1100
+++ /u/p4/dtrace/src/sys/i386/i386/trap.c 2008-04-19 17:08:03.000000000 +1000
@@ -49,6 +49,7 @@
#include "opt_hwpmc_hooks.h"
#include "opt_isa.h"
#include "opt_kdb.h"
+#include "opt_kdtrace.h"
#include "opt_ktrace.h"
#include "opt_npx.h"
#include "opt_trap.h"
@@ -102,6 +103,26 @@
#include
#endif
+#ifdef KDTRACE_HOOKS
+#include
+
+/*
+ * This is a hook which is initialised by the dtrace module
+ * to handle traps which might occur during DTrace probe
+ * execution.
+ */
+dtrace_trap_func_t dtrace_trap_func;
+
+dtrace_doubletrap_func_t dtrace_doubletrap_func;
+
+/*
+ * This is a hook which is initialised by the systrace module
+ * when it is loaded. This keeps the DTrace syscall provider
+ * implementation opaque.
+ */
+systrace_probe_func_t systrace_probe_func;
+#endif
+
extern void trap(struct trapframe *frame);
extern void syscall(struct trapframe *frame);
@@ -218,6 +239,25 @@
goto out;
#endif
+#ifdef KDTRACE_HOOKS
+ /*
+ * A trap can occur while DTrace executes a probe. Before
+ * executing the probe, DTrace blocks re-scheduling and sets
+ * a flag in it's per-cpu flags to indicate that it doesn't
+ * want to fault. On returning from the the probe, the no-fault
+ * flag is cleared and finally re-scheduling is enabled.
+ *
+ * If the DTrace kernel module has registered a trap handler,
+ * call it and if it returns non-zero, assume that it has
+ * handled the trap and modified the trap frame so that this
+ * function can return normally.
+ */
+ if ((type == T_PROTFLT || type == T_PAGEFLT) &&
+ dtrace_trap_func != NULL)
+ if ((*dtrace_trap_func)(frame, type))
+ goto out;
+#endif
+
if ((frame->tf_eflags & PSL_I) == 0) {
/*
* Buggy application or kernel code has disabled
@@ -911,6 +951,10 @@
void
dblfault_handler()
{
+#ifdef KDTRACE_HOOKS
+ if (dtrace_doubletrap_func != NULL)
+ (*dtrace_doubletrap_func)();
+#endif
printf("\nFatal double fault:\n");
printf("eip = 0x%x\n", PCPU_GET(common_tss.tss_eip));
printf("esp = 0x%x\n", PCPU_GET(common_tss.tss_esp));
@@ -1022,9 +1066,34 @@
PTRACESTOP_SC(p, td, S_PT_SCE);
+#ifdef KDTRACE_HOOKS
+ /*
+ * If the systrace module has registered it's probe
+ * callback and if there is a probe active for the
+ * syscall 'entry', process the probe.
+ */
+ if (systrace_probe_func != NULL && callp->sy_entry != 0)
+ (*systrace_probe_func)(callp->sy_entry, code, callp,
+ args);
+#endif
+
AUDIT_SYSCALL_ENTER(code, td);
error = (*callp->sy_call)(td, args);
AUDIT_SYSCALL_EXIT(error, td);
+
+ /* Save the latest error return value. */
+ td->td_errno = error;
+
+#ifdef KDTRACE_HOOKS
+ /*
+ * If the systrace module has registered it's probe
+ * callback and if there is a probe active for the
+ * syscall 'return', process the probe.
+ */
+ if (systrace_probe_func != NULL && callp->sy_return != 0)
+ (*systrace_probe_func)(callp->sy_return, code, callp,
+ args);
+#endif
}
switch (error) {
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/i386/isa/clock.c 2008-04-23 08:20:19.000000000 +1000
+++ /u/p4/dtrace/src/sys/i386/isa/clock.c 2008-04-23 08:25:53.000000000 +1000
@@ -41,6 +41,7 @@
#include "opt_apic.h"
#include "opt_clock.h"
+#include "opt_kdtrace.h"
#include "opt_isa.h"
#include "opt_mca.h"
#include "opt_xbox.h"
@@ -79,6 +80,10 @@
#include
#endif
+#ifdef KDTRACE_HOOKS
+#include
+#endif
+
#define TIMER_DIV(x) ((i8254_freq + (x) / 2) / (x))
int clkintr_pending;
@@ -138,6 +143,18 @@
mtx_unlock_spin(&clock_lock);
}
KASSERT(!using_lapic_timer, ("clk interrupt enabled with lapic timer"));
+
+#ifdef KDTRACE_HOOKS
+ /*
+ * If the DTrace hooks are configured and a callback function
+ * has been registered, then call it to process the high speed
+ * timers.
+ */
+ int cpu = PCPU_GET(cpuid);
+ if (lapic_cyclic_clock_func[cpu] != NULL)
+ (*lapic_cyclic_clock_func[cpu])(frame);
+#endif
+
hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
#ifdef DEV_MCA
/* Reset clock interrupt by asserting bit 7 of port 0x61 */
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/kern/kern_exec.c 2008-03-31 23:05:52.000000000 +1100
+++ /u/p4/dtrace/src/sys/kern/kern_exec.c 2008-04-19 17:08:34.000000000 +1000
@@ -28,6 +28,7 @@
__FBSDID("$FreeBSD: src/sys/kern/kern_exec.c,v 1.317 2008/03/31 12:05:52 kib Exp $");
#include "opt_hwpmc_hooks.h"
+#include "opt_kdtrace.h"
#include "opt_ktrace.h"
#include "opt_mac.h"
#include "opt_vm.h"
@@ -54,6 +55,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -83,6 +85,19 @@
#include
#include
+#ifdef KDTRACE_HOOKS
+#include
+dtrace_execexit_func_t dtrace_fasttrap_exec;
+#endif
+
+SDT_PROVIDER_DECLARE(proc);
+SDT_PROBE_DEFINE(proc, kernel, , exec);
+SDT_PROBE_ARGTYPE(proc, kernel, , exec, 0, "char *");
+SDT_PROBE_DEFINE(proc, kernel, , exec_failure);
+SDT_PROBE_ARGTYPE(proc, kernel, , exec_failure, 0, "int");
+SDT_PROBE_DEFINE(proc, kernel, , exec_success);
+SDT_PROBE_ARGTYPE(proc, kernel, , exec_success, 0, "char *");
+
MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments");
static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS);
@@ -371,6 +386,8 @@
imgp->image_header = NULL;
+ SDT_PROBE(proc, kernel, , exec, args->fname, 0, 0, 0, 0 );
+
/*
* Translate the file name. namei() returns a vnode pointer
* in ni_vp amoung other things.
@@ -702,6 +719,15 @@
textvp = p->p_textvp;
p->p_textvp = binvp;
+#ifdef KDTRACE_HOOKS
+ /*
+ * Tell the DTrace fasttrap provider about the exec if it
+ * has declared an interest.
+ */
+ if (dtrace_fasttrap_exec)
+ dtrace_fasttrap_exec(p);
+#endif
+
/*
* Notify others that we exec'd, and clear the P_INEXEC flag
* as we're now a bona fide freshly-execed process.
@@ -764,6 +790,7 @@
vfs_mark_atime(imgp->vp, td);
done1:
+
/*
* Free any resources malloc'd earlier that we didn't use.
*/
@@ -773,6 +800,9 @@
else
crfree(newcred);
VOP_UNLOCK(imgp->vp, 0);
+
+ SDT_PROBE(proc, kernel, , exec_success, args->fname, 0, 0, 0, 0);
+
/*
* Handle deferred decrement of ref counts.
*/
@@ -836,6 +866,8 @@
p->p_flag &= ~P_INEXEC;
PROC_UNLOCK(p);
+ SDT_PROBE(proc, kernel, , exec_failure, error, 0, 0, 0, 0);
+
done2:
#ifdef MAC
mac_execve_exit(imgp);
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/kern/kern_exit.c 2008-03-23 03:32:52.000000000 +1100
+++ /u/p4/dtrace/src/sys/kern/kern_exit.c 2008-04-19 17:08:34.000000000 +1000
@@ -38,6 +38,7 @@
__FBSDID("$FreeBSD: src/sys/kern/kern_exit.c,v 1.310 2008/03/22 16:32:52 phk Exp $");
#include "opt_compat.h"
+#include "opt_kdtrace.h"
#include "opt_ktrace.h"
#include "opt_mac.h"
@@ -65,6 +66,7 @@
#include
#include /* for acct_process() function prototype */
#include
+#include
#include
#include
#ifdef KTRACE
@@ -82,6 +84,15 @@
#include
#include
+#ifdef KDTRACE_HOOKS
+#include
+dtrace_execexit_func_t dtrace_fasttrap_exit;
+#endif
+
+SDT_PROVIDER_DECLARE(proc);
+SDT_PROBE_DEFINE(proc, kernel, , exit);
+SDT_PROBE_ARGTYPE(proc, kernel, , exit, 0, "int");
+
/* Required to be non-static for SysVR4 emulator */
MALLOC_DEFINE(M_ZOMBIE, "zombie", "zombie proc status");
@@ -443,11 +454,30 @@
PROC_LOCK(p);
p->p_xstat = rv;
p->p_xthread = td;
+
+#ifdef KDTRACE_HOOKS
+ /*
+ * Tell the DTrace fasttrap provider about the exit if it
+ * has declared an interest.
+ */
+ if (dtrace_fasttrap_exit)
+ dtrace_fasttrap_exit(p);
+#endif
+
/*
* Notify interested parties of our demise.
*/
KNOTE_LOCKED(&p->p_klist, NOTE_EXIT);
+#ifdef KDTRACE_HOOKS
+ int reason = CLD_EXITED;
+ if (WCOREDUMP(rv))
+ reason = CLD_DUMPED;
+ else if (WIFSIGNALED(rv))
+ reason = CLD_KILLED;
+ SDT_PROBE(proc, kernel, , exit, reason, 0, 0, 0, 0);
+#endif
+
/*
* Just delete all entries in the p_klist. At this point we won't
* report any more events, and there are nasty race conditions that
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/kern/kern_fork.c 2008-03-21 02:24:49.000000000 +1100
+++ /u/p4/dtrace/src/sys/kern/kern_fork.c 2008-04-19 17:08:34.000000000 +1000
@@ -37,6 +37,7 @@
#include
__FBSDID("$FreeBSD: src/sys/kern/kern_fork.c,v 1.292 2008/03/20 15:24:49 kib Exp $");
+#include "opt_kdtrace.h"
#include "opt_ktrace.h"
#include "opt_mac.h"
@@ -63,6 +64,7 @@
#include
#include
#include
+#include
#include
#include
@@ -75,6 +77,16 @@
#include
#include
+#ifdef KDTRACE_HOOKS
+#include
+dtrace_fork_func_t dtrace_fasttrap_fork;
+#endif
+
+SDT_PROVIDER_DECLARE(proc);
+SDT_PROBE_DEFINE(proc, kernel, , create);
+SDT_PROBE_ARGTYPE(proc, kernel, , create, 0, "struct proc *");
+SDT_PROBE_ARGTYPE(proc, kernel, , create, 1, "struct proc *");
+SDT_PROBE_ARGTYPE(proc, kernel, , create, 2, "int");
#ifndef _SYS_SYSPROTO_H_
struct fork_args {
@@ -626,6 +638,15 @@
p2->p_pfsflags = p1->p_pfsflags;
}
+#ifdef KDTRACE_HOOKS
+ /*
+ * Tell the DTrace fasttrap provider about the new process
+ * if it has registered an interest.
+ */
+ if (dtrace_fasttrap_fork)
+ dtrace_fasttrap_fork(p1, p2);
+#endif
+
/*
* This begins the section where we must prevent the parent
* from being swapped.
@@ -715,6 +736,8 @@
PROC_UNLOCK(p1);
+ SDT_PROBE(proc, kernel, , create, p2, p1, flags, 0, 0);
+
/*
* Preserve synchronization semantics of vfork. If waiting for
* child to exec or exit, set P_PPWAIT on child, and sleep on our
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/kern/kern_mutex.c 2008-02-14 10:39:05.000000000 +1100
+++ /u/p4/dtrace/src/sys/kern/kern_mutex.c 2008-04-19 17:08:37.000000000 +1000
@@ -40,6 +40,7 @@
#include "opt_ddb.h"
#include "opt_global.h"
#include "opt_sched.h"
+#include "opt_kdtrace.h"
#include
#include
@@ -59,6 +60,7 @@
#include
#include
#include
+#include
#include
#include
@@ -201,8 +203,10 @@
line);
mtx_assert(m, MA_OWNED);
- if (m->mtx_recurse == 0)
+ if (m->mtx_recurse == 0) {
lock_profile_release_lock(&m->lock_object);
+ LOCKSTAT_RECORD0(LS_MTX_UNLOCK_RELEASE, m);
+ }
_rel_sleep_lock(m, curthread, opts, file, line);
}
@@ -276,10 +280,11 @@
WITNESS_LOCK(&m->lock_object, opts | LOP_EXCLUSIVE | LOP_TRYLOCK,
file, line);
curthread->td_locks++;
- if (m->mtx_recurse == 0)
+ if (m->mtx_recurse == 0) {
lock_profile_obtain_lock_success(&m->lock_object, contested,
waittime, file, line);
-
+ LOCKSTAT_RECORD0(LS_MTX_LOCK_ACQUIRE, m);
+ }
}
return (rval);
@@ -305,6 +310,11 @@
int contested = 0;
uint64_t waittime = 0;
uintptr_t v;
+#ifdef KDTRACE_HOOKS
+ uint64_t spin_cnt = 0;
+ uint64_t sleep_cnt = 0;
+ int64_t sleep_time = 0;
+#endif
if (mtx_owned(m)) {
KASSERT((m->lock_object.lo_flags & LO_RECURSABLE) != 0,
@@ -325,6 +335,9 @@
m->lock_object.lo_name, (void *)m->mtx_lock, file, line);
while (!_obtain_lock(m, tid)) {
+#ifdef KDTRACE_HOOKS
+ spin_cnt++;
+#endif
#ifdef ADAPTIVE_MUTEXES
/*
* If the owner is running on another CPU, spin until the
@@ -339,8 +352,12 @@
"%s: spinning on %p held by %p",
__func__, m, owner);
while (mtx_owner(m) == owner &&
- TD_IS_RUNNING(owner))
+ TD_IS_RUNNING(owner)) {
cpu_spinwait();
+#ifdef KDTRACE_HOOKS
+ spin_cnt++;
+#endif
+ }
continue;
}
}
@@ -405,7 +422,15 @@
/*
* Block on the turnstile.
*/
+#ifdef KDTRACE_HOOKS
+ /* Record the time blocked */
+ sleep_time -= lockstat_nsecs();
+#endif
turnstile_wait(ts, mtx_owner(m), TS_EXCLUSIVE_QUEUE);
+#ifdef KDTRACE_HOOKS
+ sleep_time += lockstat_nsecs();
+ sleep_cnt++;
+#endif
}
#ifdef KTR
if (cont_logged) {
@@ -416,6 +441,15 @@
#endif
lock_profile_obtain_lock_success(&m->lock_object, contested,
waittime, file, line);
+#ifdef KDTRACE_HOOKS
+ /* sleep_time is the total time blocked */
+ if (sleep_time != 0)
+ LOCKSTAT_RECORD1(LS_MTX_LOCK_BLOCK, m, sleep_time);
+ /* record only the loops spinning and not sleeping */
+ if (spin_cnt > sleep_cnt)
+ LOCKSTAT_RECORD1(LS_MTX_LOCK_SPIN, m, (spin_cnt - sleep_cnt));
+ LOCKSTAT_RECORD0(LS_MTX_LOCK_ACQUIRE, m);
+#endif
}
static void
@@ -478,6 +512,8 @@
lock_profile_obtain_lock_success(&m->lock_object, contested,
waittime, (file), (line));
+ LOCKSTAT_RECORD1(LS_MTX_SPIN_LOCK_SPIN, m, i);
+ LOCKSTAT_RECORD0(LS_MTX_SPIN_LOCK_ACQUIRE, m);
}
#endif /* SMP */
@@ -488,6 +524,9 @@
uintptr_t tid;
int i, contested;
uint64_t waittime;
+#ifdef KDTRACE_HOOKS
+ uint64_t spin_cnt = 0;
+#endif
contested = i = 0;
waittime = 0;
@@ -508,6 +547,9 @@
WITNESS_CHECKORDER(&m->lock_object,
opts | LOP_NEWORDER | LOP_EXCLUSIVE, file, line);
while (!_obtain_lock(m, tid)) {
+#ifdef KDTRACE_HOOKS
+ spin_cnt++;
+#endif
if (m->mtx_lock == tid) {
m->mtx_recurse++;
break;
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/kern/kern_proc.c 2008-03-19 17:19:00.000000000 +1100
+++ /u/p4/dtrace/src/sys/kern/kern_proc.c 2008-05-16 07:26:29.000000000 +1000
@@ -33,6 +33,7 @@
__FBSDID("$FreeBSD: src/sys/kern/kern_proc.c,v 1.263 2008/03/19 06:19:00 jeff Exp $");
#include "opt_ddb.h"
+#include "opt_kdtrace.h"
#include "opt_ktrace.h"
#include "opt_kstack_pages.h"
#include "opt_stack.h"
@@ -55,6 +56,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -76,6 +78,35 @@
#include
#include
+SDT_PROVIDER_DEFINE(proc);
+SDT_PROBE_DEFINE(proc, kernel, ctor, entry);
+SDT_PROBE_ARGTYPE(proc, kernel, ctor, entry, 0, "struct proc *");
+SDT_PROBE_ARGTYPE(proc, kernel, ctor, entry, 1, "int");
+SDT_PROBE_ARGTYPE(proc, kernel, ctor, entry, 2, "void *");
+SDT_PROBE_ARGTYPE(proc, kernel, ctor, entry, 3, "int");
+SDT_PROBE_DEFINE(proc, kernel, ctor, return);
+SDT_PROBE_ARGTYPE(proc, kernel, ctor, return, 0, "struct proc *");
+SDT_PROBE_ARGTYPE(proc, kernel, ctor, return, 1, "int");
+SDT_PROBE_ARGTYPE(proc, kernel, ctor, return, 2, "void *");
+SDT_PROBE_ARGTYPE(proc, kernel, ctor, return, 3, "int");
+SDT_PROBE_DEFINE(proc, kernel, dtor, entry);
+SDT_PROBE_ARGTYPE(proc, kernel, dtor, entry, 0, "struct proc *");
+SDT_PROBE_ARGTYPE(proc, kernel, dtor, entry, 1, "int");
+SDT_PROBE_ARGTYPE(proc, kernel, dtor, entry, 2, "void *");
+SDT_PROBE_ARGTYPE(proc, kernel, dtor, entry, 3, "struct thread *");
+SDT_PROBE_DEFINE(proc, kernel, dtor, return);
+SDT_PROBE_ARGTYPE(proc, kernel, dtor, return, 0, "struct proc *");
+SDT_PROBE_ARGTYPE(proc, kernel, dtor, return, 1, "int");
+SDT_PROBE_ARGTYPE(proc, kernel, dtor, return, 2, "void *");
+SDT_PROBE_DEFINE(proc, kernel, init, entry);
+SDT_PROBE_ARGTYPE(proc, kernel, init, entry, 0, "struct proc *");
+SDT_PROBE_ARGTYPE(proc, kernel, init, entry, 1, "int");
+SDT_PROBE_ARGTYPE(proc, kernel, init, entry, 2, "int");
+SDT_PROBE_DEFINE(proc, kernel, init, return);
+SDT_PROBE_ARGTYPE(proc, kernel, init, return, 0, "struct proc *");
+SDT_PROBE_ARGTYPE(proc, kernel, init, return, 1, "int");
+SDT_PROBE_ARGTYPE(proc, kernel, init, return, 2, "int");
+
MALLOC_DEFINE(M_PGRP, "pgrp", "process group header");
MALLOC_DEFINE(M_SESSION, "session", "session header");
static MALLOC_DEFINE(M_PROC, "proc", "Proc structures");
@@ -142,7 +173,9 @@
struct proc *p;
p = (struct proc *)mem;
+ SDT_PROBE(proc, kernel, ctor , entry, p, size, arg, flags, 0);
EVENTHANDLER_INVOKE(process_ctor, p);
+ SDT_PROBE(proc, kernel, ctor , return, p, size, arg, flags, 0);
return (0);
}
@@ -158,6 +191,7 @@
/* INVARIANTS checks go here */
p = (struct proc *)mem;
td = FIRST_THREAD_IN_PROC(p);
+ SDT_PROBE(proc, kernel, dtor, entry, p, size, arg, td, 0);
if (td != NULL) {
#ifdef INVARIANTS
KASSERT((p->p_numthreads == 1),
@@ -175,6 +209,7 @@
EVENTHANDLER_INVOKE(process_dtor, p);
if (p->p_ksi != NULL)
KASSERT(! KSI_ONQ(p->p_ksi), ("SIGCHLD queue"));
+ SDT_PROBE(proc, kernel, dtor, return, p, size, arg, 0, 0);
}
/*
@@ -186,6 +221,7 @@
struct proc *p;
p = (struct proc *)mem;
+ SDT_PROBE(proc, kernel, init, entry, p, size, flags, 0, 0);
p->p_sched = (struct p_sched *)&p[1];
bzero(&p->p_mtx, sizeof(struct mtx));
mtx_init(&p->p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK);
@@ -193,6 +229,7 @@
TAILQ_INIT(&p->p_threads); /* all threads in proc */
EVENTHANDLER_INVOKE(process_init, p);
p->p_stats = pstats_alloc();
+ SDT_PROBE(proc, kernel, init, return, p, size, flags, 0, 0);
return (0);
}
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/kern/kern_rwlock.c 2008-04-04 21:00:46.000000000 +1100
+++ /u/p4/dtrace/src/sys/kern/kern_rwlock.c 2008-04-19 17:08:38.000000000 +1000
@@ -36,11 +36,13 @@
#include "opt_ddb.h"
#include "opt_no_adaptive_rwlocks.h"
+#include "opt_kdtrace.h"
#include
#include
#include
#include
+#include
#include
#include
#include
@@ -249,8 +251,10 @@
WITNESS_UNLOCK(&rw->lock_object, LOP_EXCLUSIVE, file, line);
LOCK_LOG_LOCK("WUNLOCK", &rw->lock_object, 0, rw->rw_recurse, file,
line);
- if (!rw_recursed(rw))
+ if (!rw_recursed(rw)) {
lock_profile_release_lock(&rw->lock_object);
+ LOCKSTAT_RECORD0(LS_RW_WUNLOCK_RELEASE, rw);
+ }
__rw_wunlock(rw, curthread, file, line);
}
/*
@@ -277,6 +281,11 @@
uint64_t waittime = 0;
int contested = 0;
uintptr_t v;
+#ifdef KDTRACE_HOOKS
+ uint64_t spin_cnt = 0;
+ uint64_t sleep_cnt = 0;
+ int64_t sleep_time = 0;
+#endif
KASSERT(rw->rw_lock != RW_DESTROYED,
("rw_rlock() of destroyed rwlock @ %s:%d", file, line));
@@ -286,6 +295,9 @@
WITNESS_CHECKORDER(&rw->lock_object, LOP_NEWORDER, file, line);
for (;;) {
+#ifdef KDTRACE_HOOKS
+ spin_cnt++;
+#endif
/*
* Handle the easy case. If no other thread has a write
* lock, then try to bump up the count of read locks. Note
@@ -332,8 +344,12 @@
"%s: spinning on %p held by %p",
__func__, rw, owner);
while ((struct thread*)RW_OWNER(rw->rw_lock) ==
- owner && TD_IS_RUNNING(owner))
+ owner && TD_IS_RUNNING(owner)) {
cpu_spinwait();
+#ifdef KDTRACE_HOOKS
+ spin_cnt++;
+#endif
+ }
continue;
}
} else if (spintries < rowner_retries) {
@@ -413,7 +429,14 @@
if (LOCK_LOG_TEST(&rw->lock_object, 0))
CTR2(KTR_LOCK, "%s: %p blocking on turnstile", __func__,
rw);
+#ifdef KDTRACE_HOOKS
+ sleep_time -= lockstat_nsecs();
+#endif
turnstile_wait(ts, rw_owner(rw), TS_SHARED_QUEUE);
+#ifdef KDTRACE_HOOKS
+ sleep_time += lockstat_nsecs();
+ sleep_cnt++;
+#endif
if (LOCK_LOG_TEST(&rw->lock_object, 0))
CTR2(KTR_LOCK, "%s: %p resuming from turnstile",
__func__, rw);
@@ -430,6 +453,15 @@
WITNESS_LOCK(&rw->lock_object, 0, file, line);
curthread->td_locks++;
curthread->td_rw_rlocks++;
+#ifdef KDTRACE_HOOKS
+ /* sleep_time is the total time blocked */
+ if (sleep_time != 0)
+ LOCKSTAT_RECORD1(LS_RW_RLOCK_BLOCK, rw, sleep_time);
+ /* record only the loops spinning and not sleeping */
+ if (spin_cnt > sleep_cnt)
+ LOCKSTAT_RECORD1(LS_RW_RLOCK_SPIN, rw, (spin_cnt - sleep_cnt));
+ LOCKSTAT_RECORD0(LS_RW_RLOCK_ACQUIRE, rw);
+#endif
}
int
@@ -560,6 +592,7 @@
break;
}
lock_profile_release_lock(&rw->lock_object);
+ LOCKSTAT_RECORD0(LS_RW_RUNLOCK_RELEASE, rw);
}
/*
@@ -579,6 +612,11 @@
uint64_t waittime = 0;
uintptr_t v, x;
int contested = 0;
+#ifdef KDTRACE_HOOKS
+ uint64_t spin_cnt = 0;
+ uint64_t sleep_cnt = 0;
+ int64_t sleep_time = 0;
+#endif
if (rw_wlocked(rw)) {
KASSERT(rw->lock_object.lo_flags & RW_RECURSE,
@@ -595,6 +633,9 @@
rw->lock_object.lo_name, (void *)rw->rw_lock, file, line);
while (!_rw_write_lock(rw, tid)) {
+#ifdef KDTRACE_HOOKS
+ spin_cnt++;
+#endif
lock_profile_obtain_lock_failed(&rw->lock_object,
&contested, &waittime);
#ifdef ADAPTIVE_RWLOCKS
@@ -610,8 +651,12 @@
CTR3(KTR_LOCK, "%s: spinning on %p held by %p",
__func__, rw, owner);
while ((struct thread*)RW_OWNER(rw->rw_lock) == owner &&
- TD_IS_RUNNING(owner))
+ TD_IS_RUNNING(owner)) {
cpu_spinwait();
+#ifdef KDTRACE_HOOKS
+ spin_cnt++;
+#endif
+ }
continue;
}
if ((v & RW_LOCK_READ) && RW_READERS(v) &&
@@ -629,6 +674,9 @@
break;
cpu_spinwait();
}
+#ifdef KDTRACE_HOOKS
+ spin_cnt += 100000 - i;
+#endif
if (i != rowner_loops)
continue;
}
@@ -691,7 +739,14 @@
if (LOCK_LOG_TEST(&rw->lock_object, 0))
CTR2(KTR_LOCK, "%s: %p blocking on turnstile", __func__,
rw);
+#ifdef KDTRACE_HOOKS
+ sleep_time -= lockstat_nsecs();
+#endif
turnstile_wait(ts, rw_owner(rw), TS_EXCLUSIVE_QUEUE);
+#ifdef KDTRACE_HOOKS
+ sleep_time += lockstat_nsecs();
+ sleep_cnt++;
+#endif
if (LOCK_LOG_TEST(&rw->lock_object, 0))
CTR2(KTR_LOCK, "%s: %p resuming from turnstile",
__func__, rw);
@@ -701,6 +756,15 @@
}
lock_profile_obtain_lock_success(&rw->lock_object, contested, waittime,
file, line);
+#ifdef KDTRACE_HOOKS
+ /* sleep_time is the total time blocked */
+ if (sleep_time != 0)
+ LOCKSTAT_RECORD1(LS_RW_WLOCK_BLOCK, rw, sleep_time);
+ /* record only the loops spinning and not sleeping */
+ if (spin_cnt > sleep_cnt)
+ LOCKSTAT_RECORD1(LS_RW_WLOCK_SPIN, rw, (spin_cnt - sleep_cnt));
+ LOCKSTAT_RECORD0(LS_RW_WLOCK_ACQUIRE, rw);
+#endif
}
/*
@@ -834,6 +898,7 @@
curthread->td_rw_rlocks--;
WITNESS_UPGRADE(&rw->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK,
file, line);
+ LOCKSTAT_RECORD0(LS_RW_TRYUPGRADE_UPGRADE, rw);
}
return (success);
}
@@ -899,6 +964,7 @@
out:
curthread->td_rw_rlocks++;
LOCK_LOG_LOCK("WDOWNGRADE", &rw->lock_object, 0, 0, file, line);
+ LOCKSTAT_RECORD0(LS_RW_DOWNGRADE_DOWNGRADE, rw);
}
#ifdef INVARIANT_SUPPORT
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/kern/kern_sig.c 2008-03-21 19:23:25.000000000 +1100
+++ /u/p4/dtrace/src/sys/kern/kern_sig.c 2008-04-19 17:08:39.000000000 +1000
@@ -38,6 +38,7 @@
__FBSDID("$FreeBSD: src/sys/kern/kern_sig.c,v 1.360 2008/03/21 08:23:25 jeff Exp $");
#include "opt_compat.h"
+#include "opt_kdtrace.h"
#include "opt_ktrace.h"
#include
@@ -59,6 +60,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -82,6 +84,19 @@
#define ONSIG 32 /* NSIG for osig* syscalls. XXX. */
+SDT_PROVIDER_DECLARE(proc);
+SDT_PROBE_DEFINE(proc, kernel, , signal_send);
+SDT_PROBE_ARGTYPE(proc, kernel, , signal_send, 0, "struct thread *");
+SDT_PROBE_ARGTYPE(proc, kernel, , signal_send, 1, "struct proc *");
+SDT_PROBE_ARGTYPE(proc, kernel, , signal_send, 2, "int");
+SDT_PROBE_DEFINE(proc, kernel, , signal_clear);
+SDT_PROBE_ARGTYPE(proc, kernel, , signal_clear, 0, "int");
+SDT_PROBE_ARGTYPE(proc, kernel, , signal_clear, 1, "ksiginfo_t *");
+SDT_PROBE_DEFINE(proc, kernel, , signal_discard);
+SDT_PROBE_ARGTYPE(proc, kernel, , signal_discard, 0, "struct thread *");
+SDT_PROBE_ARGTYPE(proc, kernel, , signal_discard, 1, "struct proc *");
+SDT_PROBE_ARGTYPE(proc, kernel, , signal_discard, 2, "int");
+
static int coredump(struct thread *);
static char *expand_name(const char *, uid_t, pid_t);
static int killpg1(struct thread *td, int sig, int pgid, int all);
@@ -1236,6 +1251,9 @@
ksiginfo_init(ksi);
sigqueue_get(&td->td_sigqueue, sig, ksi);
ksi->ksi_signo = sig;
+
+ SDT_PROBE(proc, kernel, , signal_clear, sig, ksi, 0, 0, 0);
+
if (ksi->ksi_code == SI_TIMER)
itimer_accept(p, ksi->ksi_timerid, ksi);
error = 0;
@@ -1976,6 +1994,8 @@
sigqueue = &td->td_sigqueue;
}
+ SDT_PROBE(proc, kernel, , signal_send, td, p, sig, 0, 0 );
+
/*
* If the signal is being ignored,
* then we forget about it immediately.
@@ -1985,6 +2005,8 @@
*/
mtx_lock(&ps->ps_mtx);
if (SIGISMEMBER(ps->ps_sigignore, sig)) {
+ SDT_PROBE(proc, kernel, , signal_discard, ps, td, sig, 0, 0 );
+
mtx_unlock(&ps->ps_mtx);
if (ksi && (ksi->ksi_flags & KSI_INS))
ksiginfo_tryfree(ksi);
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/kern/kern_sx.c 2008-05-17 11:54:24.000000000 +1000
+++ /u/p4/dtrace/src/sys/kern/kern_sx.c 2008-05-17 11:54:47.000000000 +1000
@@ -38,6 +38,7 @@
#include "opt_adaptive_sx.h"
#include "opt_ddb.h"
+#include "opt_kdtrace.h"
#include
__FBSDID("$FreeBSD: src/sys/kern/kern_sx.c,v 1.60 2008/05/15 20:10:06 attilio Exp $");
@@ -305,6 +306,7 @@
LOCK_LOG_LOCK("SUNLOCK", &sx->lock_object, 0, 0, file, line);
__sx_sunlock(sx, file, line);
lock_profile_release_lock(&sx->lock_object);
+ LOCKSTAT_RECORD0(LS_SX_SUNLOCK_RELEASE, sx);
}
void
@@ -319,8 +321,10 @@
WITNESS_UNLOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line);
LOCK_LOG_LOCK("XUNLOCK", &sx->lock_object, 0, sx->sx_recurse, file,
line);
- if (!sx_recursed(sx))
+ if (!sx_recursed(sx)) {
lock_profile_release_lock(&sx->lock_object);
+ LOCKSTAT_RECORD0(LS_SX_XUNLOCK_RELEASE, sx);
+ }
__sx_xunlock(sx, curthread, file, line);
}
@@ -348,9 +352,11 @@
success = atomic_cmpset_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) | x,
(uintptr_t)curthread | x);
LOCK_LOG_TRY("XUPGRADE", &sx->lock_object, 0, success, file, line);
- if (success)
+ if (success) {
WITNESS_UPGRADE(&sx->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK,
file, line);
+ LOCKSTAT_RECORD0(LS_SX_TRYUPGRADE_UPGRADE, sx);
+ }
return (success);
}
@@ -410,6 +416,7 @@
sleepq_release(&sx->lock_object);
LOCK_LOG_LOCK("XDOWNGRADE", &sx->lock_object, 0, 0, file, line);
+ LOCKSTAT_RECORD0(LS_SX_DOWNGRADE_DOWNGRADE, sx);
}
/*
@@ -429,6 +436,11 @@
uint64_t waittime = 0;
uintptr_t x;
int contested = 0, error = 0;
+#ifdef KDTRACE_HOOKS
+ uint64_t spin_cnt = 0;
+ uint64_t sleep_cnt = 0;
+ int64_t sleep_time = 0;
+#endif
/* If we already hold an exclusive lock, then recurse. */
if (sx_xlocked(sx)) {
@@ -447,6 +459,9 @@
sx->lock_object.lo_name, (void *)sx->sx_lock, file, line);
while (!atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED, tid)) {
+#ifdef KDTRACE_HOOKS
+ spin_cnt++;
+#endif
lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
&waittime);
#ifdef ADAPTIVE_SX
@@ -467,8 +482,12 @@
__func__, sx, owner);
GIANT_SAVE();
while (SX_OWNER(sx->sx_lock) == x &&
- TD_IS_RUNNING(owner))
+ TD_IS_RUNNING(owner)) {
cpu_spinwait();
+#ifdef KDTRACE_HOOKS
+ spin_cnt++;
+#endif
+ }
continue;
}
}
@@ -550,7 +569,9 @@
if (LOCK_LOG_TEST(&sx->lock_object, 0))
CTR2(KTR_LOCK, "%s: %p blocking on sleep queue",
__func__, sx);
-
+#ifdef KDTRACE_HOOKS
+ sleep_time -= lockstat_nsecs();
+#endif
GIANT_SAVE();
sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
SLEEPQ_SX | ((opts & SX_INTERRUPTIBLE) ?
@@ -560,6 +581,10 @@
else
error = sleepq_wait_sig(&sx->lock_object, 0);
+#ifdef KDTRACE_HOOKS
+ sleep_time += lockstat_nsecs();
+ sleep_cnt++;
+#endif
if (error) {
if (LOCK_LOG_TEST(&sx->lock_object, 0))
CTR2(KTR_LOCK,
@@ -573,9 +598,17 @@
}
GIANT_RESTORE();
- if (!error)
+ if (!error) {
lock_profile_obtain_lock_success(&sx->lock_object, contested,
waittime, file, line);
+ LOCKSTAT_RECORD0(LS_SX_XLOCK_ACQUIRE, sx);
+ }
+#ifdef KDTRACE_HOOKS
+ if (sleep_time != 0)
+ LOCKSTAT_RECORD1(LS_SX_XLOCK_BLOCK, sx, sleep_time);
+ if (spin_cnt > sleep_cnt)
+ LOCKSTAT_RECORD1(LS_SX_XLOCK_SPIN, sx, (spin_cnt - sleep_cnt));
+#endif
return (error);
}
@@ -648,12 +681,20 @@
int contested = 0;
uintptr_t x;
int error = 0;
+#ifdef KDTRACE_HOOKS
+ uint64_t spin_cnt = 0;
+ uint64_t sleep_cnt = 0;
+ int64_t sleep_time = 0;
+#endif
/*
* As with rwlocks, we don't make any attempt to try to block
* shared locks once there is an exclusive waiter.
*/
for (;;) {
+#ifdef KDTRACE_HOOKS
+ spin_cnt++;
+#endif
x = sx->sx_lock;
/*
@@ -694,8 +735,12 @@
__func__, sx, owner);
GIANT_SAVE();
while (SX_OWNER(sx->sx_lock) == x &&
- TD_IS_RUNNING(owner))
+ TD_IS_RUNNING(owner)) {
+#ifdef KDTRACE_HOOKS
+ spin_cnt++;
+#endif
cpu_spinwait();
+ }
continue;
}
}
@@ -756,7 +801,9 @@
if (LOCK_LOG_TEST(&sx->lock_object, 0))
CTR2(KTR_LOCK, "%s: %p blocking on sleep queue",
__func__, sx);
-
+#ifdef KDTRACE_HOOKS
+ sleep_time -= lockstat_nsecs();
+#endif
GIANT_SAVE();
sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
SLEEPQ_SX | ((opts & SX_INTERRUPTIBLE) ?
@@ -777,9 +824,17 @@
CTR2(KTR_LOCK, "%s: %p resuming from sleep queue",
__func__, sx);
}
- if (error == 0)
+#ifdef KDTRACE_HOOKS
+ if (sleep_time != 0)
+ LOCKSTAT_RECORD1(LS_SX_XLOCK_BLOCK, sx, sleep_time);
+ if (spin_cnt > sleep_cnt)
+ LOCKSTAT_RECORD1(LS_SX_XLOCK_SPIN, sx, (spin_cnt - sleep_cnt));
+#endif
+ if (error == 0) {
lock_profile_obtain_lock_success(&sx->lock_object, contested,
waittime, file, line);
+ LOCKSTAT_RECORD0(LS_SX_SLOCK_ACQUIRE, sx);
+ }
GIANT_RESTORE();
return (error);
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/kern/sched_4bsd.c 2008-04-25 16:35:47.000000000 +1000
+++ /u/p4/dtrace/src/sys/kern/sched_4bsd.c 2008-04-25 16:42:15.000000000 +1000
@@ -37,6 +37,7 @@
#include "opt_hwpmc_hooks.h"
#include "opt_sched.h"
+#include "opt_kdtrace.h"
#include
#include
@@ -61,6 +62,12 @@
#include
#endif
+#ifdef KDTRACE_HOOKS
+#include
+int dtrace_vtime_active;
+dtrace_vtime_switch_func_t dtrace_vtime_switch_func;
+#endif
+
/*
* INVERSE_ESTCPU_WEIGHT is only suitable for statclock() frequencies in
* the range 100-256 Hz (approximately).
@@ -962,6 +969,16 @@
#endif
/* I feel sleepy */
lock_profile_release_lock(&sched_lock.lock_object);
+#ifdef KDTRACE_HOOKS
+ /*
+ * If DTrace has set the active vtime enum to anything
+ * other than INACTIVE (0), then it should have set the
+ * function to call.
+ */
+ if (dtrace_vtime_active)
+ (*dtrace_vtime_switch_func)(newtd);
+#endif
+
cpu_switch(td, newtd, td->td_lock);
lock_profile_obtain_lock_success(&sched_lock.lock_object,
0, 0, __FILE__, __LINE__);
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/kern/sched_ule.c 2008-04-25 16:35:47.000000000 +1000
+++ /u/p4/dtrace/src/sys/kern/sched_ule.c 2008-04-25 16:42:17.000000000 +1000
@@ -39,6 +39,7 @@
__FBSDID("$FreeBSD: src/sys/kern/sched_ule.c,v 1.244 2008/04/25 05:18:49 jeff Exp $");
#include "opt_hwpmc_hooks.h"
+#include "opt_kdtrace.h"
#include "opt_sched.h"
#include
@@ -69,6 +70,12 @@
#include
#endif
+#ifdef KDTRACE_HOOKS
+#include
+int dtrace_vtime_active;
+dtrace_vtime_switch_func_t dtrace_vtime_switch_func;
+#endif
+
#include
#include
@@ -1823,6 +1830,17 @@
#endif
lock_profile_release_lock(&TDQ_LOCKPTR(tdq)->lock_object);
TDQ_LOCKPTR(tdq)->mtx_lock = (uintptr_t)newtd;
+
+#ifdef KDTRACE_HOOKS
+ /*
+ * If DTrace has set the active vtime enum to anything
+ * other than INACTIVE (0), then it should have set the
+ * function to call.
+ */
+ if (dtrace_vtime_active)
+ (*dtrace_vtime_switch_func)(newtd);
+#endif
+
cpu_switch(td, newtd, mtx);
/*
* We may return from cpu_switch on a different cpu. However,
=====================================================================
--ditto--
---------------------------------------------------------------------
New file: src/sys/kern/kern_lockstat.c
---------------------------------------------------------------------
/*-
* Copyright 2008 Stacey Son
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*
* Backend for the lock tracing (lockstat) kernel support. This is required
* to allow a module to load even though DTrace kernel support may not be
* present.
*
*/
#include "opt_kdtrace.h"
#ifdef KDTRACE_HOOKS
#include
#include
#include
/*
* The following must match the type definition of dtrace_probe. It is
* defined this way to avoid having to rely on CDDL code.
*/
uint32_t lockstat_probemap[LS_NPROBES];
void (*lockstat_probe_func)(uint32_t, uintptr_t, uintptr_t,
uintptr_t, uintptr_t, uintptr_t);
uint64_t
lockstat_nsecs(void)
{
struct bintime bt;
uint64_t ns;
binuptime(&bt);
ns = bt.sec * (uint64_t)1000000000;
ns += ((uint64_t)1000000000 * (uint32_t)(bt.frac >> 32)) >> 32;
return (ns);
}
#endif /* KDTRACE_HOOKS */
=====================================================================
--ditto--
---------------------------------------------------------------------
New file: src/sys/modules/cyclic_test/Makefile
---------------------------------------------------------------------
# $FreeBSD#
.PATH: ${.CURDIR}/../../cddl/cyclic
KMOD= cyclic_test
SRCS= cyclic_test.c
#SRCS+= bus_if.h device_if.h vnode_if.h
CFLAGS+= -I${.CURDIR}/../../cddl/compat/opensolaris \
-I${.CURDIR}/../../cddl/contrib/opensolaris/uts/common \
-I${.CURDIR}/../..
IGNORE_PRAGMA= 1
.include
=====================================================================
(Not Specified)
---------------------------------------------------------------------
--- /u/freebsd/head/src/sys/netinet/sctputil.c 2008-05-22 09:23:37.000000000 +1000
+++ /u/p4/dtrace/src/sys/netinet/sctputil.c 2008-05-22 09:17:53.000000000 +1000
@@ -33,6 +33,8 @@
#include
__FBSDID("$FreeBSD: src/sys/netinet/sctputil.c,v 1.77 2008/05/21 16:51:21 rrs Exp $");
+#include "opt_kdtrace.h"
+
#include
#include
#include
@@ -50,9 +52,18 @@
#include
#include
#include
+#include
#define NUMBER_OF_MTU_SIZES 18
+SDT_PROVIDER_DEFINE(sctp);
+SDT_PROBE_DEFINE(sctp, kernel, log , sb);
+SDT_PROBE_ARGTYPE(sctp, kernel, log, sb, 0, "struct sockbuf *");
+SDT_PROBE_ARGTYPE(sctp, kernel, log, sb, 1, "struct sctp_cwnd_log *");
+SDT_PROBE_ARGTYPE(sctp, kernel, log, sb, 2, "int");
+SDT_PROBE_ARGTYPE(sctp, kernel, log, sb, 3, "int");
+SDT_PROBE_DEFINE(sctp, kernel, log , closing);
+SDT_PROBE_ARGTYPE(sctp, kernel, log, closing, 0, "struct sctp_cwnd_log *");
#ifndef KTR_SCTP
#define KTR_SCTP KTR_SUBSYS
@@ -71,6 +82,7 @@
else
sctp_clog.x.sb.stcb_sbcc = 0;
sctp_clog.x.sb.incr = incr;
+ SDT_PROBE(sctp, kernel, log, sb, sb, &sctp_clog, from, incr, 0);
SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_SB,
from,
@@ -95,6 +107,7 @@
sctp_clog.x.close.state = 0;
}
sctp_clog.x.close.loc = loc;
+ SDT_PROBE(sctp, kernel, log, closing, &sctp_clog, 0, 0, 0, 0);
SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_CLOSE,
0,
=====================================================================
--ditto--
---------------------------------------------------------------------
New file: src/sys/sys/lockstat.h
---------------------------------------------------------------------
/*-
* Copyright (c) 2008 Stacey Son
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*
* DTrace lockstat provider definitions
*
*/
#ifndef _SYS_LOCKSTAT_H
#define _SYS_LOCKSTAT_H
#ifdef _KERNEL
/*
* Spin Locks
*/
#define LS_MTX_SPIN_LOCK_ACQUIRE 0
#define LS_MTX_SPIN_LOCK_SPIN 1
#define LS_MTX_SPIN_UNLOCK_RELEASE 2
/*
* Adaptive Locks
*/
#define LS_MTX_LOCK_ACQUIRE 3
#define LS_MTX_LOCK_BLOCK 4
#define LS_MTX_LOCK_SPIN 5
#define LS_MTX_UNLOCK_RELEASE 6
#define LS_MTX_TRYLOCK_ACQUIRE 7
/*
* Reader/Writer Locks
*/
#define LS_RW_RLOCK_ACQUIRE 7
#define LS_RW_RLOCK_BLOCK 8
#define LS_RW_RLOCK_SPIN 9
#define LS_RW_RUNLOCK_RELEASE 10
#define LS_RW_WLOCK_ACQUIRE 11
#define LS_RW_WLOCK_BLOCK 12
#define LS_RW_WLOCK_SPIN 13
#define LS_RW_WUNLOCK_RELEASE 14
#define LS_RW_TRYUPGRADE_UPGRADE 15
#define LS_RW_DOWNGRADE_DOWNGRADE 16
/*
* Shared/Exclusive Locks
*/
#define LS_SX_SLOCK_ACQUIRE 17
#define LS_SX_SLOCK_BLOCK 18
#define LS_SX_SLOCK_SPIN 19
#define LS_SX_SUNLOCK_RELEASE 20
#define LS_SX_XLOCK_ACQUIRE 21
#define LS_SX_XLOCK_BLOCK 22
#define LS_SX_XLOCK_SPIN 23
#define LS_SX_XUNLOCK_RELEASE 24
#define LS_SX_TRYUPGRADE_UPGRADE 25
#define LS_SX_DOWNGRADE_DOWNGRADE 26
/*
* Thread Locks
*/
#define LS_THREAD_LOCK_SPIN 27
/*
* Lockmanager Locks
* According to locking(9) Lockmgr locks are "Largely deprecated"
* so no support for these have been added in the lockstat provider.
*/
#define LS_NPROBES 28
#define LS_MTX_LOCK "mtx_lock"
#define LS_MTX_UNLOCK "mtx_unlock"
#define LS_MTX_SPIN_LOCK "mtx_lock_spin"
#define LS_MTX_SPIN_UNLOCK "mtx_unlock_spin"
#define LS_MTX_TRYLOCK "mtx_trylock"
#define LS_RW_RLOCK "rw_rlock"
#define LS_RW_WLOCK "rw_wlock"
#define LS_RW_RUNLOCK "rw_runlock"
#define LS_RW_WUNLOCK "rw_wunlock"
#define LS_RW_TRYUPGRADE "rw_try_upgrade"
#define LS_RW_DOWNGRADE "rw_downgrade"
#define LS_SX_SLOCK "sx_slock"
#define LS_SX_XLOCK "sx_xlock"
#define LS_SX_SUNLOCK "sx_sunlock"
#define LS_SX_XUNLOCK "sx_xunlock"
#define LS_SX_TRYUPGRADE "sx_try_upgrade"
#define LS_SX_DOWNGRADE "sx_downgrade"
#define LS_THREAD_LOCK "thread_lock"
#define LS_ACQUIRE "acquire"
#define LS_RELEASE "release"
#define LS_SPIN "spin"
#define LS_BLOCK "block"
#define LS_UPGRADE "upgrade"
#define LS_DOWNGRADE "downgrade"
#define LS_TYPE_ADAPTIVE "adaptive"
#define LS_TYPE_SPIN "spin"
#define LS_TYPE_THREAD "thread"
#define LS_TYPE_RW "rw"
#define LS_TYPE_SX "sx"
#define LSA_ACQUIRE (LS_TYPE_ADAPTIVE "-" LS_ACQUIRE)
#define LSA_RELEASE (LS_TYPE_ADAPTIVE "-" LS_RELEASE)
#define LSA_SPIN (LS_TYPE_ADAPTIVE "-" LS_SPIN)
#define LSA_BLOCK (LS_TYPE_ADAPTIVE "-" LS_BLOCK)
#define LSS_ACQUIRE (LS_TYPE_SPIN "-" LS_ACQUIRE)
#define LSS_RELEASE (LS_TYPE_SPIN "-" LS_RELEASE)
#define LSS_SPIN (LS_TYPE_SPIN "-" LS_SPIN)
#define LSR_ACQUIRE (LS_TYPE_RW "-" LS_ACQUIRE)
#define LSR_RELEASE (LS_TYPE_RW "-" LS_RELEASE)
#define LSR_BLOCK (LS_TYPE_RW "-" LS_BLOCK)
#define LSR_SPIN (LS_TYPE_RW "-" LS_SPIN)
#define LSR_UPGRADE (LS_TYPE_RW "-" LS_UPGRADE)
#define LSR_DOWNGRADE (LS_TYPE_RW "-" LS_DOWNGRADE)
#define LSX_ACQUIRE (LS_TYPE_SX "-" LS_ACQUIRE)
#define LSX_RELEASE (LS_TYPE_SX "-" LS_RELEASE)
#define LSX_BLOCK (LS_TYPE_SX "-" LS_BLOCK)
#define LSX_SPIN (LS_TYPE_SX "-" LS_SPIN)
#define LSX_UPGRADE (LS_TYPE_SX "-" LS_UPGRADE)
#define LSX_DOWNGRADE (LS_TYPE_SX "-" LS_DOWNGRADE)
#define LST_SPIN (LS_TYPE_THREAD "-" LS_SPIN)
/*
* The following must match the type definition of dtrace_probe. It is
* defined this way to avoid having to rely on CDDL code.
*/
extern uint32_t lockstat_probemap[LS_NPROBES];
typedef void (*lockstat_probe_func_t)(uint32_t, uintptr_t arg0, uintptr_t arg1,
uintptr_t arg2, uintptr_t arg3, uintptr_t arg4);
extern lockstat_probe_func_t lockstat_probe_func;
extern uint64_t lockstat_nsecs(void);
#ifdef KDTRACE_HOOKS
/*
* Macros to record lockstat probes.
*/
#define LOCKSTAT_RECORD4(probe, lp, arg1, arg2, arg3, arg4) \
do { \
uint32_t id; \
if ((id = lockstat_probemap[(probe)])) { \
(*lockstat_probe_func)(id, (uintptr_t)(lp), (arg1), \
(arg2), (arg3), (arg4)); \
} \
} while (0)
#define LOCKSTAT_RECORD(probe, lp, arg1) \
LOCKSTAT_RECORD4(probe, lp, arg1, 0, 0, 0)
#define LOCKSTAT_RECORD0(probe, lp) \
LOCKSTAT_RECORD4(probe, lp, 0, 0, 0, 0)
#define LOCKSTAT_RECORD1(probe, lp, arg1) \
LOCKSTAT_RECORD4(probe, lp, arg1, 0, 0, 0)
#define LOCKSTAT_RECORD2(probe, lp, arg1, arg2) \
LOCKSTAT_RECORD4(probe, lp, arg1, arg2, 0, 0)
#define LOCKSTAT_RECORD3(probe, lp, arg1, arg2, arg3) \
LOCKSTAT_RECORD4(probe, lp, arg1, arg2, arg3, 0)
#else /* !KDTRACE_HOOKS */
#define LOCKSTAT_RECORD(probe, lp, arg1)
#define LOCKSTAT_RECORD0(probe, lp)
#define LOCKSTAT_RECORD1(probe, lp, arg1)
#define LOCKSTAT_RECORD2(probe, lp, arg1, arg2)
#define LOCKSTAT_RECORD3(probe, lp, arg1, arg2, arg3)
#define LOCKSTAT_RECORD4(probe, lp, arg1, arg2, arg3, arg4)
#endif /* !KDTRACE_HOOKS */
#endif /* _KERNEL */
#endif /* _SYS_LOCKSTAT_H */