===================================================================== (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 */