--- a/usr/src/cmd/dtrace/dtrace.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/dtrace.c Wed Jul 25 19:05:31 2012 -0400
@@ -23,8 +23,9 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
#include <sys/types.h>
#include <sys/stat.h>
@@ -1339,6 +1340,7 @@
(void) dtrace_setopt(g_dtp, "bufsize", "4m");
(void) dtrace_setopt(g_dtp, "aggsize", "4m");
+ (void) dtrace_setopt(g_dtp, "temporal", "yes");
/*
* If -G is specified, enable -xlink=dynamic and -xunodefs to permit
--- a/usr/src/cmd/dtrace/test/cmd/scripts/dtest.pl Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/cmd/scripts/dtest.pl Wed Jul 25 19:05:31 2012 -0400
@@ -27,6 +27,7 @@
#
# Copyright (c) 2011, Joyent, Inc. All rights reserved.
+# Copyright (c) 2012 by Delphix. All rights reserved.
#
require 5.8.4;
@@ -612,6 +613,8 @@
die "$PNAME: failed to open $PNAME.$$.log: $!\n"
unless (!$opt_l || open(LOG, ">$PNAME.$$.log"));
+$ENV{'DTRACE_DEBUG_REGSET'} = 'true';
+
if ($opt_g) {
$ENV{'UMEM_DEBUG'} = 'default,verbose';
$ENV{'UMEM_LOGGING'} = 'fail,contents';
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/aggs/tst.sizedkeys.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,35 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#pragma D option quiet
+
+/*
+ * Make sure the sizes of compatible keys doesn't affect the sort order.
+ */
+
+BEGIN
+{
+ @[(int)1, 0] = sum(10);
+ @[(uint64_t)2, 0] = sum(20);
+ @[(int)3, 0] = sum(30);
+ @[(uint64_t)4, 0] = sum(40);
+ printa(@);
+
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/aggs/tst.sizedkeys.d.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,6 @@
+
+ 1 0 10
+ 2 0 20
+ 3 0 30
+ 4 0 40
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.basics.d.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,8 @@
+The value of i is 6
+The value of i is 18
+The value of i is 72
+The value of i is 25920
+The value of i is 935761216
+The value of i is -91738734
+The value of i is -91738729
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.compcast.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,50 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Test compile-time casting between integer types of different size.
+ */
+
+#pragma D option quiet
+
+int64_t x;
+
+BEGIN
+{
+ x = (int32_t)(int16_t)0xfff0;
+ printf("%16x %20d %20u\n", x, x, x);
+ x = (int32_t)(uint16_t)0xfff0;
+ printf("%16x %20d %20u\n", x, x, x);
+ x = (uint32_t)(int16_t)0xfff0;
+ printf("%16x %20d %20u\n", x, x, x);
+ x = (uint32_t)(uint16_t)0xfff0;
+ printf("%16x %20d %20u\n", x, x, x);
+ printf("\n");
+
+ x = (int16_t)(int32_t)0xfff0;
+ printf("%16x %20d %20u\n", x, x, x);
+ x = (int16_t)(uint32_t)0xfff0;
+ printf("%16x %20d %20u\n", x, x, x);
+ x = (uint16_t)(int32_t)0xfff0;
+ printf("%16x %20d %20u\n", x, x, x);
+ x = (uint16_t)(uint32_t)0xfff0;
+ printf("%16x %20d %20u\n", x, x, x);
+
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.compcast.d.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,10 @@
+fffffffffffffff0 -16 18446744073709551600
+ fff0 65520 65520
+ fffffff0 4294967280 4294967280
+ fff0 65520 65520
+
+fffffffffffffff0 -16 18446744073709551600
+fffffffffffffff0 -16 18446744073709551600
+ fff0 65520 65520
+ fff0 65520 65520
+
--- a/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.complex.d Tue Jul 24 03:56:16 2012 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * 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 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * ASSERTION:
- * Complex expressions.
- * Call complex expressions and make sure test succeeds.
- * Match expected output in tst.complex.d.out
- *
- * SECTION: Types, Operators, and Expressions/Arithmetic Operators
- *
- */
-
-#pragma D option quiet
-
-BEGIN
-{
- i = 0;
- i = i++ + ++i;
- printf("The value of i is %d\n", i);
- i = i-- - --i;
- printf("The value of i is %d\n", i);
- i = i-- + ++i;
- printf("The value of i is %d\n", i);
- i += i++ + -- i + ++i - ++i * i ;
- printf("The value of i is %d\n", i);
- i -= i++ * 3;
- printf("The value of i is %d\n", i);
- i = i++/i--+i++-++i-++i;
- printf("The value of i is %d\n", i);
- exit (0);
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.compnarrowassign.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,36 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Test narrowing at assignment.
+ */
+
+#pragma D option quiet
+
+uint16_t x;
+uint32_t y;
+
+BEGIN
+{
+ x = 0xbeefcafe;
+ y = x;
+ printf("%x", y); /* where's the beef? */
+
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.compnarrowassign.d.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,1 @@
+cafe
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.execcast.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,52 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Test execution-time casting between integer types of different size.
+ */
+
+#pragma D option quiet
+
+int64_t x;
+
+BEGIN
+{
+ z = 0xfff0;
+
+ x = (int32_t)(int16_t)z;
+ printf("%16x %20d %20u\n", x, x, x);
+ x = (int32_t)(uint16_t)z;
+ printf("%16x %20d %20u\n", x, x, x);
+ x = (uint32_t)(int16_t)z;
+ printf("%16x %20d %20u\n", x, x, x);
+ x = (uint32_t)(uint16_t)z;
+ printf("%16x %20d %20u\n", x, x, x);
+ printf("\n");
+
+ x = (int16_t)(int32_t)z;
+ printf("%16x %20d %20u\n", x, x, x);
+ x = (int16_t)(uint32_t)z;
+ printf("%16x %20d %20u\n", x, x, x);
+ x = (uint16_t)(int32_t)z;
+ printf("%16x %20d %20u\n", x, x, x);
+ x = (uint16_t)(uint32_t)z;
+ printf("%16x %20d %20u\n", x, x, x);
+
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.execcast.d.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,10 @@
+fffffffffffffff0 -16 18446744073709551600
+ fff0 65520 65520
+ fffffff0 4294967280 4294967280
+ fff0 65520 65520
+
+fffffffffffffff0 -16 18446744073709551600
+fffffffffffffff0 -16 18446744073709551600
+ fff0 65520 65520
+ fff0 65520 65520
+
--- a/usr/src/cmd/dtrace/test/tst/common/buffering/tst.fill1.d Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/buffering/tst.fill1.d Wed Jul 25 19:05:31 2012 -0400
@@ -23,26 +23,29 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/*
* ASSERTION:
* Positive test for fill buffer policy.
*
* SECTION: Buffers and Buffering/fill Policy;
- * Buffers and Buffering/Buffer Sizes;
+ * Buffers and Buffering/Buffer Sizes;
* Options and Tunables/bufsize;
* Options and Tunables/bufpolicy;
* Options and Tunables/statusrate
*/
/*
- * This is a brute-force way of testing fill buffers. We assume that each
- * printf() stores 8 bytes. Because each fill buffer is per-CPU, we must
- * fill up our buffer in one series of enablings on a single CPU.
+ * This is a brute-force way of testing fill buffers. We assume that
+ * each printf() stores 16 bytes (4x 32-bit words for EPID, timestamp
+ * lo, timestamp hi, and the variable i). Because each fill buffer is
+ * per-CPU, we must fill up our buffer in one series of enablings on a
+ * single CPU.
*/
#pragma D option bufpolicy=fill
-#pragma D option bufsize=64
+#pragma D option bufsize=128
#pragma D option statusrate=10ms
#pragma D option quiet
--- a/usr/src/cmd/dtrace/test/tst/common/buffering/tst.ring3.d Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/buffering/tst.ring3.d Wed Jul 25 19:05:31 2012 -0400
@@ -23,8 +23,9 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/*
* ASSERTION:
@@ -37,19 +38,20 @@
*/
/*
- * We make some regrettable assumptions about the implementation in this test.
- * First, we assume that each entry for the printf() of an int takes _exactly_
- * eight bytes (four bytes for the EPID, four bytes for the payload). Second,
- * we assume that by allocating storage for n + 1 records, we will get exactly
- * n. Here is why: the final predicate that evaluates to false will reserve
- * space that it won't use. This act of reservation will advance the wrapped
- * offset. That record won't be subsequently used, but the wrapped offset has
- * advanced. (And in this case, that old record is clobbered by the exit()
- * anyway.) Thirdly: we rely on t_cpu/cpu_id. Finally: we rely on being
- * able to run on the CPU that we first ran on.
+ * We make some regrettable assumptions about the implementation in this
+ * test. First, we assume that each entry for the printf() of an int
+ * takes _exactly_ 16 bytes (4 bytes for the EPID, 8 bytes for the
+ * timestamp, 4 bytes for the payload). Second, we assume that by
+ * allocating storage for n + 1 records, we will get exactly n. Here is
+ * why: the final predicate that evaluates to false will reserve space
+ * that it won't use. This act of reservation will advance the wrapped
+ * offset. That record won't be subsequently used, but the wrapped
+ * offset has advanced. (And in this case, that old record is clobbered
+ * by the exit() anyway.) Thirdly: we rely on t_cpu/cpu_id. Finally:
+ * we rely on being able to run on the CPU that we first ran on.
*/
#pragma D option bufpolicy=ring
-#pragma D option bufsize=40
+#pragma D option bufsize=80
#pragma D option quiet
int n;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/cg/err.D_NOREG.noreg.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,41 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Compile some code that requires exactly 9 registers. This should run out
+ * of registers.
+ *
+ * Changes to the code generator might cause this test to succeeed in which
+ * case the code should be changed to another sequence that exhausts the
+ * available internal registers.
+ *
+ * Note that this and err.baddif.d should be kept in sync.
+ */
+
+BEGIN
+{
+ a = 4;
+ trace((a + a) * ((a + a) * ((a + a) * ((a + a) * ((a + a) *
+ ((a + a) * (a + a)))))));
+}
+
+BEGIN
+{
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/cg/err.baddif.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,44 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Compile some code that requires exactly 9 registers. This should generate
+ * invalid DIF because the kernel will flag the fact that we're using more
+ * registers than are available internally.
+ *
+ * Changes to the code generator might cause this test to succeeed in which
+ * case the code should be changed to another sequence that exhausts the
+ * available internal registers.
+ *
+ * Note that this and err.D_NOREG.noreg.d should be kept in sync.
+ */
+
+#pragma D option iregs=9
+
+BEGIN
+{
+ a = 4;
+ trace((a + a) * ((a + a) * ((a + a) * ((a + a) * ((a + a) *
+ ((a + a) * (a + a)))))));
+}
+
+BEGIN
+{
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/err.D_PRAGMA_OPTSET.setfromscript.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,25 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#pragma D option setenv=balloon=something_bad_happens
+
+BEGIN
+{
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/err.D_PRAGMA_OPTSET.unsetfromscript.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,25 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#pragma D option unsetenv=rectalexambot
+
+BEGIN
+{
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.ld_nolazyload.ksh Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Check that the LD_NOLAZYLOAD variable is set to 1 as expected.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+
+$dtrace -q -Z -n doogle -c 'printenv LD_NOLAZYLOAD'
+
+exit $?
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.ld_nolazyload.ksh.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,2 @@
+1
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.setenv1.ksh Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Reset an environment variable we already know to be set.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+
+$dtrace -q -Z -n doogle -xsetenv=LD_NOLAZYLOAD=0 -c 'printenv LD_NOLAZYLOAD'
+
+exit $?
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.setenv1.ksh.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,2 @@
+0
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.setenv2.ksh Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Test setting a variable that we isn't already set.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+
+$dtrace -q -Z -n doogle -xsetenv=CORPORATIONS=PEOPLE -c 'printenv CORPORATIONS'
+
+exit $?
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.setenv2.ksh.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,2 @@
+PEOPLE
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.unsetenv1.ksh Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Test unsetting a variable we know to be set.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+
+$dtrace -q -Z -n doogle -xunsetenv=LD_NOLAZYLOAD -c 'printenv LD_NOLAZYLOAD'
+
+exit $?
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.unsetenv1.ksh.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,1 @@
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.unsetenv2.ksh Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Test invalid syntax to the unsetenv option.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+
+$dtrace -q -Z -n doogle -xunsetenv=ed=screven -c 'true' 2>&1
+
+[[ $? -eq 1 ]] && exit 0
+
+exit 1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.unsetenv2.ksh.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,1 @@
+dtrace: failed to set -x unsetenv: Invalid value for specified option
--- a/usr/src/cmd/dtrace/test/tst/common/pid/tst.newprobes.ksh Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/pid/tst.newprobes.ksh Wed Jul 25 19:05:31 2012 -0400
@@ -24,7 +24,9 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
#
if [ $# != 1 ]; then
@@ -49,13 +51,13 @@
tick-1s
/(i % 2) == 0/
{
- system("dtrace -c date -ln 'pid\$target::main:entry' >/dev/null");
+ system("dtrace -c date -n 'pid\$target::main:entry' >/dev/null");
}
tick-1s
/(i % 2) == 1/
{
- system("dtrace -c date -ln 'pid\$target::main:return' >/dev/null");
+ system("dtrace -c date -n 'pid\$target::main:return' >/dev/null");
}
EOF
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/pointers/tst.assigncast1.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,28 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+BEGIN
+{
+ *((int *)alloca(4)) = 1;
+}
+
+BEGIN
+{
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/pointers/tst.assigncast2.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,29 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+BEGIN
+{
+ this->a = alloca(4);
+ *((int *)this->a) = 1;
+}
+
+BEGIN
+{
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/pragma/tst.temporal.ksh Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,106 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+############################################################################
+# ASSERTION:
+# temporal option causes output to be sorted
+#
+# SECTION: Pragma
+#
+# NOTES: The temporal option has no effect on a single-CPU system, so
+# this needs to be run on a multi-CPU system to effectively test the
+# temporal option.
+#
+############################################################################
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+file=/tmp/out.$$
+
+rm -f $file
+
+$dtrace -o $file -c 'sleep 3' -s /dev/stdin <<EOF
+ #pragma D option quiet
+ #pragma D option temporal
+
+ BEGIN
+ {
+ @lines = count();
+ printf("0 begin\n");
+ }
+
+ END
+ {
+ /* Bump @lines every time we print a line. */
+ @lines = count();
+ printf("%u end\n", timestamp);
+ @lines = count();
+ printa("99999999999999999 lines %@u\n", @lines);
+ }
+
+ profile-97hz
+ {
+ @lines = count();
+ printf("%u\n", timestamp);
+ }
+EOF
+
+status=$?
+if [ "$status" -ne 0 ]; then
+ echo $tst: dtrace failed
+ exit $status
+fi
+
+# dtrace outputs a blank line at the end, which will sort to the beginning,
+# so use head to remove the blank line.
+head -n -1 $file > $file.2
+
+sort -n $file.2 | diff $file.2 -
+status=$?
+if [ "$status" -ne 0 ]; then
+ echo $tst: output is not sorted
+ exit $status
+fi
+
+head -n 1 $file.2 | grep begin >/dev/null
+status=$?
+if [ "$status" -ne 0 ]; then
+ echo $tst: begin probe did not fire
+ exit $status
+fi
+
+tail -n 2 $file.2 | grep end >/dev/null
+status=$?
+if [ "$status" -ne 0 ]; then
+ echo $tst: end probe did not fire
+ exit $status
+fi
+
+if [ $(tail -n 1 $file.2 | cut -f3 -d ' ') -ne \
+ $(wc -l $file.2) ]; then
+ echo $tst: incorrect number of lines output
+ exit 1
+fi
+
+exit $status
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/pragma/tst.temporal2.ksh Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,102 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+############################################################################
+# ASSERTION:
+# temporal option causes output to be sorted, even when some
+# buffers are empty
+#
+# SECTION: Pragma
+#
+# NOTES: The temporal option has no effect on a single-CPU system, so
+# this needs to be run on a multi-CPU system to effectively test the
+# temporal option.
+#
+############################################################################
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+file=/tmp/out.$$
+
+rm -f $file
+
+$dtrace -o $file -s /dev/stdin <<EOF
+ #pragma D option quiet
+ #pragma D option destructive
+ #pragma D option temporal
+ #pragma D option switchrate=1000hz
+
+ /*
+ * Use two enablings of the same probe, so that cpu 0 will always
+ * record its data just a little bit before the other cpus.
+ * We don't want to use the chill() action in the same enabling
+ * that we record the timestamp, because chill() causes the
+ * timestamp to be re-read, and thus not match the timestamp
+ * which libdtrace uses to sort the records.
+ */
+
+ profile-401
+ /cpu == 0/
+ {
+ printf("%d\n", timestamp);
+ }
+
+ profile-401
+ /cpu != 0/
+ {
+ chill(1000); /* one microsecond */
+ }
+
+ profile-401
+ /cpu != 0/
+ {
+ printf("%d\n", timestamp);
+ }
+
+ tick-1s
+ /k++ == 10/
+ {
+ printf("%d\n", timestamp);
+ exit(0);
+ }
+EOF
+
+status=$?
+if [ "$status" -ne 0 ]; then
+ echo $tst: dtrace failed
+ exit $status
+fi
+
+# dtrace outputs a blank line at the end, which will sort to the beginning,
+# so use grep to remove the blank line.
+head -n -1 $file > $file.2
+
+sort -n $file.2 | diff $file.2 -
+status=$?
+if [ "$status" -ne 0 ]; then
+ echo $tst: output is not sorted
+ exit $status
+fi
+
+exit $status
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/pragma/tst.temporal3.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,48 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * This test excercises the "remnant" handling of the temporal option.
+ * At the end of one pass of retrieving and printing data from all CPUs,
+ * some unprocessed data will remain, because its timestamp is after the
+ * time covered by all CPUs' buffers. This unprocessed data is
+ * rearranged in a more space-efficient manner. If this is done
+ * incorrectly, an alignment error may occur. To test this, we use a
+ * high-frequency probe so that data will be recorded in subsequent
+ * CPU's buffers after the first CPU's buffer is obtained. The
+ * combination of data traced here (a 8-byte value and a 4-byte value)
+ * is effective to cause alignment problems with an incorrect
+ * implementation.
+ *
+ * This test needs to be run on a multi-CPU system to be effective.
+ */
+
+#pragma D option quiet
+#pragma D option temporal
+
+profile-4997
+{
+ printf("%u %u", 1ULL, 2);
+}
+
+tick-1
+/i++ == 10/
+{
+ exit(0);
+}
--- a/usr/src/cmd/dtrace/test/tst/common/predicates/tst.predcache.ksh Tue Jul 24 03:56:16 2012 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-#
-# 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 2007 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-
-unload()
-{
- #
- # Get the list of services whose processes have USDT probes. Ideally
- # it would be possible to unload the fasttrap provider while USDT
- # probes exist -- once that fix is integrated, this hack can go away
- # We create two lists -- one of regular SMF services and one of legacy
- # services -- since each must be enabled and disabled using a specific
- # mechanism.
- #
- pids=$(dtrace -l | \
- perl -ne 'print "$1\n" if (/^\s*\S+\s+\S*\D(\d+)\s+/);' | \
- sort | uniq | tr '\n' ',')
-
- ctids=$(ps -p $pids -o ctid | tail +2 | sort | uniq)
- svcs=
- lrcs=
-
- for ct in $ctids
- do
- line=$(svcs -o fmri,ctid | grep " $ct\$")
- svc=$(echo $line | cut -d' ' -f1)
-
- if [[ $(svcs -Ho STA $svc) == "LRC" ]]; then
- lrc=$(svcs -Ho SVC $svc | tr _ '?')
- lrcs="$lrcs $lrc"
- else
- svcs="$svcs $svc"
- fi
- done
-
- for svc in $svcs
- do
- svcadm disable -ts $svc
- done
-
- for lrc in $lrcs
- do
- #
- # Does it seem a little paternalistic that lsvcrun requires
- # this environment variable to be set? I'd say so...
- #
- SMF_RESTARTER=svc:/system/svc/restarter:default \
- /lib/svc/bin/lsvcrun $lrc stop
- done
-
- modunload -i 0
- modunload -i 0
- modunload -i 0
- modinfo | grep dtrace
- success=$?
-
- for svc in $svcs
- do
- svcadm enable -ts $svc
- done
-
- for lrc in $lrcs
- do
- SMF_RESTARTER=svc:/system/svc/restarter:default \
- /lib/svc/bin/lsvcrun $lrc start
- done
-
- if [ ! $success ]; then
- echo $tst: could not unload dtrace
- exit 1
- fi
-}
-
-script1()
-{
- $dtrace -s /dev/stdin <<EOF
- syscall:::entry
- /pid != $ppid/
- {
- @a[probefunc] = count();
- }
-
- tick-1sec
- /i++ == 5/
- {
- exit(0);
- }
-EOF
-}
-
-script2()
-{
- $dtrace -s /dev/stdin <<EOF
-
- #pragma D option statusrate=1ms
-
- syscall:::entry
- /pid == $ppid/
- {
- ttl++;
- }
-
- tick-1sec
- /i++ == 5/
- {
- exit(2);
- }
-
- END
- /ttl/
- {
- printf("success; ttl is %d", ttl);
- exit(0);
- }
-
- END
- /ttl == 0/
- {
- printf("error -- total should be non-zero");
- exit(1);
- }
-EOF
-}
-
-if [ $# != 1 ]; then
- echo expected one argument: '<'dtrace-path'>'
- exit 2
-fi
-
-ppid=$$
-dtrace=$1
-
-unload
-script1 &
-child=$!
-
-let waited=0
-
-while [ "$waited" -lt 5 ]; do
- seconds=`date +%S`
-
- if [ "$seconds" -ne "$last" ]; then
- last=$seconds
- let waited=waited+1
- fi
-done
-
-wait $child
-status=$?
-
-if [ "$status" -ne 0 ]; then
- echo $tst: first dtrace failed
- exit $status
-fi
-
-unload
-script2 &
-child=$!
-
-let waited=0
-
-while [ "$waited" -lt 10 ]; do
- seconds=`date +%S`
-
- if [ "$seconds" -ne "$last" ]; then
- last=$seconds
- let waited=waited+1
- fi
-done
-
-wait $child
-status=$?
-
-exit $status
--- a/usr/src/cmd/dtrace/test/tst/common/print/err.D_PRINT_DYN.bad.d Tue Jul 24 03:56:16 2012 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * 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 (c) 2011 by Delphix. All rights reserved.
- */
-
-BEGIN
-{
- print(*curpsinfo);
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/print/tst.dyn.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,28 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+BEGIN
+{
+ print(*curpsinfo);
+}
+
+BEGIN
+{
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/print/tst.xlate.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,42 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#pragma D option quiet
+
+typedef struct pancakes {
+ int i;
+ string s;
+ timespec_t t;
+} pancakes_t;
+
+translator pancakes_t < void *V > {
+ i = 2 * 10;
+ s = strjoin("I like ", "pancakes");
+ t = *(timespec_t *)`dtrace_zero;
+};
+
+BEGIN
+{
+ print(*(xlate < pancakes_t * > ((void *)NULL)));
+}
+
+BEGIN
+{
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/print/tst.xlate.d.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,8 @@
+pancakes_t {
+ int i = 0x14
+ string s = [ "I like pancakes" ]
+ timespec_t t = {
+ time_t tv_sec = 0
+ long tv_nsec = 0
+ }
+}
--- a/usr/src/cmd/dtrace/test/tst/common/printf/tst.ints.d.out Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/printf/tst.ints.d.out Wed Jul 25 19:05:31 2012 -0400
@@ -1,6 +1,6 @@
-239
-52719
+-17
+-12817
-1867788817
1311768467294899695
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/printf/tst.signs.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,38 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Check %d v. %i v. %u.
+ */
+
+#pragma D option quiet
+
+uint16_t x;
+int16_t y;
+
+BEGIN
+{
+ x = 0xffffffff;
+ y = 0xffffffff;
+
+ printf("%d %i %u\n", x, x, x);
+ printf("%d %i %u\n", y, y, y);
+
+ exit(0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/printf/tst.signs.d.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,3 @@
+65535 -1 65535
+-1 -1 65535
+
--- a/usr/src/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations1.d Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations1.d Wed Jul 25 19:05:31 2012 -0400
@@ -24,7 +24,10 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
/*
* ASSERTION:
@@ -35,17 +38,10 @@
*
* NOTES: This test behaves differently depending on the values
* assigned to bufsize.
- * 1. 0 > bufsize.
- * 2. 0 == bufsize.
- * 3. 0 < bufsize <= 7
- * 4. 8 <= bufsize <= 31
- * 5. 32 <= bufsize <= 47
- * 6. 48 <= bufsize <= 71
- * 7. 72 <= bufsize
*/
#pragma D option quiet
-#pragma D option bufsize=41
+#pragma D option bufsize=49
BEGIN
{
--- a/usr/src/cmd/dtrace/test/tst/common/speculation/tst.SpecSizeVariations3.d Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/speculation/tst.SpecSizeVariations3.d Wed Jul 25 19:05:31 2012 -0400
@@ -24,7 +24,10 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
/*
* ASSERTION:
* Verify the behavior of speculations with changes in specsize.
@@ -35,7 +38,7 @@
*/
#pragma D option quiet
-#pragma D option specsize=40
+#pragma D option specsize=48
BEGIN
{
--- a/usr/src/cmd/dtrace/test/tst/common/trace/err.D_TRACE_DYN.bad.d Tue Jul 24 03:56:16 2012 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * 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 (c) 2011 by Delphix. All rights reserved.
- */
-
-BEGIN
-{
- trace(*curpsinfo);
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/trace/tst.dyn.d Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,28 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+BEGIN
+{
+ trace(*curpsinfo);
+}
+
+BEGIN
+{
+ exit(0);
+}
--- a/usr/src/cmd/dtrace/test/tst/common/translators/man.TestTransStability.d Tue Jul 24 03:56:16 2012 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * 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 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * ASSERTION:
- * The D inline translation mechanism can be used to facilitate stable
- * translations.
- *
- * SECTION: Translators/ Translator Declarations
- * SECTION: Translators/ Translate Operator
- * SECTION: Translators/Stable Translations
- *
- * NOTES: Uncomment the pragma that explicitly resets the attributes of
- * myinfo identifier to Stable/Stable/Common from Private/Private/Unknown.
- * Run the program with and without the comments as:
- * /usr/sbin/dtrace -vs man.TestTransStability.d
- */
-
-#pragma D option quiet
-
-inline lwpsinfo_t *myinfo = xlate < lwpsinfo_t *> (curthread);
-
-/*
-#pragma D attributes Stable/Stable/Common myinfo
-*/
-
-BEGIN
-{
- trace(myinfo->pr_flag);
- exit(0);
-}
-
-ERROR
-{
- exit(1);
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/translators/tst.TestTransStability1.ksh Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,62 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Test the output for stable translations.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+
+$dtrace -v -s /dev/stdin <<EOF
+
+#pragma D option quiet
+
+inline lwpsinfo_t *myinfo = xlate < lwpsinfo_t *> (curthread);
+
+#pragma D attributes Stable/Stable/Common myinfo
+
+BEGIN
+{
+ this->a = myinfo->pr_flag;
+ exit(0);
+}
+
+BEGIN
+{
+ exit(1);
+}
+EOF
+
+exit $?
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/translators/tst.TestTransStability1.ksh.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,14 @@
+
+Stability attributes for script /dev/stdin:
+
+ Minimum Probe Description Attributes
+ Identifier Names: Unstable
+ Data Semantics: Unstable
+ Dependency Class: Common
+
+ Minimum Statement Attributes
+ Identifier Names: Stable
+ Data Semantics: Stable
+ Dependency Class: Common
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/translators/tst.TestTransStability2.ksh Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,60 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Test the output of unstable translations.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+
+$dtrace -v -s /dev/stdin <<EOF
+
+#pragma D option quiet
+
+inline lwpsinfo_t *myinfo = xlate < lwpsinfo_t *> (curthread);
+
+BEGIN
+{
+ this->a = myinfo->pr_flag;
+ exit(0);
+}
+
+BEGIN
+{
+ exit(1);
+}
+EOF
+
+exit $?
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/translators/tst.TestTransStability2.ksh.out Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,14 @@
+
+Stability attributes for script /dev/stdin:
+
+ Minimum Probe Description Attributes
+ Identifier Names: Unstable
+ Data Semantics: Unstable
+ Dependency Class: Common
+
+ Minimum Statement Attributes
+ Identifier Names: Private
+ Data Semantics: Private
+ Dependency Class: Unknown
+
+
--- a/usr/src/lib/libdtrace/Makefile.com Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/Makefile.com Wed Jul 25 19:05:31 2012 -0400
@@ -20,7 +20,7 @@
#
#
# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright (c) 2011 by Delphix. All rights reserved.
+# Copyright (c) 2012 by Delphix. All rights reserved.
#
LIBRARY = libdtrace.a
@@ -52,6 +52,7 @@
dt_parser.c \
dt_pcb.c \
dt_pid.c \
+ dt_pq.c \
dt_pragma.c \
dt_print.c \
dt_printf.c \
--- a/usr/src/lib/libdtrace/common/dt_aggregate.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_aggregate.c Wed Jul 25 19:05:31 2012 -0400
@@ -26,6 +26,7 @@
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <stdlib.h>
@@ -884,33 +885,14 @@
caddr_t rdata = rh->dtahe_data.dtada_data;
dtrace_recdesc_t *lrec, *rrec;
int64_t *laddr, *raddr;
- int rval, i;
-
- if ((rval = dt_aggregate_hashcmp(lhs, rhs)) != 0)
- return (rval);
+ int rval;
- if (lagg->dtagd_nrecs > ragg->dtagd_nrecs)
- return (DT_GREATERTHAN);
-
- if (lagg->dtagd_nrecs < ragg->dtagd_nrecs)
- return (DT_LESSTHAN);
+ assert(lagg->dtagd_nrecs == ragg->dtagd_nrecs);
- for (i = 0; i < lagg->dtagd_nrecs; i++) {
- lrec = &lagg->dtagd_rec[i];
- rrec = &ragg->dtagd_rec[i];
-
- if (lrec->dtrd_offset < rrec->dtrd_offset)
- return (DT_LESSTHAN);
+ lrec = &lagg->dtagd_rec[lagg->dtagd_nrecs - 1];
+ rrec = &ragg->dtagd_rec[ragg->dtagd_nrecs - 1];
- if (lrec->dtrd_offset > rrec->dtrd_offset)
- return (DT_GREATERTHAN);
-
- if (lrec->dtrd_action < rrec->dtrd_action)
- return (DT_LESSTHAN);
-
- if (lrec->dtrd_action > rrec->dtrd_action)
- return (DT_GREATERTHAN);
- }
+ assert(lrec->dtrd_action == rrec->dtrd_action);
laddr = (int64_t *)(uintptr_t)(ldata + lrec->dtrd_offset);
raddr = (int64_t *)(uintptr_t)(rdata + rrec->dtrd_offset);
--- a/usr/src/lib/libdtrace/common/dt_cc.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_cc.c Wed Jul 25 19:05:31 2012 -0400
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, Joyent Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
@@ -663,63 +663,48 @@
dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
{
dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
+ boolean_t istrace = (dnp->dn_ident->di_id == DT_ACT_TRACE);
+ const char *act = istrace ? "trace" : "print";
if (dt_node_is_void(dnp->dn_args)) {
- dnerror(dnp->dn_args, D_TRACE_VOID,
- "trace( ) may not be applied to a void expression\n");
+ dnerror(dnp->dn_args, istrace ? D_TRACE_VOID : D_PRINT_VOID,
+ "%s( ) may not be applied to a void expression\n", act);
}
- if (dt_node_is_dynamic(dnp->dn_args)) {
- dnerror(dnp->dn_args, D_TRACE_DYN,
- "trace( ) may not be applied to a dynamic expression\n");
+ if (dt_node_resolve(dnp->dn_args, DT_IDENT_XLPTR) != NULL) {
+ dnerror(dnp->dn_args, istrace ? D_TRACE_DYN : D_PRINT_DYN,
+ "%s( ) may not be applied to a translated pointer\n", act);
}
dt_cg(yypcb, dnp->dn_args);
- ap->dtad_difo = dt_as(yypcb);
- ap->dtad_kind = DTRACEACT_DIFEXPR;
-}
-
-/*
- * The print() action behaves identically to trace(), except that it stores the
- * CTF type of the argument (if present) within the DOF for the DIFEXPR action.
- * To do this, we set the 'dtsd_strdata' to point to the fully-qualified CTF
- * type ID for the result of the DIF action. We use the ID instead of the name
- * to handles complex types like arrays and function pointers that can't be
- * resolved by ctf_type_lookup(). This is later processed by
- * dtrace_dof_create() and turned into a reference into the string table so
- * that we can get the type information when we process the data after the
- * fact.
- */
-static void
-dt_action_print(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
-{
- dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
- dt_node_t *dret;
- size_t len;
- dt_module_t *dmp;
-
- if (dt_node_is_void(dnp->dn_args)) {
- dnerror(dnp->dn_args, D_PRINT_VOID,
- "print( ) may not be applied to a void expression\n");
+
+ /*
+ * The print() action behaves identically to trace(), except that it
+ * stores the CTF type of the argument (if present) within the DOF for
+ * the DIFEXPR action. To do this, we set the 'dtsd_strdata' to point
+ * to the fully-qualified CTF type ID for the result of the DIF
+ * action. We use the ID instead of the name to handles complex types
+ * like arrays and function pointers that can't be resolved by
+ * ctf_type_lookup(). This is later processed by dtrace_dof_create()
+ * and turned into a reference into the string table so that we can
+ * get the type information when we process the data after the fact.
+ */
+ if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
+ dt_node_t *dret;
+ size_t n;
+ dt_module_t *dmp;
+
+ dret = yypcb->pcb_dret;
+ dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
+
+ n = snprintf(NULL, 0, "%s`%d", dmp->dm_name, dret->dn_type) + 1;
+ sdp->dtsd_strdata = dt_alloc(dtp, n);
+ if (sdp->dtsd_strdata == NULL)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
+ (void) snprintf(sdp->dtsd_strdata, n, "%s`%d", dmp->dm_name,
+ dret->dn_type);
}
- if (dt_node_is_dynamic(dnp->dn_args)) {
- dnerror(dnp->dn_args, D_PRINT_DYN,
- "print( ) may not be applied to a dynamic expression\n");
- }
-
- dt_cg(yypcb, dnp->dn_args);
-
- dret = yypcb->pcb_dret;
- dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
-
- len = snprintf(NULL, 0, "%s`%d", dmp->dm_name, dret->dn_type) + 1;
- sdp->dtsd_strdata = dt_alloc(dtp, len);
- if (sdp->dtsd_strdata == NULL)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
- (void) snprintf(sdp->dtsd_strdata, len, "%s`%d", dmp->dm_name,
- dret->dn_type);
-
ap->dtad_difo = dt_as(yypcb);
ap->dtad_kind = DTRACEACT_DIFEXPR;
}
@@ -1073,6 +1058,9 @@
case DT_ACT_PANIC:
dt_action_panic(dtp, dnp->dn_expr, sdp);
break;
+ case DT_ACT_PRINT:
+ dt_action_trace(dtp, dnp->dn_expr, sdp);
+ break;
case DT_ACT_PRINTA:
dt_action_printa(dtp, dnp->dn_expr, sdp);
break;
@@ -1103,9 +1091,6 @@
case DT_ACT_TRACE:
dt_action_trace(dtp, dnp->dn_expr, sdp);
break;
- case DT_ACT_PRINT:
- dt_action_print(dtp, dnp->dn_expr, sdp);
- break;
case DT_ACT_TRACEMEM:
dt_action_tracemem(dtp, dnp->dn_expr, sdp);
break;
@@ -2462,7 +2447,8 @@
}
out:
- if (context != DT_CTX_DTYPE && DT_TREEDUMP_PASS(dtp, 3))
+ if (context != DT_CTX_DTYPE && yypcb->pcb_root != NULL &&
+ DT_TREEDUMP_PASS(dtp, 3))
dt_node_printr(yypcb->pcb_root, stderr, 0);
if (dtp->dt_cdefs_fd != -1 && (ftruncate64(dtp->dt_cdefs_fd, 0) == -1 ||
--- a/usr/src/lib/libdtrace/common/dt_cg.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_cg.c Wed Jul 25 19:05:31 2012 -0400
@@ -19,12 +19,15 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
#include <sys/types.h>
#include <sys/sysmacros.h>
@@ -193,9 +196,6 @@
ssize_t size;
int sreg;
- if ((sreg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
type = ctf_type_resolve(ctfp, dnp->dn_type);
kind = ctf_type_kind(ctfp, type);
assert(kind == CTF_K_POINTER || kind == CTF_K_ARRAY);
@@ -212,6 +212,7 @@
if ((size = ctf_type_size(ctfp, type)) == 1)
return; /* multiply or divide by one can be omitted */
+ sreg = dt_regset_alloc(drp);
dt_cg_setx(dlp, sreg, size);
instr = DIF_INSTR_FMT(op, dreg, sreg, dreg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -251,9 +252,7 @@
assert(dnp->dn_op == DT_TOK_PTR || dnp->dn_op == DT_TOK_DOT);
r1 = dnp->dn_left->dn_reg;
-
- if ((r2 = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ r2 = dt_regset_alloc(drp);
/*
* On little-endian architectures, ctm_offset counts from the right so
@@ -356,10 +355,9 @@
"bits %u\n", m.ctm_offset, m.ctm_type, e.cte_bits);
}
- if ((r1 = dt_regset_alloc(drp)) == -1 ||
- (r2 = dt_regset_alloc(drp)) == -1 ||
- (r3 = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ r1 = dt_regset_alloc(drp);
+ r2 = dt_regset_alloc(drp);
+ r3 = dt_regset_alloc(drp);
/*
* Compute shifts and masks. We need to compute "shift" as the amount
@@ -423,8 +421,7 @@
size = dt_node_type_size(src);
if (src->dn_flags & DT_NF_REF) {
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ reg = dt_regset_alloc(drp);
dt_cg_setx(dlp, reg, size);
instr = DIF_INSTR_COPYS(src->dn_reg, reg, dst->dn_reg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -474,30 +471,58 @@
size_t dstsize = dt_node_type_size(dst);
dif_instr_t instr;
- int reg, n;
+ int rg;
+
+ if (!dt_node_is_scalar(dst))
+ return; /* not a scalar */
+ if (dstsize == srcsize &&
+ ((src->dn_flags ^ dst->dn_flags) & DT_NF_SIGNED) != 0)
+ return; /* not narrowing or changing signed-ness */
+ if (dstsize > srcsize && (src->dn_flags & DT_NF_SIGNED) == 0)
+ return; /* nothing to do in this case */
- if (dt_node_is_scalar(dst) && (dstsize < srcsize ||
- (src->dn_flags & DT_NF_SIGNED) ^ (dst->dn_flags & DT_NF_SIGNED))) {
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ rg = dt_regset_alloc(drp);
+
+ if (dstsize > srcsize) {
+ int n = sizeof (uint64_t) * NBBY - srcsize * NBBY;
+ int s = (dstsize - srcsize) * NBBY;
+
+ dt_cg_setx(dlp, rg, n);
+
+ instr = DIF_INSTR_FMT(DIF_OP_SLL, src->dn_reg, rg, dst->dn_reg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
- if (dstsize < srcsize)
- n = sizeof (uint64_t) * NBBY - dstsize * NBBY;
- else
- n = sizeof (uint64_t) * NBBY - srcsize * NBBY;
+ if ((dst->dn_flags & DT_NF_SIGNED) || n == s) {
+ instr = DIF_INSTR_FMT(DIF_OP_SRA,
+ dst->dn_reg, rg, dst->dn_reg);
+ dt_irlist_append(dlp,
+ dt_cg_node_alloc(DT_LBL_NONE, instr));
+ } else {
+ dt_cg_setx(dlp, rg, s);
+ instr = DIF_INSTR_FMT(DIF_OP_SRA,
+ dst->dn_reg, rg, dst->dn_reg);
+ dt_irlist_append(dlp,
+ dt_cg_node_alloc(DT_LBL_NONE, instr));
+ dt_cg_setx(dlp, rg, n - s);
+ instr = DIF_INSTR_FMT(DIF_OP_SRL,
+ dst->dn_reg, rg, dst->dn_reg);
+ dt_irlist_append(dlp,
+ dt_cg_node_alloc(DT_LBL_NONE, instr));
+ }
+ } else if (dstsize != sizeof (uint64_t)) {
+ int n = sizeof (uint64_t) * NBBY - dstsize * NBBY;
- dt_cg_setx(dlp, reg, n);
+ dt_cg_setx(dlp, rg, n);
- instr = DIF_INSTR_FMT(DIF_OP_SLL,
- src->dn_reg, reg, dst->dn_reg);
+ instr = DIF_INSTR_FMT(DIF_OP_SLL, src->dn_reg, rg, dst->dn_reg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
instr = DIF_INSTR_FMT((dst->dn_flags & DT_NF_SIGNED) ?
- DIF_OP_SRA : DIF_OP_SRL, dst->dn_reg, reg, dst->dn_reg);
-
+ DIF_OP_SRA : DIF_OP_SRL, dst->dn_reg, rg, dst->dn_reg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
- dt_regset_free(drp, reg);
}
+
+ dt_regset_free(drp, rg);
}
/*
@@ -523,8 +548,7 @@
for (dnp = args; dnp != NULL; dnp = dnp->dn_list)
dt_cg_node(dnp, dlp, drp);
- dt_irlist_append(dlp,
- dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
for (dnp = args; dnp != NULL; dnp = dnp->dn_list, i++) {
dtrace_diftype_t t;
@@ -538,17 +562,18 @@
dt_cg_typecast(dnp, &isp->dis_args[i], dlp, drp);
isp->dis_args[i].dn_reg = -1;
- if (t.dtdt_flags & DIF_TF_BYREF)
+ if (t.dtdt_flags & DIF_TF_BYREF) {
op = DIF_OP_PUSHTR;
- else
+ if (t.dtdt_size != 0) {
+ reg = dt_regset_alloc(drp);
+ dt_cg_setx(dlp, reg, t.dtdt_size);
+ } else {
+ reg = DIF_REG_R0;
+ }
+ } else {
op = DIF_OP_PUSHTV;
-
- if (t.dtdt_size != 0) {
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
- dt_cg_setx(dlp, reg, t.dtdt_size);
- } else
reg = DIF_REG_R0;
+ }
instr = DIF_INSTR_PUSHTS(op, t.dtdt_kind, reg, dnp->dn_reg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -629,9 +654,7 @@
dt_cg_node(dnp->dn_child, dlp, drp);
dnp->dn_reg = dnp->dn_child->dn_reg;
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ reg = dt_regset_alloc(drp);
dt_cg_setx(dlp, reg, size);
instr = DIF_INSTR_FMT(op, dnp->dn_reg, reg, dnp->dn_reg);
@@ -688,9 +711,7 @@
dt_cg_node(dnp->dn_child, dlp, drp);
dnp->dn_reg = dnp->dn_child->dn_reg;
- if ((nreg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ nreg = dt_regset_alloc(drp);
dt_cg_setx(dlp, nreg, size);
instr = DIF_INSTR_FMT(op, dnp->dn_reg, nreg, nreg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -1008,9 +1029,7 @@
* set it to the size of our data structure, and then replace
* it with the result of an allocs of the specified size.
*/
- if ((r1 = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ r1 = dt_regset_alloc(drp);
dt_cg_setx(dlp, r1,
ctf_type_size(dxp->dx_dst_ctfp, dxp->dx_dst_base));
@@ -1054,8 +1073,7 @@
* and add r1 to it before storing the result.
*/
if (ctm.ctm_offset != 0) {
- if ((r2 = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ r2 = dt_regset_alloc(drp);
/*
* Add the member offset rounded down to the
@@ -1142,8 +1160,7 @@
dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dnp->dn_reg = dt_regset_alloc(drp);
if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)
op = DIF_OP_LDTAA;
@@ -1273,9 +1290,7 @@
if ((size = dt_node_type_size(dnp)) == sizeof (uint64_t))
return;
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ reg = dt_regset_alloc(drp);
assert(size < sizeof (uint64_t));
n = sizeof (uint64_t) * NBBY - size * NBBY;
@@ -1338,6 +1353,162 @@
}
}
+typedef struct dt_xlmemb {
+ dt_ident_t *dtxl_idp; /* translated ident */
+ dt_irlist_t *dtxl_dlp; /* instruction list */
+ dt_regset_t *dtxl_drp; /* register set */
+ int dtxl_sreg; /* location of the translation input */
+ int dtxl_dreg; /* location of our allocated buffer */
+} dt_xlmemb_t;
+
+/*ARGSUSED*/
+static int
+dt_cg_xlate_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
+{
+ dt_xlmemb_t *dx = arg;
+ dt_ident_t *idp = dx->dtxl_idp;
+ dt_irlist_t *dlp = dx->dtxl_dlp;
+ dt_regset_t *drp = dx->dtxl_drp;
+
+ dt_node_t *mnp;
+ dt_xlator_t *dxp;
+
+ int reg, treg;
+ uint32_t instr;
+ size_t size;
+
+ /* Generate code for the translation. */
+ dxp = idp->di_data;
+ mnp = dt_xlator_member(dxp, name);
+
+ /* If there's no translator for the given member, skip it. */
+ if (mnp == NULL)
+ return (0);
+
+ dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;
+ dxp->dx_ident->di_id = dx->dtxl_sreg;
+
+ dt_cg_node(mnp->dn_membexpr, dlp, drp);
+
+ dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
+ dxp->dx_ident->di_id = 0;
+
+ treg = mnp->dn_membexpr->dn_reg;
+
+ /* Compute the offset into our buffer and store the result there. */
+ reg = dt_regset_alloc(drp);
+
+ dt_cg_setx(dlp, reg, off / NBBY);
+ instr = DIF_INSTR_FMT(DIF_OP_ADD, dx->dtxl_dreg, reg, reg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+ size = ctf_type_size(mnp->dn_membexpr->dn_ctfp,
+ mnp->dn_membexpr->dn_type);
+ if (dt_node_is_scalar(mnp->dn_membexpr)) {
+ /*
+ * Copying scalars is simple.
+ */
+ switch (size) {
+ case 1:
+ instr = DIF_INSTR_STORE(DIF_OP_STB, treg, reg);
+ break;
+ case 2:
+ instr = DIF_INSTR_STORE(DIF_OP_STH, treg, reg);
+ break;
+ case 4:
+ instr = DIF_INSTR_STORE(DIF_OP_STW, treg, reg);
+ break;
+ case 8:
+ instr = DIF_INSTR_STORE(DIF_OP_STX, treg, reg);
+ break;
+ default:
+ xyerror(D_UNKNOWN, "internal error -- unexpected "
+ "size: %lu\n", (ulong_t)size);
+ }
+
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+ } else if (dt_node_is_string(mnp->dn_membexpr)) {
+ int szreg;
+
+ /*
+ * Use the copys instruction for strings.
+ */
+ szreg = dt_regset_alloc(drp);
+ dt_cg_setx(dlp, szreg, size);
+ instr = DIF_INSTR_COPYS(treg, szreg, reg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+ dt_regset_free(drp, szreg);
+ } else {
+ int szreg;
+
+ /*
+ * If it's anything else then we'll just bcopy it.
+ */
+ szreg = dt_regset_alloc(drp);
+ dt_cg_setx(dlp, szreg, size);
+ dt_irlist_append(dlp,
+ dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
+ instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
+ DIF_REG_R0, treg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+ instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
+ DIF_REG_R0, reg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+ instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
+ DIF_REG_R0, szreg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+ instr = DIF_INSTR_CALL(DIF_SUBR_BCOPY, szreg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+ dt_regset_free(drp, szreg);
+ }
+
+ dt_regset_free(drp, reg);
+ dt_regset_free(drp, treg);
+
+ return (0);
+}
+
+/*
+ * If we're expanding a translated type, we create an appropriately sized
+ * buffer with alloca() and then translate each member into it.
+ */
+static int
+dt_cg_xlate_expand(dt_node_t *dnp, dt_ident_t *idp, dt_irlist_t *dlp,
+ dt_regset_t *drp)
+{
+ dt_xlmemb_t dlm;
+ uint32_t instr;
+ int dreg;
+ size_t size;
+
+ dreg = dt_regset_alloc(drp);
+ size = ctf_type_size(dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
+
+ /* Call alloca() to create the buffer. */
+ dt_cg_setx(dlp, dreg, size);
+
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
+
+ instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF, DIF_REG_R0, dreg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+ instr = DIF_INSTR_CALL(DIF_SUBR_ALLOCA, dreg);
+ dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+ /* Generate the translation for each member. */
+ dlm.dtxl_idp = idp;
+ dlm.dtxl_dlp = dlp;
+ dlm.dtxl_drp = drp;
+ dlm.dtxl_sreg = dnp->dn_reg;
+ dlm.dtxl_dreg = dreg;
+ (void) ctf_member_iter(dnp->dn_ident->di_ctfp,
+ dnp->dn_ident->di_type, dt_cg_xlate_member,
+ &dlm);
+
+ return (dreg);
+}
+
static void
dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
{
@@ -1350,7 +1521,6 @@
dt_ident_t *idp;
ssize_t stroff;
uint_t op;
- int reg;
switch (dnp->dn_op) {
case DT_TOK_COMMA:
@@ -1552,7 +1722,16 @@
dt_cg_node(dnp->dn_child, dlp, drp);
dnp->dn_reg = dnp->dn_child->dn_reg;
- if (!(dnp->dn_flags & DT_NF_REF)) {
+ if (dt_node_is_dynamic(dnp->dn_child)) {
+ int reg;
+ idp = dt_node_resolve(dnp->dn_child, DT_IDENT_XLPTR);
+ assert(idp != NULL);
+ reg = dt_cg_xlate_expand(dnp, idp, dlp, drp);
+
+ dt_regset_free(drp, dnp->dn_child->dn_reg);
+ dnp->dn_reg = reg;
+
+ } else if (!(dnp->dn_flags & DT_NF_REF)) {
uint_t ubit = dnp->dn_flags & DT_NF_USERLAND;
/*
@@ -1588,10 +1767,7 @@
case DT_TOK_SIZEOF: {
size_t size = dt_node_sizeof(dnp->dn_child);
-
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ dnp->dn_reg = dt_regset_alloc(drp);
assert(size != 0);
dt_cg_setx(dlp, dnp->dn_reg, size);
break;
@@ -1616,8 +1792,7 @@
assert(dxp->dx_ident->di_flags & DT_IDFLG_CGREG);
assert(dxp->dx_ident->di_id != 0);
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dnp->dn_reg = dt_regset_alloc(drp);
if (dxp->dx_arg == -1) {
instr = DIF_INSTR_MOV(
@@ -1701,8 +1876,9 @@
}
if (m.ctm_offset != 0) {
- if ((reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ int reg;
+
+ reg = dt_regset_alloc(drp);
/*
* If the offset is not aligned on a byte boundary, it
@@ -1748,8 +1924,7 @@
break;
case DT_TOK_STRING:
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dnp->dn_reg = dt_regset_alloc(drp);
assert(dnp->dn_kind == DT_NODE_STRING);
stroff = dt_strtab_insert(yypcb->pcb_strtab, dnp->dn_string);
@@ -1772,8 +1947,7 @@
*/
if (dnp->dn_kind == DT_NODE_VAR &&
(dnp->dn_ident->di_flags & DT_IDFLG_CGREG)) {
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dnp->dn_reg = dt_regset_alloc(drp);
instr = DIF_INSTR_MOV(dnp->dn_ident->di_id,
dnp->dn_reg);
dt_irlist_append(dlp,
@@ -1803,11 +1977,9 @@
dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
- instr = DIF_INSTR_CALL(
- dnp->dn_ident->di_id, dnp->dn_reg);
+ dnp->dn_reg = dt_regset_alloc(drp);
+ instr = DIF_INSTR_CALL(dnp->dn_ident->di_id,
+ dnp->dn_reg);
dt_irlist_append(dlp,
dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -1834,8 +2006,7 @@
break;
}
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+ dnp->dn_reg = dt_regset_alloc(drp);
if (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL)
op = DIF_OP_LDLS;
@@ -1865,9 +2036,7 @@
dtrace_errmsg(dtp, dtrace_errno(dtp)));
}
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ dnp->dn_reg = dt_regset_alloc(drp);
dt_cg_xsetx(dlp, dnp->dn_ident,
DT_LBL_NONE, dnp->dn_reg, sym.st_value);
@@ -1887,9 +2056,7 @@
break;
case DT_TOK_INT:
- if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+ dnp->dn_reg = dt_regset_alloc(drp);
dt_cg_setx(dlp, dnp->dn_reg, dnp->dn_value);
break;
@@ -1904,6 +2071,7 @@
{
dif_instr_t instr;
dt_xlator_t *dxp;
+ dt_ident_t *idp;
if (pcb->pcb_regs == NULL && (pcb->pcb_regs =
dt_regset_create(pcb->pcb_hdl->dt_conf.dtc_difintregs)) == NULL)
@@ -1930,9 +2098,9 @@
assert(pcb->pcb_dret == NULL);
pcb->pcb_dret = dnp;
- if (dt_node_is_dynamic(dnp)) {
+ if (dt_node_resolve(dnp, DT_IDENT_XLPTR) != NULL) {
dnerror(dnp, D_CG_DYN, "expression cannot evaluate to result "
- "of dynamic type\n");
+ "of a translated pointer\n");
}
/*
@@ -1948,6 +2116,14 @@
}
dt_cg_node(dnp, &pcb->pcb_ir, pcb->pcb_regs);
+
+ if ((idp = dt_node_resolve(dnp, DT_IDENT_XLSOU)) != NULL) {
+ int reg = dt_cg_xlate_expand(dnp, idp,
+ &pcb->pcb_ir, pcb->pcb_regs);
+ dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
+ dnp->dn_reg = reg;
+ }
+
instr = DIF_INSTR_RET(dnp->dn_reg);
dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
dt_irlist_append(&pcb->pcb_ir, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -1957,4 +2133,7 @@
dxp->dx_ident->di_id = 0;
dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
}
+
+ dt_regset_free(pcb->pcb_regs, 0);
+ dt_regset_assert_free(pcb->pcb_regs);
}
--- a/usr/src/lib/libdtrace/common/dt_consume.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_consume.c Wed Jul 25 19:05:31 2012 -0400
@@ -25,7 +25,7 @@
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <stdlib.h>
@@ -37,6 +37,7 @@
#include <ctype.h>
#include <alloca.h>
#include <dt_impl.h>
+#include <dt_pq.h>
#define DT_MASK_LO 0x00000000FFFFFFFFULL
@@ -438,17 +439,8 @@
offs += epd->dtepd_size;
do {
- if (offs >= buf->dtbd_size) {
- /*
- * We're at the end -- maybe. If the oldest
- * record is non-zero, we need to wrap.
- */
- if (buf->dtbd_oldest != 0) {
- offs = 0;
- } else {
- goto out;
- }
- }
+ if (offs >= buf->dtbd_size)
+ goto out;
next = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs);
@@ -1700,26 +1692,27 @@
}
static int
-dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, dtrace_bufdesc_t *buf,
+dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
+ dtrace_bufdesc_t *buf, boolean_t just_one,
dtrace_consume_probe_f *efunc, dtrace_consume_rec_f *rfunc, void *arg)
{
dtrace_epid_t id;
- size_t offs, start = buf->dtbd_oldest, end = buf->dtbd_size;
+ size_t offs;
int flow = (dtp->dt_options[DTRACEOPT_FLOWINDENT] != DTRACEOPT_UNSET);
int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET);
int rval, i, n;
- dtrace_epid_t last = DTRACE_EPIDNONE;
uint64_t tracememsize = 0;
dtrace_probedata_t data;
uint64_t drops;
- caddr_t addr;
bzero(&data, sizeof (data));
data.dtpda_handle = dtp;
data.dtpda_cpu = cpu;
-
-again:
- for (offs = start; offs < end; ) {
+ data.dtpda_flow = dtp->dt_flow;
+ data.dtpda_indent = dtp->dt_indent;
+ data.dtpda_prefix = dtp->dt_prefix;
+
+ for (offs = buf->dtbd_oldest; offs < buf->dtbd_size; ) {
dtrace_eprobedesc_t *epd;
/*
@@ -1754,7 +1747,8 @@
}
if (flow)
- (void) dt_flowindent(dtp, &data, last, buf, offs);
+ (void) dt_flowindent(dtp, &data, dtp->dt_last_epid,
+ buf, offs);
rval = (*efunc)(&data, arg);
@@ -1773,6 +1767,7 @@
return (dt_set_errno(dtp, EDT_BADRVAL));
for (i = 0; i < epd->dtepd_nrecs; i++) {
+ caddr_t addr;
dtrace_recdesc_t *rec = &epd->dtepd_rec[i];
dtrace_actkind_t act = rec->dtrd_action;
@@ -2132,14 +2127,16 @@
rval = (*rfunc)(&data, NULL, arg);
nextepid:
offs += epd->dtepd_size;
- last = id;
+ dtp->dt_last_epid = id;
+ if (just_one) {
+ buf->dtbd_oldest = offs;
+ break;
+ }
}
- if (buf->dtbd_oldest != 0 && start == buf->dtbd_oldest) {
- end = buf->dtbd_oldest;
- start = 0;
- goto again;
- }
+ dtp->dt_flow = data.dtpda_flow;
+ dtp->dt_indent = data.dtpda_indent;
+ dtp->dt_prefix = data.dtpda_prefix;
if ((drops = buf->dtbd_drops) == 0)
return (0);
@@ -2152,6 +2149,126 @@
return (dt_handle_cpudrop(dtp, cpu, DTRACEDROP_PRINCIPAL, drops));
}
+/*
+ * Reduce memory usage by shrinking the buffer if it's no more than half full.
+ * Note, we need to preserve the alignment of the data at dtbd_oldest, which is
+ * only 4-byte aligned.
+ */
+static void
+dt_realloc_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf, int cursize)
+{
+ uint64_t used = buf->dtbd_size - buf->dtbd_oldest;
+ if (used < cursize / 2) {
+ int misalign = buf->dtbd_oldest & (sizeof (uint64_t) - 1);
+ char *newdata = dt_alloc(dtp, used + misalign);
+ if (newdata == NULL)
+ return;
+ bzero(newdata, misalign);
+ bcopy(buf->dtbd_data + buf->dtbd_oldest,
+ newdata + misalign, used);
+ dt_free(dtp, buf->dtbd_data);
+ buf->dtbd_oldest = misalign;
+ buf->dtbd_size = used + misalign;
+ buf->dtbd_data = newdata;
+ }
+}
+
+/*
+ * If the ring buffer has wrapped, the data is not in order. Rearrange it
+ * so that it is. Note, we need to preserve the alignment of the data at
+ * dtbd_oldest, which is only 4-byte aligned.
+ */
+static int
+dt_unring_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf)
+{
+ int misalign;
+ char *newdata, *ndp;
+
+ if (buf->dtbd_oldest == 0)
+ return (0);
+
+ misalign = buf->dtbd_oldest & (sizeof (uint64_t) - 1);
+ newdata = ndp = dt_alloc(dtp, buf->dtbd_size + misalign);
+
+ if (newdata == NULL)
+ return (-1);
+
+ assert(0 == (buf->dtbd_size & (sizeof (uint64_t) - 1)));
+
+ bzero(ndp, misalign);
+ ndp += misalign;
+
+ bcopy(buf->dtbd_data + buf->dtbd_oldest, ndp,
+ buf->dtbd_size - buf->dtbd_oldest);
+ ndp += buf->dtbd_size - buf->dtbd_oldest;
+
+ bcopy(buf->dtbd_data, ndp, buf->dtbd_oldest);
+
+ dt_free(dtp, buf->dtbd_data);
+ buf->dtbd_oldest = 0;
+ buf->dtbd_data = newdata;
+ buf->dtbd_size += misalign;
+
+ return (0);
+}
+
+static void
+dt_put_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf)
+{
+ dt_free(dtp, buf->dtbd_data);
+ dt_free(dtp, buf);
+}
+
+/*
+ * Returns 0 on success, in which case *cbp will be filled in if we retrieved
+ * data, or NULL if there is no data for this CPU.
+ * Returns -1 on failure and sets dt_errno.
+ */
+static int
+dt_get_buf(dtrace_hdl_t *dtp, int cpu, dtrace_bufdesc_t **bufp)
+{
+ dtrace_optval_t size;
+ dtrace_bufdesc_t *buf = dt_zalloc(dtp, sizeof (*buf));
+ int error;
+
+ if (buf == NULL)
+ return (-1);
+
+ (void) dtrace_getopt(dtp, "bufsize", &size);
+ buf->dtbd_data = dt_alloc(dtp, size);
+ if (buf->dtbd_data == NULL) {
+ dt_free(dtp, buf);
+ return (-1);
+ }
+ buf->dtbd_size = size;
+ buf->dtbd_cpu = cpu;
+
+ if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
+ dt_put_buf(dtp, buf);
+ /*
+ * If we failed with ENOENT, it may be because the
+ * CPU was unconfigured -- this is okay. Any other
+ * error, however, is unexpected.
+ */
+ if (errno == ENOENT) {
+ *bufp = NULL;
+ return (0);
+ }
+
+ return (dt_set_errno(dtp, errno));
+ }
+
+ error = dt_unring_buf(dtp, buf);
+ if (error != 0) {
+ dt_put_buf(dtp, buf);
+ return (error);
+ }
+ dt_realloc_buf(dtp, buf, size);
+
+ *bufp = buf;
+ return (0);
+}
+
typedef struct dt_begin {
dtrace_consume_probe_f *dtbgn_probefunc;
dtrace_consume_rec_f *dtbgn_recfunc;
@@ -2164,7 +2281,7 @@
static int
dt_consume_begin_probe(const dtrace_probedata_t *data, void *arg)
{
- dt_begin_t *begin = (dt_begin_t *)arg;
+ dt_begin_t *begin = arg;
dtrace_probedesc_t *pd = data->dtpda_pdesc;
int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0);
@@ -2189,7 +2306,7 @@
dt_consume_begin_record(const dtrace_probedata_t *data,
const dtrace_recdesc_t *rec, void *arg)
{
- dt_begin_t *begin = (dt_begin_t *)arg;
+ dt_begin_t *begin = arg;
return (begin->dtbgn_recfunc(data, rec, begin->dtbgn_arg));
}
@@ -2215,7 +2332,7 @@
}
static int
-dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp, dtrace_bufdesc_t *buf,
+dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
{
/*
@@ -2239,26 +2356,19 @@
* first pass, and that we only process ERROR enablings _not_ induced
* by BEGIN enablings in the second pass.
*/
+
dt_begin_t begin;
processorid_t cpu = dtp->dt_beganon;
- dtrace_bufdesc_t nbuf;
int rval, i;
static int max_ncpus;
- dtrace_optval_t size;
+ dtrace_bufdesc_t *buf;
dtp->dt_beganon = -1;
- if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
- /*
- * We really don't expect this to fail, but it is at least
- * technically possible for this to fail with ENOENT. In this
- * case, we just drive on...
- */
- if (errno == ENOENT)
- return (0);
-
- return (dt_set_errno(dtp, errno));
- }
+ if (dt_get_buf(dtp, cpu, &buf) != 0)
+ return (-1);
+ if (buf == NULL)
+ return (0);
if (!dtp->dt_stopped || buf->dtbd_cpu != dtp->dt_endedon) {
/*
@@ -2266,7 +2376,10 @@
* we are, we actually processed any END probes on another
* CPU. We can simply consume this buffer and return.
*/
- return (dt_consume_cpu(dtp, fp, cpu, buf, pf, rf, arg));
+ rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
+ pf, rf, arg);
+ dt_put_buf(dtp, buf);
+ return (rval);
}
begin.dtbgn_probefunc = pf;
@@ -2283,56 +2396,41 @@
dtp->dt_errhdlr = dt_consume_begin_error;
dtp->dt_errarg = &begin;
- rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe,
- dt_consume_begin_record, &begin);
+ rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
+ dt_consume_begin_probe, dt_consume_begin_record, &begin);
dtp->dt_errhdlr = begin.dtbgn_errhdlr;
dtp->dt_errarg = begin.dtbgn_errarg;
- if (rval != 0)
+ if (rval != 0) {
+ dt_put_buf(dtp, buf);
return (rval);
-
- /*
- * Now allocate a new buffer. We'll use this to deal with every other
- * CPU.
- */
- bzero(&nbuf, sizeof (dtrace_bufdesc_t));
- (void) dtrace_getopt(dtp, "bufsize", &size);
- if ((nbuf.dtbd_data = malloc(size)) == NULL)
- return (dt_set_errno(dtp, EDT_NOMEM));
+ }
if (max_ncpus == 0)
max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1;
for (i = 0; i < max_ncpus; i++) {
- nbuf.dtbd_cpu = i;
-
+ dtrace_bufdesc_t *nbuf;
if (i == cpu)
continue;
- if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &nbuf) == -1) {
- /*
- * If we failed with ENOENT, it may be because the
- * CPU was unconfigured -- this is okay. Any other
- * error, however, is unexpected.
- */
- if (errno == ENOENT)
- continue;
-
- free(nbuf.dtbd_data);
-
- return (dt_set_errno(dtp, errno));
+ if (dt_get_buf(dtp, i, &nbuf) != 0) {
+ dt_put_buf(dtp, buf);
+ return (-1);
}
-
- if ((rval = dt_consume_cpu(dtp, fp,
- i, &nbuf, pf, rf, arg)) != 0) {
- free(nbuf.dtbd_data);
+ if (nbuf == NULL)
+ continue;
+
+ rval = dt_consume_cpu(dtp, fp, i, nbuf, B_FALSE,
+ pf, rf, arg);
+ dt_put_buf(dtp, nbuf);
+ if (rval != 0) {
+ dt_put_buf(dtp, buf);
return (rval);
}
}
- free(nbuf.dtbd_data);
-
/*
* Okay -- we're done with the other buffers. Now we want to
* reconsume the first buffer -- but this time we're looking for
@@ -2347,8 +2445,8 @@
dtp->dt_errhdlr = dt_consume_begin_error;
dtp->dt_errarg = &begin;
- rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe,
- dt_consume_begin_record, &begin);
+ rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
+ dt_consume_begin_probe, dt_consume_begin_record, &begin);
dtp->dt_errhdlr = begin.dtbgn_errhdlr;
dtp->dt_errarg = begin.dtbgn_errarg;
@@ -2356,11 +2454,31 @@
return (rval);
}
+/* ARGSUSED */
+static uint64_t
+dt_buf_oldest(void *elem, void *arg)
+{
+ dtrace_bufdesc_t *buf = elem;
+ size_t offs = buf->dtbd_oldest;
+
+ while (offs < buf->dtbd_size) {
+ dtrace_rechdr_t *dtrh =
+ (dtrace_rechdr_t *)(buf->dtbd_data + offs);
+ if (dtrh->dtrh_epid == DTRACE_EPIDNONE) {
+ offs += sizeof (dtrace_epid_t);
+ } else {
+ return (DTRACE_RECORD_LOAD_TIMESTAMP(dtrh));
+ }
+ }
+
+ /* There are no records left; use the time the buffer was retrieved. */
+ return (buf->dtbd_timestamp);
+}
+
int
dtrace_consume(dtrace_hdl_t *dtp, FILE *fp,
dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
{
- dtrace_bufdesc_t *buf = &dtp->dt_buf;
dtrace_optval_t size;
static int max_ncpus;
int i, rval;
@@ -2388,71 +2506,158 @@
if (rf == NULL)
rf = (dtrace_consume_rec_f *)dt_nullrec;
- if (buf->dtbd_data == NULL) {
+ if (dtp->dt_options[DTRACEOPT_TEMPORAL] == DTRACEOPT_UNSET) {
+ /*
+ * The output will not be in the order it was traced. Rather,
+ * we will consume all of the data from each CPU's buffer in
+ * turn. We apply special handling for the records from BEGIN
+ * and END probes so that they are consumed first and last,
+ * respectively.
+ *
+ * If we have just begun, we want to first process the CPU that
+ * executed the BEGIN probe (if any).
+ */
+ if (dtp->dt_active && dtp->dt_beganon != -1 &&
+ (rval = dt_consume_begin(dtp, fp, pf, rf, arg)) != 0)
+ return (rval);
+
+ for (i = 0; i < max_ncpus; i++) {
+ dtrace_bufdesc_t *buf;
+
+ /*
+ * If we have stopped, we want to process the CPU on
+ * which the END probe was processed only _after_ we
+ * have processed everything else.
+ */
+ if (dtp->dt_stopped && (i == dtp->dt_endedon))
+ continue;
+
+ if (dt_get_buf(dtp, i, &buf) != 0)
+ return (-1);
+ if (buf == NULL)
+ continue;
+
+ dtp->dt_flow = 0;
+ dtp->dt_indent = 0;
+ dtp->dt_prefix = NULL;
+ rval = dt_consume_cpu(dtp, fp, i,
+ buf, B_FALSE, pf, rf, arg);
+ dt_put_buf(dtp, buf);
+ if (rval != 0)
+ return (rval);
+ }
+ if (dtp->dt_stopped) {
+ dtrace_bufdesc_t *buf;
+
+ if (dt_get_buf(dtp, dtp->dt_endedon, &buf) != 0)
+ return (-1);
+ if (buf == NULL)
+ return (0);
+
+ rval = dt_consume_cpu(dtp, fp, dtp->dt_endedon,
+ buf, B_FALSE, pf, rf, arg);
+ dt_put_buf(dtp, buf);
+ return (rval);
+ }
+ } else {
+ /*
+ * The output will be in the order it was traced (or for
+ * speculations, when it was committed). We retrieve a buffer
+ * from each CPU and put it into a priority queue, which sorts
+ * based on the first entry in the buffer. This is sufficient
+ * because entries within a buffer are already sorted.
+ *
+ * We then consume records one at a time, always consuming the
+ * oldest record, as determined by the priority queue. When
+ * we reach the end of the time covered by these buffers,
+ * we need to stop and retrieve more records on the next pass.
+ * The kernel tells us the time covered by each buffer, in
+ * dtbd_timestamp. The first buffer's timestamp tells us the
+ * time covered by all buffers, as subsequently retrieved
+ * buffers will cover to a more recent time.
+ */
+
+ uint64_t *drops = alloca(max_ncpus * sizeof (uint64_t));
+ uint64_t first_timestamp = 0;
+ uint_t cookie = 0;
+ dtrace_bufdesc_t *buf;
+
+ bzero(drops, max_ncpus * sizeof (uint64_t));
+
+ if (dtp->dt_bufq == NULL) {
+ dtp->dt_bufq = dt_pq_init(dtp, max_ncpus * 2,
+ dt_buf_oldest, NULL);
+ if (dtp->dt_bufq == NULL) /* ENOMEM */
+ return (-1);
+ }
+
+ /* Retrieve data from each CPU. */
(void) dtrace_getopt(dtp, "bufsize", &size);
- if ((buf->dtbd_data = malloc(size)) == NULL)
- return (dt_set_errno(dtp, EDT_NOMEM));
-
- buf->dtbd_size = size;
- }
-
- /*
- * If we have just begun, we want to first process the CPU that
- * executed the BEGIN probe (if any).
- */
- if (dtp->dt_active && dtp->dt_beganon != -1) {
- buf->dtbd_cpu = dtp->dt_beganon;
- if ((rval = dt_consume_begin(dtp, fp, buf, pf, rf, arg)) != 0)
- return (rval);
- }
-
- for (i = 0; i < max_ncpus; i++) {
- buf->dtbd_cpu = i;
+ for (i = 0; i < max_ncpus; i++) {
+ dtrace_bufdesc_t *buf;
+
+ if (dt_get_buf(dtp, i, &buf) != 0)
+ return (-1);
+ if (buf != NULL) {
+ if (first_timestamp == 0)
+ first_timestamp = buf->dtbd_timestamp;
+ assert(buf->dtbd_timestamp >= first_timestamp);
+
+ dt_pq_insert(dtp->dt_bufq, buf);
+ drops[i] = buf->dtbd_drops;
+ buf->dtbd_drops = 0;
+ }
+ }
+
+ /* Consume records. */
+ for (;;) {
+ dtrace_bufdesc_t *buf = dt_pq_pop(dtp->dt_bufq);
+ uint64_t timestamp;
+
+ if (buf == NULL)
+ break;
+
+ timestamp = dt_buf_oldest(buf, dtp);
+ assert(timestamp >= dtp->dt_last_timestamp);
+ dtp->dt_last_timestamp = timestamp;
+
+ if (timestamp == buf->dtbd_timestamp) {
+ /*
+ * We've reached the end of the time covered
+ * by this buffer. If this is the oldest
+ * buffer, we must do another pass
+ * to retrieve more data.
+ */
+ dt_put_buf(dtp, buf);
+ if (timestamp == first_timestamp &&
+ !dtp->dt_stopped)
+ break;
+ continue;
+ }
+
+ if ((rval = dt_consume_cpu(dtp, fp,
+ buf->dtbd_cpu, buf, B_TRUE, pf, rf, arg)) != 0)
+ return (rval);
+ dt_pq_insert(dtp->dt_bufq, buf);
+ }
+
+ /* Consume drops. */
+ for (i = 0; i < max_ncpus; i++) {
+ if (drops[i] != 0) {
+ int error = dt_handle_cpudrop(dtp, i,
+ DTRACEDROP_PRINCIPAL, drops[i]);
+ if (error != 0)
+ return (error);
+ }
+ }
/*
- * If we have stopped, we want to process the CPU on which the
- * END probe was processed only _after_ we have processed
- * everything else.
+ * Reduce memory usage by re-allocating smaller buffers
+ * for the "remnants".
*/
- if (dtp->dt_stopped && (i == dtp->dt_endedon))
- continue;
-
- if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
- /*
- * If we failed with ENOENT, it may be because the
- * CPU was unconfigured -- this is okay. Any other
- * error, however, is unexpected.
- */
- if (errno == ENOENT)
- continue;
-
- return (dt_set_errno(dtp, errno));
- }
-
- if ((rval = dt_consume_cpu(dtp, fp, i, buf, pf, rf, arg)) != 0)
- return (rval);
+ while (buf = dt_pq_walk(dtp->dt_bufq, &cookie))
+ dt_realloc_buf(dtp, buf, buf->dtbd_size);
}
- if (!dtp->dt_stopped)
- return (0);
-
- buf->dtbd_cpu = dtp->dt_endedon;
-
- if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
- /*
- * This _really_ shouldn't fail, but it is strictly speaking
- * possible for this to return ENOENT if the CPU that called
- * the END enabling somehow managed to become unconfigured.
- * It's unclear how the user can possibly expect anything
- * rational to happen in this case -- the state has been thrown
- * out along with the unconfigured CPU -- so we'll just drive
- * on...
- */
- if (errno == ENOENT)
- return (0);
-
- return (dt_set_errno(dtp, errno));
- }
-
- return (dt_consume_cpu(dtp, fp, dtp->dt_endedon, buf, pf, rf, arg));
+ return (0);
}
--- a/usr/src/lib/libdtrace/common/dt_dis.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_dis.c Wed Jul 25 19:05:31 2012 -0400
@@ -19,12 +19,15 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
#include <strings.h>
#include <stdio.h>
@@ -212,12 +215,22 @@
{
static const char *const tnames[] = { "D type", "string" };
uint_t type = DIF_INSTR_TYPE(in);
+ const char *pad;
- (void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u, %%r%u",
- name, type, DIF_INSTR_R2(in), DIF_INSTR_RS(in));
+ if (DIF_INSTR_OP(in) == DIF_OP_PUSHTV) {
+ (void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u",
+ name, type, DIF_INSTR_RS(in));
+ pad = "\t\t";
+ } else {
+ (void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u, %%r%u",
+ name, type, DIF_INSTR_R2(in), DIF_INSTR_RS(in));
+ pad = "\t";
+ }
- if (type < sizeof (tnames) / sizeof (tnames[0]))
- (void) fprintf(fp, "\t! DT_TYPE(%u) = %s", type, tnames[type]);
+ if (type < sizeof (tnames) / sizeof (tnames[0])) {
+ (void) fprintf(fp, "%s! DT_TYPE(%u) = %s", pad,
+ type, tnames[type]);
+ }
}
static void
--- a/usr/src/lib/libdtrace/common/dt_error.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_error.c Wed Jul 25 19:05:31 2012 -0400
@@ -18,11 +18,16 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
#include <strings.h>
#include <dt_impl.h>
@@ -36,7 +41,6 @@
{ EDT_VERSREDUCED, "Requested version conflicts with earlier setting" },
{ EDT_CTF, "Unexpected libctf error" },
{ EDT_COMPILER, "Error in D program compilation" },
- { EDT_NOREG, "Insufficient registers to generate code" },
{ EDT_NOTUPREG, "Insufficient tuple registers to generate code" },
{ EDT_NOMEM, "Memory allocation failure" },
{ EDT_INT2BIG, "Integer constant table limit exceeded" },
--- a/usr/src/lib/libdtrace/common/dt_errtags.h Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_errtags.h Wed Jul 25 19:05:31 2012 -0400
@@ -26,7 +26,7 @@
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#ifndef _DT_ERRTAGS_H
@@ -259,7 +259,8 @@
D_LLQUANT_FACTORNSTEPS, /* llquantize() # steps < factor */
D_LLQUANT_FACTOREVEN, /* llquantize() bad # steps/factor */
D_LLQUANT_FACTORSMALL, /* llquantize() magnitude too small */
- D_LLQUANT_MAGTOOBIG /* llquantize() high mag too large */
+ D_LLQUANT_MAGTOOBIG, /* llquantize() high mag too large */
+ D_NOREG /* no available internal registers */
} dt_errtag_t;
extern const char *dt_errtag(dt_errtag_t);
--- a/usr/src/lib/libdtrace/common/dt_impl.h Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_impl.h Wed Jul 25 19:05:31 2012 -0400
@@ -26,7 +26,7 @@
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#ifndef _DT_IMPL_H
@@ -55,6 +55,7 @@
#include <dt_proc.h>
#include <dt_dof.h>
#include <dt_pcb.h>
+#include <dt_pq.h>
struct dt_module; /* see below */
struct dt_pfdict; /* see <dt_printf.h> */
@@ -226,6 +227,7 @@
uint_t dt_provbuckets; /* number of provider hash buckets */
uint_t dt_nprovs; /* number of providers in hash and list */
dt_proc_hash_t *dt_procs; /* hash table of grabbed process handles */
+ char **dt_proc_env; /* additional environment variables */
dt_intdesc_t dt_ints[6]; /* cached integer type descriptions */
ctf_id_t dt_type_func; /* cached CTF identifier for function type */
ctf_id_t dt_type_fptr; /* cached CTF identifier for function pointer */
@@ -244,7 +246,7 @@
int dt_maxstrdata; /* max strdata ID */
char **dt_strdata; /* pointer to strdata array */
dt_aggregate_t dt_aggregate; /* aggregate */
- dtrace_bufdesc_t dt_buf; /* staging buffer */
+ dt_pq_t *dt_bufq; /* CPU-specific data queue */
struct dt_pfdict *dt_pfdict; /* dictionary of printf conversions */
dt_version_t dt_vmax; /* optional ceiling on program API binding */
dtrace_attribute_t dt_amin; /* optional floor on program attributes */
@@ -305,6 +307,11 @@
struct utsname dt_uts; /* uname(2) information for system */
dt_list_t dt_lib_dep; /* scratch linked-list of lib dependencies */
dt_list_t dt_lib_dep_sorted; /* dependency sorted library list */
+ dtrace_flowkind_t dt_flow; /* flow kind */
+ const char *dt_prefix; /* recommended flow prefix */
+ int dt_indent; /* recommended flow indent */
+ dtrace_epid_t dt_last_epid; /* most recently consumed EPID */
+ uint64_t dt_last_timestamp; /* most recently consumed timestamp */
};
/*
@@ -438,7 +445,6 @@
EDT_VERSREDUCED, /* requested API version has been reduced */
EDT_CTF, /* libctf called failed (dt_ctferr has more) */
EDT_COMPILER, /* error in D program compilation */
- EDT_NOREG, /* register allocation failure */
EDT_NOTUPREG, /* tuple register allocation failure */
EDT_NOMEM, /* memory allocation failure */
EDT_INT2BIG, /* integer limit exceeded */
--- a/usr/src/lib/libdtrace/common/dt_open.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_open.c Wed Jul 25 19:05:31 2012 -0400
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <sys/types.h>
@@ -81,7 +81,7 @@
/*
* The version number should be increased for every customer visible release
- * of Solaris. The major number should be incremented when a fundamental
+ * of DTrace. The major number should be incremented when a fundamental
* change has been made that would affect all consumers, and would reflect
* sweeping changes to DTrace or the D language. The minor number should be
* incremented when a change is introduced that could break scripts that had
@@ -110,8 +110,9 @@
#define DT_VERS_1_8 DT_VERSION_NUMBER(1, 8, 0)
#define DT_VERS_1_8_1 DT_VERSION_NUMBER(1, 8, 1)
#define DT_VERS_1_9 DT_VERSION_NUMBER(1, 9, 0)
-#define DT_VERS_LATEST DT_VERS_1_9
-#define DT_VERS_STRING "Sun D 1.9"
+#define DT_VERS_1_9_1 DT_VERSION_NUMBER(1, 9, 1)
+#define DT_VERS_LATEST DT_VERS_1_9_1
+#define DT_VERS_STRING "Sun D 1.9.1"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -132,6 +133,7 @@
DT_VERS_1_8, /* D API 1.8 */
DT_VERS_1_8_1, /* D API 1.8.1 */
DT_VERS_1_9, /* D API 1.9 */
+ DT_VERS_1_9_1, /* D API 1.9.1 */
0
};
@@ -937,7 +939,7 @@
dtp->dt_mods = calloc(dtp->dt_modbuckets, sizeof (dt_module_t *));
dtp->dt_provbuckets = _dtrace_strbuckets;
dtp->dt_provs = calloc(dtp->dt_provbuckets, sizeof (dt_provider_t *));
- dt_proc_hash_create(dtp);
+ dt_proc_init(dtp);
dtp->dt_vmax = DT_VERS_LATEST;
dtp->dt_cpp_path = strdup(_dtrace_defcpp);
dtp->dt_cpp_argv = malloc(sizeof (char *));
@@ -951,8 +953,9 @@
(void) uname(&dtp->dt_uts);
if (dtp->dt_mods == NULL || dtp->dt_provs == NULL ||
- dtp->dt_procs == NULL || dtp->dt_ld_path == NULL ||
- dtp->dt_cpp_path == NULL || dtp->dt_cpp_argv == NULL)
+ dtp->dt_procs == NULL || dtp->dt_proc_env == NULL ||
+ dtp->dt_ld_path == NULL || dtp->dt_cpp_path == NULL ||
+ dtp->dt_cpp_argv == NULL)
return (set_open_errno(dtp, errp, EDT_NOMEM));
for (i = 0; i < DTRACEOPT_MAX; i++)
@@ -1318,7 +1321,7 @@
int i;
if (dtp->dt_procs != NULL)
- dt_proc_hash_destroy(dtp);
+ dt_proc_fini(dtp);
while ((pgp = dt_list_next(&dtp->dt_programs)) != NULL)
dt_program_destroy(dtp, pgp);
@@ -1365,7 +1368,6 @@
dt_strdata_destroy(dtp);
dt_buffered_destroy(dtp);
dt_aggregate_destroy(dtp);
- free(dtp->dt_buf.dtbd_data);
dt_pfdict_destroy(dtp);
dt_provmod_destroy(&dtp->dt_provmod);
dt_dof_fini(dtp);
--- a/usr/src/lib/libdtrace/common/dt_options.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_options.c Wed Jul 25 19:05:31 2012 -0400
@@ -24,6 +24,10 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
#include <sys/resource.h>
#include <sys/mman.h>
#include <sys/types.h>
@@ -364,6 +368,61 @@
return (0);
}
+static int
+dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
+{
+ char **p;
+ char *var;
+ int i;
+
+ /*
+ * We can't effectively set environment variables from #pragma lines
+ * since the processes have already been spawned.
+ */
+ if (dtp->dt_pcb != NULL)
+ return (dt_set_errno(dtp, EDT_BADOPTCTX));
+
+ if (arg == NULL)
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ if (!option && strchr(arg, '=') != NULL)
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ for (i = 1, p = dtp->dt_proc_env; *p != NULL; i++, p++)
+ continue;
+
+ for (p = dtp->dt_proc_env; *p != NULL; p++) {
+ var = strchr(*p, '=');
+ if (var == NULL)
+ var = *p + strlen(*p);
+ if (strncmp(*p, arg, var - *p) == 0) {
+ dt_free(dtp, *p);
+ *p = dtp->dt_proc_env[i - 1];
+ dtp->dt_proc_env[i - 1] = NULL;
+ i--;
+ }
+ }
+
+ if (option) {
+ if ((var = strdup(arg)) == NULL)
+ return (dt_set_errno(dtp, EDT_NOMEM));
+
+ if ((p = dt_alloc(dtp, sizeof (char *) * (i + 1))) == NULL) {
+ dt_free(dtp, var);
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ }
+
+ bcopy(dtp->dt_proc_env, p, sizeof (char *) * i);
+ dt_free(dtp, dtp->dt_proc_env);
+ dtp->dt_proc_env = p;
+
+ dtp->dt_proc_env[i - 1] = var;
+ dtp->dt_proc_env[i] = NULL;
+ }
+
+ return (0);
+}
+
/*ARGSUSED*/
static int
dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
@@ -407,7 +466,6 @@
return (0);
}
-
/*ARGSUSED*/
static int
dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
@@ -874,6 +932,7 @@
{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
{ "pgmax", dt_opt_pgmax },
{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
+ { "setenv", dt_opt_setenv, 1 },
{ "stdc", dt_opt_stdc },
{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
{ "syslibdir", dt_opt_syslibdir },
@@ -882,6 +941,7 @@
{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },
{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },
{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },
+ { "unsetenv", dt_opt_setenv, 0 },
{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },
{ "version", dt_opt_version },
{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },
@@ -909,6 +969,7 @@
{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },
{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },
{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },
+ { "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL },
{ NULL }
};
--- a/usr/src/lib/libdtrace/common/dt_parser.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_parser.c Wed Jul 25 19:05:31 2012 -0400
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, Joyent Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
@@ -93,6 +94,7 @@
*/
#include <sys/param.h>
+#include <sys/sysmacros.h>
#include <limits.h>
#include <setjmp.h>
#include <strings.h>
@@ -1856,6 +1858,38 @@
return (dnp);
}
+/*
+ * If an integer constant is being cast to another integer type, we can
+ * perform the cast as part of integer constant folding in this pass. We must
+ * take action when the integer is being cast to a smaller type or if it is
+ * changing signed-ness. If so, we first shift rp's bits bits high (losing
+ * excess bits if narrowing) and then shift them down with either a logical
+ * shift (unsigned) or arithmetic shift (signed).
+ */
+static void
+dt_cast(dt_node_t *lp, dt_node_t *rp)
+{
+ size_t srcsize = dt_node_type_size(rp);
+ size_t dstsize = dt_node_type_size(lp);
+
+ if (dstsize < srcsize) {
+ int n = (sizeof (uint64_t) - dstsize) * NBBY;
+ rp->dn_value <<= n;
+ rp->dn_value >>= n;
+ } else if (dstsize > srcsize) {
+ int n = (sizeof (uint64_t) - srcsize) * NBBY;
+ int s = (dstsize - srcsize) * NBBY;
+
+ rp->dn_value <<= n;
+ if (rp->dn_flags & DT_NF_SIGNED) {
+ rp->dn_value = (intmax_t)rp->dn_value >> s;
+ rp->dn_value >>= n - s;
+ } else {
+ rp->dn_value >>= n;
+ }
+ }
+}
+
dt_node_t *
dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
{
@@ -2005,32 +2039,9 @@
}
}
- /*
- * If an integer constant is being cast to another integer type, we can
- * perform the cast as part of integer constant folding in this pass.
- * We must take action when the integer is being cast to a smaller type
- * or if it is changing signed-ness. If so, we first shift rp's bits
- * bits high (losing excess bits if narrowing) and then shift them down
- * with either a logical shift (unsigned) or arithmetic shift (signed).
- */
if (op == DT_TOK_LPAR && rp->dn_kind == DT_NODE_INT &&
dt_node_is_integer(lp)) {
- size_t srcsize = dt_node_type_size(rp);
- size_t dstsize = dt_node_type_size(lp);
-
- if ((dstsize < srcsize) || ((lp->dn_flags & DT_NF_SIGNED) ^
- (rp->dn_flags & DT_NF_SIGNED))) {
- int n = dstsize < srcsize ?
- (sizeof (uint64_t) * NBBY - dstsize * NBBY) :
- (sizeof (uint64_t) * NBBY - srcsize * NBBY);
-
- rp->dn_value <<= n;
- if (lp->dn_flags & DT_NF_SIGNED)
- rp->dn_value = (intmax_t)rp->dn_value >> n;
- else
- rp->dn_value = rp->dn_value >> n;
- }
-
+ dt_cast(lp, rp);
dt_node_type_propagate(lp, rp);
dt_node_attr_assign(rp, dt_attr_min(lp->dn_attr, rp->dn_attr));
dt_node_free(lp);
@@ -2889,14 +2900,14 @@
case DT_TOK_DEREF:
/*
* If the deref operator is applied to a translated pointer,
- * we can just set our output type to the base translation.
+ * we set our output type to the output of the translation.
*/
if ((idp = dt_node_resolve(cp, DT_IDENT_XLPTR)) != NULL) {
dt_xlator_t *dxp = idp->di_data;
dnp->dn_ident = &dxp->dx_souid;
dt_node_type_assign(dnp,
- DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
break;
}
@@ -3072,6 +3083,31 @@
return (dnp);
}
+static void
+dt_assign_common(dt_node_t *dnp)
+{
+ dt_node_t *lp = dnp->dn_left;
+ dt_node_t *rp = dnp->dn_right;
+ int op = dnp->dn_op;
+
+ if (rp->dn_kind == DT_NODE_INT)
+ dt_cast(lp, rp);
+
+ if (!(lp->dn_flags & DT_NF_LVALUE)) {
+ xyerror(D_OP_LVAL, "operator %s requires modifiable "
+ "lvalue as an operand\n", opstr(op));
+ /* see K&R[A7.17] */
+ }
+
+ if (!(lp->dn_flags & DT_NF_WRITABLE)) {
+ xyerror(D_OP_WRITE, "operator %s can only be applied "
+ "to a writable variable\n", opstr(op));
+ }
+
+ dt_node_type_propagate(lp, dnp); /* see K&R[A7.17] */
+ dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
+}
+
static dt_node_t *
dt_cook_op2(dt_node_t *dnp, uint_t idflags)
{
@@ -3550,19 +3586,7 @@
}
}
asgn_common:
- if (!(lp->dn_flags & DT_NF_LVALUE)) {
- xyerror(D_OP_LVAL, "operator %s requires modifiable "
- "lvalue as an operand\n", opstr(op));
- /* see K&R[A7.17] */
- }
-
- if (!(lp->dn_flags & DT_NF_WRITABLE)) {
- xyerror(D_OP_WRITE, "operator %s can only be applied "
- "to a writable variable\n", opstr(op));
- }
-
- dt_node_type_propagate(lp, dnp); /* see K&R[A7.17] */
- dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
+ dt_assign_common(dnp);
break;
case DT_TOK_PTR:
@@ -3867,6 +3891,14 @@
dt_node_type_propagate(lp, dnp); /* see K&R[A7.5] */
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
+
+ /*
+ * If it's a pointer then should be able to (attempt to)
+ * assign to it.
+ */
+ if (lkind == CTF_K_POINTER)
+ dnp->dn_flags |= DT_NF_WRITABLE;
+
break;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdtrace/common/dt_pq.c Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,157 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#include <dtrace.h>
+#include <dt_impl.h>
+#include <dt_pq.h>
+#include <assert.h>
+
+/*
+ * Create a new priority queue.
+ *
+ * size is the maximum number of items that will be stored in the priority
+ * queue at one time.
+ */
+dt_pq_t *
+dt_pq_init(dtrace_hdl_t *dtp, uint_t size, dt_pq_value_f value_cb, void *cb_arg)
+{
+ dt_pq_t *p;
+ assert(size > 1);
+
+ if ((p = dt_zalloc(dtp, sizeof (dt_pq_t))) == NULL)
+ return (NULL);
+
+ p->dtpq_items = dt_zalloc(dtp, size * sizeof (p->dtpq_items[0]));
+ if (p->dtpq_items == NULL) {
+ dt_free(dtp, p);
+ return (NULL);
+ }
+
+ p->dtpq_hdl = dtp;
+ p->dtpq_size = size;
+ p->dtpq_last = 1;
+ p->dtpq_value = value_cb;
+ p->dtpq_arg = cb_arg;
+
+ return (p);
+}
+
+void
+dt_pq_fini(dt_pq_t *p)
+{
+ dtrace_hdl_t *dtp = p->dtpq_hdl;
+
+ dt_free(dtp, p->dtpq_items);
+ dt_free(dtp, p);
+}
+
+static uint64_t
+dt_pq_getvalue(dt_pq_t *p, uint_t index)
+{
+ void *item = p->dtpq_items[index];
+ return (p->dtpq_value(item, p->dtpq_arg));
+}
+
+void
+dt_pq_insert(dt_pq_t *p, void *item)
+{
+ uint_t i;
+
+ assert(p->dtpq_last < p->dtpq_size);
+
+ i = p->dtpq_last++;
+ p->dtpq_items[i] = item;
+
+ while (i > 1 && dt_pq_getvalue(p, i) < dt_pq_getvalue(p, i / 2)) {
+ void *tmp = p->dtpq_items[i];
+ p->dtpq_items[i] = p->dtpq_items[i / 2];
+ p->dtpq_items[i / 2] = tmp;
+ i /= 2;
+ }
+}
+
+/*
+ * Return elements from the priority queue. *cookie should be zero when first
+ * called. Returns NULL when there are no more elements.
+ */
+void *
+dt_pq_walk(dt_pq_t *p, uint_t *cookie)
+{
+ (*cookie)++;
+ if (*cookie >= p->dtpq_last)
+ return (NULL);
+
+ return (p->dtpq_items[*cookie]);
+}
+
+void *
+dt_pq_pop(dt_pq_t *p)
+{
+ uint_t i = 1;
+ void *ret;
+
+ assert(p->dtpq_last > 0);
+
+ if (p->dtpq_last == 1)
+ return (NULL);
+
+ ret = p->dtpq_items[1];
+
+ p->dtpq_last--;
+ p->dtpq_items[1] = p->dtpq_items[p->dtpq_last];
+ p->dtpq_items[p->dtpq_last] = NULL;
+
+ for (;;) {
+ uint_t lc = i * 2;
+ uint_t rc = i * 2 + 1;
+ uint_t c;
+ uint64_t v;
+ void *tmp;
+
+ if (lc >= p->dtpq_last)
+ break;
+
+ if (rc >= p->dtpq_last) {
+ c = lc;
+ v = dt_pq_getvalue(p, lc);
+ } else {
+ uint64_t lv = dt_pq_getvalue(p, lc);
+ uint64_t rv = dt_pq_getvalue(p, rc);
+
+ if (lv < rv) {
+ c = lc;
+ v = lv;
+ } else {
+ c = rc;
+ v = rv;
+ }
+ }
+
+ if (v >= dt_pq_getvalue(p, i))
+ break;
+
+ tmp = p->dtpq_items[i];
+ p->dtpq_items[i] = p->dtpq_items[c];
+ p->dtpq_items[c] = tmp;
+
+ i = c;
+ }
+
+ return (ret);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdtrace/common/dt_pq.h Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,51 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#ifndef _DT_PQ_H
+#define _DT_PQ_H
+
+#include <dtrace.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint64_t (*dt_pq_value_f)(void *, void *);
+
+typedef struct dt_pq {
+ dtrace_hdl_t *dtpq_hdl; /* dtrace handle */
+ void **dtpq_items; /* array of elements */
+ uint_t dtpq_size; /* count of allocated elements */
+ uint_t dtpq_last; /* next free slot */
+ dt_pq_value_f dtpq_value; /* callback to get the value */
+ void *dtpq_arg; /* callback argument */
+} dt_pq_t;
+
+extern dt_pq_t *dt_pq_init(dtrace_hdl_t *, uint_t size, dt_pq_value_f, void *);
+extern void dt_pq_fini(dt_pq_t *);
+
+extern void dt_pq_insert(dt_pq_t *, void *);
+extern void *dt_pq_pop(dt_pq_t *);
+extern void *dt_pq_walk(dt_pq_t *, uint_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DT_PQ_H */
--- a/usr/src/lib/libdtrace/common/dt_printf.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_printf.c Wed Jul 25 19:05:31 2012 -0400
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <sys/sysmacros.h>
@@ -154,7 +155,7 @@
pfcheck_dint(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp)
{
if (dnp->dn_flags & DT_NF_SIGNED)
- pfd->pfd_flags |= DT_PFCONV_SIGNED;
+ pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'i';
else
pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'u';
@@ -642,7 +643,7 @@
{ "hu", "u", "unsigned short", pfcheck_type, pfprint_uint },
{ "hx", "x", "short", pfcheck_xshort, pfprint_uint },
{ "hX", "X", "short", pfcheck_xshort, pfprint_uint },
-{ "i", "i", pfproto_xint, pfcheck_dint, pfprint_dint },
+{ "i", "i", pfproto_xint, pfcheck_xint, pfprint_sint },
{ "I", "s", pfproto_cstr, pfcheck_str, pfprint_inetaddr },
{ "k", "s", "stack", pfcheck_stack, pfprint_stack },
{ "lc", "lc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wint_t */
--- a/usr/src/lib/libdtrace/common/dt_proc.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_proc.c Wed Jul 25 19:05:31 2012 -0400
@@ -25,6 +25,10 @@
*/
/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
* DTrace Process Control
*
* This file provides a set of routines that permit libdtrace and its clients
@@ -460,7 +464,7 @@
dt_proc_control_data_t *datap = arg;
dtrace_hdl_t *dtp = datap->dpcd_hdl;
dt_proc_t *dpr = datap->dpcd_proc;
- dt_proc_hash_t *dph = dpr->dpr_hdl->dt_procs;
+ dt_proc_hash_t *dph = dtp->dt_procs;
struct ps_prochandle *P = dpr->dpr_proc;
int pfd = Pctlfd(P);
@@ -870,7 +874,8 @@
(void) pthread_mutex_init(&dpr->dpr_lock, NULL);
(void) pthread_cond_init(&dpr->dpr_cv, NULL);
- if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0)) == NULL) {
+ dpr->dpr_proc = Pxcreate(file, argv, dtp->dt_proc_env, &err, NULL, 0);
+ if (dpr->dpr_proc == NULL) {
return (dt_proc_error(dtp, dpr,
"failed to execute %s: %s\n", file, Pcreate_error(err)));
}
@@ -1034,30 +1039,75 @@
}
void
-dt_proc_hash_create(dtrace_hdl_t *dtp)
+dt_proc_init(dtrace_hdl_t *dtp)
{
+ extern char **environ;
+ static char *envdef[] = {
+ "LD_NOLAZYLOAD=1", /* linker lazy loading hides funcs */
+ NULL
+ };
+ char **p;
+ int i;
+
if ((dtp->dt_procs = dt_zalloc(dtp, sizeof (dt_proc_hash_t) +
- sizeof (dt_proc_t *) * _dtrace_pidbuckets - 1)) != NULL) {
+ sizeof (dt_proc_t *) * _dtrace_pidbuckets - 1)) == NULL)
+ return;
+
+ (void) pthread_mutex_init(&dtp->dt_procs->dph_lock, NULL);
+ (void) pthread_cond_init(&dtp->dt_procs->dph_cv, NULL);
+
+ dtp->dt_procs->dph_hashlen = _dtrace_pidbuckets;
+ dtp->dt_procs->dph_lrulim = _dtrace_pidlrulim;
+
- (void) pthread_mutex_init(&dtp->dt_procs->dph_lock, NULL);
- (void) pthread_cond_init(&dtp->dt_procs->dph_cv, NULL);
+ /*
+ * Count how big our environment needs to be.
+ */
+ for (i = 1, p = environ; *p != NULL; i++, p++)
+ continue;
+ for (p = envdef; *p != NULL; i++, p++)
+ continue;
+
+ if ((dtp->dt_proc_env = dt_zalloc(dtp, sizeof (char *) * i)) == NULL)
+ return;
- dtp->dt_procs->dph_hashlen = _dtrace_pidbuckets;
- dtp->dt_procs->dph_lrulim = _dtrace_pidlrulim;
+ for (i = 0, p = environ; *p != NULL; i++, p++) {
+ if ((dtp->dt_proc_env[i] = strdup(*p)) == NULL)
+ goto err;
+ }
+ for (p = envdef; *p != NULL; i++, p++) {
+ if ((dtp->dt_proc_env[i] = strdup(*p)) == NULL)
+ goto err;
}
+
+ return;
+
+err:
+ while (--i != 0) {
+ dt_free(dtp, dtp->dt_proc_env[i]);
+ }
+ dt_free(dtp, dtp->dt_proc_env);
+ dtp->dt_proc_env = NULL;
}
void
-dt_proc_hash_destroy(dtrace_hdl_t *dtp)
+dt_proc_fini(dtrace_hdl_t *dtp)
{
dt_proc_hash_t *dph = dtp->dt_procs;
dt_proc_t *dpr;
+ char **p;
while ((dpr = dt_list_next(&dph->dph_lrulist)) != NULL)
dt_proc_destroy(dtp, dpr->dpr_proc);
dtp->dt_procs = NULL;
dt_free(dtp, dph);
+
+ for (p = dtp->dt_proc_env; *p != NULL; p++)
+ dt_free(dtp, *p);
+
+ dt_free(dtp, dtp->dt_proc_env);
+ dtp->dt_proc_env = NULL;
}
struct ps_prochandle *
--- a/usr/src/lib/libdtrace/common/dt_proc.h Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_proc.h Wed Jul 25 19:05:31 2012 -0400
@@ -24,11 +24,13 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
#ifndef _DT_PROC_H
#define _DT_PROC_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <libproc.h>
#include <dtrace.h>
#include <pthread.h>
@@ -106,8 +108,8 @@
extern void dt_proc_unlock(dtrace_hdl_t *, struct ps_prochandle *);
extern dt_proc_t *dt_proc_lookup(dtrace_hdl_t *, struct ps_prochandle *, int);
-extern void dt_proc_hash_create(dtrace_hdl_t *);
-extern void dt_proc_hash_destroy(dtrace_hdl_t *);
+extern void dt_proc_init(dtrace_hdl_t *);
+extern void dt_proc_fini(dtrace_hdl_t *);
#ifdef __cplusplus
}
--- a/usr/src/lib/libdtrace/common/dt_regset.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_regset.c Wed Jul 25 19:05:31 2012 -0400
@@ -19,12 +19,15 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
#include <sys/types.h>
#include <sys/bitmap.h>
@@ -33,18 +36,19 @@
#include <stdlib.h>
#include <dt_regset.h>
+#include <dt_impl.h>
dt_regset_t *
-dt_regset_create(ulong_t size)
+dt_regset_create(ulong_t nregs)
{
- ulong_t n = BT_BITOUL(size + 1); /* + 1 for %r0 */
+ ulong_t n = BT_BITOUL(nregs);
dt_regset_t *drp = malloc(sizeof (dt_regset_t));
if (drp == NULL)
return (NULL);
drp->dr_bitmap = malloc(sizeof (ulong_t) * n);
- drp->dr_size = size + 1;
+ drp->dr_size = nregs;
if (drp->dr_bitmap == NULL) {
dt_regset_destroy(drp);
@@ -68,6 +72,25 @@
bzero(drp->dr_bitmap, sizeof (ulong_t) * BT_BITOUL(drp->dr_size));
}
+void
+dt_regset_assert_free(dt_regset_t *drp)
+{
+ int reg;
+ boolean_t fail = B_FALSE;
+ for (reg = 0; reg < drp->dr_size; reg++) {
+ if (BT_TEST(drp->dr_bitmap, reg) != 0) {
+ dt_dprintf("%%r%d was left allocated\n", reg);
+ fail = B_TRUE;
+ }
+ }
+
+ /*
+ * We set this during dtest runs to check for register leaks.
+ */
+ if (fail && getenv("DTRACE_DEBUG_REGSET") != NULL)
+ abort();
+}
+
int
dt_regset_alloc(dt_regset_t *drp)
{
@@ -95,13 +118,15 @@
}
}
- return (-1); /* no available registers */
+ xyerror(D_NOREG, "Insufficient registers to generate code");
+ /*NOTREACHED*/
+ return (-1);
}
void
dt_regset_free(dt_regset_t *drp, int reg)
{
- assert(reg > 0 && reg < drp->dr_size);
+ assert(reg >= 0 && reg < drp->dr_size);
assert(BT_TEST(drp->dr_bitmap, reg) != 0);
BT_CLEAR(drp->dr_bitmap, reg);
}
--- a/usr/src/lib/libdtrace/common/dt_regset.h Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_regset.h Wed Jul 25 19:05:31 2012 -0400
@@ -19,16 +19,19 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
#ifndef _DT_REGSET_H
#define _DT_REGSET_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#ifdef __cplusplus
@@ -45,6 +48,7 @@
extern void dt_regset_reset(dt_regset_t *);
extern int dt_regset_alloc(dt_regset_t *);
extern void dt_regset_free(dt_regset_t *, int);
+extern void dt_regset_assert_free(dt_regset_t *);
#ifdef __cplusplus
}
--- a/usr/src/lib/libdtrace/common/dt_subr.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_subr.c Wed Jul 25 19:05:31 2012 -0400
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <sys/sysmacros.h>
@@ -577,8 +578,8 @@
size_t avail;
/*
- * It's not legal to use buffered ouput if there is not a
- * handler for buffered output.
+ * Using buffered output is not allowed if a handler has
+ * not been installed.
*/
if (dtp->dt_bufhdlr == NULL) {
va_end(ap);
--- a/usr/src/lib/libdtrace/i386/dt_isadep.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/i386/dt_isadep.c Wed Jul 25 19:05:31 2012 -0400
@@ -24,6 +24,10 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
@@ -481,7 +485,8 @@
* another debugger attached to this process. The original instruction
* can't be recovered so this must fail.
*/
- if (x86dis.d86_len == 1 && instr[0] == FASTTRAP_INSTR)
+ if (x86dis.d86_len == 1 &&
+ (uchar_t)x86dis.d86_bytes[0] == FASTTRAP_INSTR)
return (-1);
return (x86dis.d86_len);
--- a/usr/src/pkg/manifests/system-dtrace-tests.mf Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/pkg/manifests/system-dtrace-tests.mf Wed Jul 25 19:05:31 2012 -0400
@@ -21,7 +21,7 @@
#
# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright (c) 2011 by Delphix. All rights reserved.
+# Copyright (c) 2012 by Delphix. All rights reserved.
#
set name=pkg.fmri value=pkg:/system/dtrace/tests@$(PKGVERS)
@@ -52,6 +52,7 @@
dir path=opt/SUNWdtrt/tst/common/bitfields
dir path=opt/SUNWdtrt/tst/common/buffering
dir path=opt/SUNWdtrt/tst/common/builtinvar
+dir path=opt/SUNWdtrt/tst/common/cg
dir path=opt/SUNWdtrt/tst/common/clauses
dir path=opt/SUNWdtrt/tst/common/cpc
dir path=opt/SUNWdtrt/tst/common/decls
@@ -59,6 +60,7 @@
dir path=opt/SUNWdtrt/tst/common/dtraceUtil
dir path=opt/SUNWdtrt/tst/common/end
dir path=opt/SUNWdtrt/tst/common/enum
+dir path=opt/SUNWdtrt/tst/common/env
dir path=opt/SUNWdtrt/tst/common/error
dir path=opt/SUNWdtrt/tst/common/exit
dir path=opt/SUNWdtrt/tst/common/fbtprovider
@@ -333,6 +335,8 @@
file path=opt/SUNWdtrt/tst/common/aggs/tst.signedkeys.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/aggs/tst.signedkeyspos.d mode=0444
file path=opt/SUNWdtrt/tst/common/aggs/tst.signedkeyspos.d.out mode=0444
+file path=opt/SUNWdtrt/tst/common/aggs/tst.sizedkeys.d mode=0444
+file path=opt/SUNWdtrt/tst/common/aggs/tst.sizedkeys.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/aggs/tst.stddev.d mode=0444
file path=opt/SUNWdtrt/tst/common/aggs/tst.stddev.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/aggs/tst.subr.d mode=0444
@@ -357,7 +361,14 @@
file path=opt/SUNWdtrt/tst/common/arithmetic/err.D_SYNTAX.muladd.d mode=0444
file path=opt/SUNWdtrt/tst/common/arithmetic/err.D_SYNTAX.muldiv.d mode=0444
file path=opt/SUNWdtrt/tst/common/arithmetic/tst.basics.d mode=0444
-file path=opt/SUNWdtrt/tst/common/arithmetic/tst.complex.d mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.basics.d.out mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.compcast.d mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.compcast.d.out mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.compnarrowassign.d mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.compnarrowassign.d.out \
+ mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.execcast.d mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.execcast.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/arrays/err.D_ARR_BADREF.bad.d mode=0444
file path=opt/SUNWdtrt/tst/common/arrays/err.D_DECL_ARRBIG.toobig.d mode=0444
file path=opt/SUNWdtrt/tst/common/arrays/err.D_DECL_ARRNULL.bad.d mode=0444
@@ -474,6 +485,8 @@
file path=opt/SUNWdtrt/tst/common/builtinvar/tst.tid1.d mode=0444
file path=opt/SUNWdtrt/tst/common/builtinvar/tst.timestamp.d mode=0444
file path=opt/SUNWdtrt/tst/common/builtinvar/tst.vtimestamp.d mode=0444
+file path=opt/SUNWdtrt/tst/common/cg/err.D_NOREG.noreg.d mode=0444
+file path=opt/SUNWdtrt/tst/common/cg/err.baddif.d mode=0444
file path=opt/SUNWdtrt/tst/common/clauses/err.D_IDENT_UNDEF.aggfun.d mode=0444
file path=opt/SUNWdtrt/tst/common/clauses/err.D_IDENT_UNDEF.aggtup.d mode=0444
file path=opt/SUNWdtrt/tst/common/clauses/err.D_IDENT_UNDEF.arrtup.d mode=0444
@@ -720,6 +733,20 @@
file path=opt/SUNWdtrt/tst/common/enum/tst.EnumEquality.d mode=0444
file path=opt/SUNWdtrt/tst/common/enum/tst.EnumSameValue.d mode=0444
file path=opt/SUNWdtrt/tst/common/enum/tst.EnumValAssign.d mode=0444
+file path=opt/SUNWdtrt/tst/common/env/err.D_PRAGMA_OPTSET.setfromscript.d \
+ mode=0444
+file path=opt/SUNWdtrt/tst/common/env/err.D_PRAGMA_OPTSET.unsetfromscript.d \
+ mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.ld_nolazyload.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.ld_nolazyload.ksh.out mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.setenv1.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.setenv1.ksh.out mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.setenv2.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.setenv2.ksh.out mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.unsetenv1.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.unsetenv1.ksh.out mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.unsetenv2.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.unsetenv2.ksh.out mode=0444
file path=opt/SUNWdtrt/tst/common/error/tst.DTRACEFLT_BADADDR.d mode=0444
file path=opt/SUNWdtrt/tst/common/error/tst.DTRACEFLT_DIVZERO.d mode=0444
file path=opt/SUNWdtrt/tst/common/error/tst.DTRACEFLT_UNKNOWN.d mode=0444
@@ -1153,6 +1180,8 @@
file path=opt/SUNWdtrt/tst/common/pointers/tst.ValidPointer1.d mode=0444
file path=opt/SUNWdtrt/tst/common/pointers/tst.ValidPointer2.d mode=0444
file path=opt/SUNWdtrt/tst/common/pointers/tst.VoidCast.d mode=0444
+file path=opt/SUNWdtrt/tst/common/pointers/tst.assigncast1.d mode=0444
+file path=opt/SUNWdtrt/tst/common/pointers/tst.assigncast2.d mode=0444
file path=opt/SUNWdtrt/tst/common/pointers/tst.basic1.d mode=0444
file path=opt/SUNWdtrt/tst/common/pointers/tst.basic2.d mode=0444
file path=opt/SUNWdtrt/tst/common/pragma/err.D_PRAGERR.d mode=0444
@@ -1168,6 +1197,9 @@
file path=opt/SUNWdtrt/tst/common/pragma/tst.libdepfullyconnected.ksh \
mode=0444
file path=opt/SUNWdtrt/tst/common/pragma/tst.libdepsepdir.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/pragma/tst.temporal.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/pragma/tst.temporal2.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/pragma/tst.temporal3.d mode=0444
file path=opt/SUNWdtrt/tst/common/predicates/err.D_PRED_SCALAR.NonScalarPred.d \
mode=0444
file path=opt/SUNWdtrt/tst/common/predicates/err.D_SYNTAX.invalid.d mode=0444
@@ -1177,7 +1209,6 @@
file path=opt/SUNWdtrt/tst/common/predicates/tst.basics.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/predicates/tst.complex.d mode=0444
file path=opt/SUNWdtrt/tst/common/predicates/tst.complex.d.out mode=0444
-file path=opt/SUNWdtrt/tst/common/predicates/tst.predcache.ksh mode=0444
file path=opt/SUNWdtrt/tst/common/preprocessor/err.D_IDENT_UNDEF.afterprobe.d \
mode=0444
file path=opt/SUNWdtrt/tst/common/preprocessor/err.D_PRAGCTL_INVAL.tabdefine.d \
@@ -1222,17 +1253,19 @@
file path=opt/SUNWdtrt/tst/common/preprocessor/tst.preexpifelse.d.out \
mode=0444
file path=opt/SUNWdtrt/tst/common/preprocessor/tst.withinprobe.d mode=0444
-file path=opt/SUNWdtrt/tst/common/print/err.D_PRINT_DYN.bad.d mode=0444
file path=opt/SUNWdtrt/tst/common/print/err.D_PRINT_VOID.bad.d mode=0444
file path=opt/SUNWdtrt/tst/common/print/err.D_PROTO_LEN.bad.d mode=0444
file path=opt/SUNWdtrt/tst/common/print/tst.array.d mode=0444
file path=opt/SUNWdtrt/tst/common/print/tst.array.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/print/tst.bitfield.d mode=0444
file path=opt/SUNWdtrt/tst/common/print/tst.bitfield.d.out mode=0444
+file path=opt/SUNWdtrt/tst/common/print/tst.dyn.d mode=0444
file path=opt/SUNWdtrt/tst/common/print/tst.primitive.d mode=0444
file path=opt/SUNWdtrt/tst/common/print/tst.primitive.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/print/tst.struct.d mode=0444
file path=opt/SUNWdtrt/tst/common/print/tst.struct.d.out mode=0444
+file path=opt/SUNWdtrt/tst/common/print/tst.xlate.d mode=0444
+file path=opt/SUNWdtrt/tst/common/print/tst.xlate.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/printa/err.D_PRINTA_AGGARG.badagg.d \
mode=0444
file path=opt/SUNWdtrt/tst/common/printa/err.D_PRINTA_AGGARG.badfmt.d \
@@ -1313,6 +1346,8 @@
file path=opt/SUNWdtrt/tst/common/printf/tst.printgG.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/printf/tst.rawfmt.d mode=0444
file path=opt/SUNWdtrt/tst/common/printf/tst.rawfmt.d.out mode=0444
+file path=opt/SUNWdtrt/tst/common/printf/tst.signs.d mode=0444
+file path=opt/SUNWdtrt/tst/common/printf/tst.signs.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/printf/tst.str.d mode=0444
file path=opt/SUNWdtrt/tst/common/printf/tst.str.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/printf/tst.sym.d mode=0444
@@ -1766,8 +1801,8 @@
file path=opt/SUNWdtrt/tst/common/tick-n/tst.tickusec.d mode=0444
file path=opt/SUNWdtrt/tst/common/tick-n/tst.tickusec.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/trace/err.D_PROTO_LEN.bad.d mode=0444
-file path=opt/SUNWdtrt/tst/common/trace/err.D_TRACE_DYN.bad.d mode=0444
file path=opt/SUNWdtrt/tst/common/trace/err.D_TRACE_VOID.bad.d mode=0444
+file path=opt/SUNWdtrt/tst/common/trace/tst.dyn.d mode=0444
file path=opt/SUNWdtrt/tst/common/trace/tst.misc.d mode=0444
file path=opt/SUNWdtrt/tst/common/trace/tst.qstring.d mode=0444
file path=opt/SUNWdtrt/tst/common/trace/tst.qstring.d.out mode=0444
@@ -1838,6 +1873,14 @@
mode=0444
file path=opt/SUNWdtrt/tst/common/translators/tst.StructureAssignment.d \
mode=0444
+file path=opt/SUNWdtrt/tst/common/translators/tst.TestTransStability1.ksh \
+ mode=0444
+file path=opt/SUNWdtrt/tst/common/translators/tst.TestTransStability1.ksh.out \
+ mode=0444
+file path=opt/SUNWdtrt/tst/common/translators/tst.TestTransStability2.ksh \
+ mode=0444
+file path=opt/SUNWdtrt/tst/common/translators/tst.TestTransStability2.ksh.out \
+ mode=0444
file path=opt/SUNWdtrt/tst/common/translators/tst.TransNonPointer.d mode=0444
file path=opt/SUNWdtrt/tst/common/translators/tst.TransOutputPointer.d \
mode=0444
--- a/usr/src/uts/common/dtrace/dtrace.c Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/uts/common/dtrace/dtrace.c Wed Jul 25 19:05:31 2012 -0400
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
@@ -2401,9 +2402,10 @@
{
dtrace_speculation_t *spec;
dtrace_buffer_t *src, *dest;
- uintptr_t daddr, saddr, dlimit;
+ uintptr_t daddr, saddr, dlimit, slimit;
dtrace_speculation_state_t current, new;
intptr_t offs;
+ uint64_t timestamp;
if (which == 0)
return;
@@ -2479,7 +2481,37 @@
}
/*
- * We have the space; copy the buffer across. (Note that this is a
+ * We have sufficient space to copy the speculative buffer into the
+ * primary buffer. First, modify the speculative buffer, filling
+ * in the timestamp of all entries with the current time. The data
+ * must have the commit() time rather than the time it was traced,
+ * so that all entries in the primary buffer are in timestamp order.
+ */
+ timestamp = dtrace_gethrtime();
+ saddr = (uintptr_t)src->dtb_tomax;
+ slimit = saddr + src->dtb_offset;
+ while (saddr < slimit) {
+ size_t size;
+ dtrace_rechdr_t *dtrh = (dtrace_rechdr_t *)saddr;
+
+ if (dtrh->dtrh_epid == DTRACE_EPIDNONE) {
+ saddr += sizeof (dtrace_epid_t);
+ continue;
+ }
+ ASSERT3U(dtrh->dtrh_epid, <=, state->dts_necbs);
+ size = state->dts_ecbs[dtrh->dtrh_epid - 1]->dte_size;
+
+ ASSERT3U(saddr + size, <=, slimit);
+ ASSERT3U(size, >=, sizeof (dtrace_rechdr_t));
+ ASSERT3U(DTRACE_RECORD_LOAD_TIMESTAMP(dtrh), ==, UINT64_MAX);
+
+ DTRACE_RECORD_STORE_TIMESTAMP(dtrh, timestamp);
+
+ saddr += size;
+ }
+
+ /*
+ * Copy the buffer across. (Note that this is a
* highly subobtimal bcopy(); in the unlikely event that this becomes
* a serious performance issue, a high-performance DTrace-specific
* bcopy() should obviously be invented.)
@@ -5951,7 +5983,7 @@
if (now - state->dts_alive > dtrace_deadman_timeout) {
/*
* We seem to be dead. Unless we (a) have kernel
- * destructive permissions (b) have expicitly enabled
+ * destructive permissions (b) have explicitly enabled
* destructive actions and (c) destructive actions have
* not been disabled, we're going to transition into
* the KILLED state, from which no further processing
@@ -5979,8 +6011,18 @@
tomax = buf->dtb_tomax;
ASSERT(tomax != NULL);
- if (ecb->dte_size != 0)
- DTRACE_STORE(uint32_t, tomax, offs, ecb->dte_epid);
+ if (ecb->dte_size != 0) {
+ dtrace_rechdr_t dtrh;
+ if (!(mstate.dtms_present & DTRACE_MSTATE_TIMESTAMP)) {
+ mstate.dtms_timestamp = dtrace_gethrtime();
+ mstate.dtms_present |= DTRACE_MSTATE_TIMESTAMP;
+ }
+ ASSERT3U(ecb->dte_size, >=, sizeof (dtrace_rechdr_t));
+ dtrh.dtrh_epid = ecb->dte_epid;
+ DTRACE_RECORD_STORE_TIMESTAMP(&dtrh,
+ mstate.dtms_timestamp);
+ *((dtrace_rechdr_t *)(tomax + offs)) = dtrh;
+ }
mstate.dtms_epid = ecb->dte_epid;
mstate.dtms_present |= DTRACE_MSTATE_EPID;
@@ -6144,7 +6186,9 @@
continue;
switch (act->dta_kind) {
- case DTRACEACT_SPECULATE:
+ case DTRACEACT_SPECULATE: {
+ dtrace_rechdr_t *dtrh;
+
ASSERT(buf == &state->dts_buffer[cpuid]);
buf = dtrace_speculation_buffer(state,
cpuid, val);
@@ -6166,10 +6210,23 @@
tomax = buf->dtb_tomax;
ASSERT(tomax != NULL);
- if (ecb->dte_size != 0)
- DTRACE_STORE(uint32_t, tomax, offs,
- ecb->dte_epid);
+ if (ecb->dte_size == 0)
+ continue;
+
+ ASSERT3U(ecb->dte_size, >=,
+ sizeof (dtrace_rechdr_t));
+ dtrh = ((void *)(tomax + offs));
+ dtrh->dtrh_epid = ecb->dte_epid;
+ /*
+ * When the speculation is committed, all of
+ * the records in the speculative buffer will
+ * have their timestamps set to the commit
+ * time. Until then, it is set to a sentinel
+ * value, for debugability.
+ */
+ DTRACE_RECORD_STORE_TIMESTAMP(dtrh, UINT64_MAX);
continue;
+ }
case DTRACEACT_CHILL:
if (dtrace_priv_kernel_destructive(state))
@@ -9369,9 +9426,9 @@
/*
* The default size is the size of the default action: recording
- * the epid.
- */
- ecb->dte_size = ecb->dte_needed = sizeof (dtrace_epid_t);
+ * the header.
+ */
+ ecb->dte_size = ecb->dte_needed = sizeof (dtrace_rechdr_t);
ecb->dte_alignment = sizeof (dtrace_epid_t);
epid = state->dts_epid++;
@@ -9470,122 +9527,89 @@
static void
dtrace_ecb_resize(dtrace_ecb_t *ecb)
{
- uint32_t maxalign = sizeof (dtrace_epid_t);
- uint32_t align = sizeof (uint8_t), offs, diff;
dtrace_action_t *act;
- int wastuple = 0;
+ uint32_t curneeded = UINT32_MAX;
uint32_t aggbase = UINT32_MAX;
- dtrace_state_t *state = ecb->dte_state;
-
- /*
- * If we record anything, we always record the epid. (And we always
- * record it first.)
- */
- offs = sizeof (dtrace_epid_t);
- ecb->dte_size = ecb->dte_needed = sizeof (dtrace_epid_t);
+
+ /*
+ * If we record anything, we always record the dtrace_rechdr_t. (And
+ * we always record it first.)
+ */
+ ecb->dte_size = sizeof (dtrace_rechdr_t);
+ ecb->dte_alignment = sizeof (dtrace_epid_t);
for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
dtrace_recdesc_t *rec = &act->dta_rec;
-
- if ((align = rec->dtrd_alignment) > maxalign)
- maxalign = align;
-
- if (!wastuple && act->dta_intuple) {
- /*
- * This is the first record in a tuple. Align the
- * offset to be at offset 4 in an 8-byte aligned
- * block.
- */
- diff = offs + sizeof (dtrace_aggid_t);
-
- if (diff = (diff & (sizeof (uint64_t) - 1)))
- offs += sizeof (uint64_t) - diff;
-
- aggbase = offs - sizeof (dtrace_aggid_t);
- ASSERT(!(aggbase & (sizeof (uint64_t) - 1)));
- }
-
- /*LINTED*/
- if (rec->dtrd_size != 0 && (diff = (offs & (align - 1)))) {
- /*
- * The current offset is not properly aligned; align it.
- */
- offs += align - diff;
- }
-
- rec->dtrd_offset = offs;
-
- if (offs + rec->dtrd_size > ecb->dte_needed) {
- ecb->dte_needed = offs + rec->dtrd_size;
-
- if (ecb->dte_needed > state->dts_needed)
- state->dts_needed = ecb->dte_needed;
- }
+ ASSERT(rec->dtrd_size > 0 || rec->dtrd_alignment == 1);
+
+ ecb->dte_alignment = MAX(ecb->dte_alignment,
+ rec->dtrd_alignment);
if (DTRACEACT_ISAGG(act->dta_kind)) {
dtrace_aggregation_t *agg = (dtrace_aggregation_t *)act;
- dtrace_action_t *first = agg->dtag_first, *prev;
-
- ASSERT(rec->dtrd_size != 0 && first != NULL);
- ASSERT(wastuple);
+
+ ASSERT(rec->dtrd_size != 0);
+ ASSERT(agg->dtag_first != NULL);
+ ASSERT(act->dta_prev->dta_intuple);
ASSERT(aggbase != UINT32_MAX);
+ ASSERT(curneeded != UINT32_MAX);
agg->dtag_base = aggbase;
- while ((prev = first->dta_prev) != NULL &&
- DTRACEACT_ISAGG(prev->dta_kind)) {
- agg = (dtrace_aggregation_t *)prev;
- first = agg->dtag_first;
- }
-
- if (prev != NULL) {
- offs = prev->dta_rec.dtrd_offset +
- prev->dta_rec.dtrd_size;
- } else {
- offs = sizeof (dtrace_epid_t);
- }
- wastuple = 0;
+ curneeded = P2ROUNDUP(curneeded, rec->dtrd_alignment);
+ rec->dtrd_offset = curneeded;
+ curneeded += rec->dtrd_size;
+ ecb->dte_needed = MAX(ecb->dte_needed, curneeded);
+
+ aggbase = UINT32_MAX;
+ curneeded = UINT32_MAX;
+ } else if (act->dta_intuple) {
+ if (curneeded == UINT32_MAX) {
+ /*
+ * This is the first record in a tuple. Align
+ * curneeded to be at offset 4 in an 8-byte
+ * aligned block.
+ */
+ ASSERT(act->dta_prev == NULL ||
+ !act->dta_prev->dta_intuple);
+ ASSERT3U(aggbase, ==, UINT32_MAX);
+ curneeded = P2PHASEUP(ecb->dte_size,
+ sizeof (uint64_t), sizeof (dtrace_aggid_t));
+
+ aggbase = curneeded - sizeof (dtrace_aggid_t);
+ ASSERT(IS_P2ALIGNED(aggbase,
+ sizeof (uint64_t)));
+ }
+ curneeded = P2ROUNDUP(curneeded, rec->dtrd_alignment);
+ rec->dtrd_offset = curneeded;
+ curneeded += rec->dtrd_size;
} else {
- if (!act->dta_intuple)
- ecb->dte_size = offs + rec->dtrd_size;
-
- offs += rec->dtrd_size;
- }
-
- wastuple = act->dta_intuple;
+ /* tuples must be followed by an aggregation */
+ ASSERT(act->dta_prev == NULL ||
+ !act->dta_prev->dta_intuple);
+
+ ecb->dte_size = P2ROUNDUP(ecb->dte_size,
+ rec->dtrd_alignment);
+ rec->dtrd_offset = ecb->dte_size;
+ ecb->dte_size += rec->dtrd_size;
+ ecb->dte_needed = MAX(ecb->dte_needed, ecb->dte_size);
+ }
}
if ((act = ecb->dte_action) != NULL &&
!(act->dta_kind == DTRACEACT_SPECULATE && act->dta_next == NULL) &&
- ecb->dte_size == sizeof (dtrace_epid_t)) {
- /*
- * If the size is still sizeof (dtrace_epid_t), then all
+ ecb->dte_size == sizeof (dtrace_rechdr_t)) {
+ /*
+ * If the size is still sizeof (dtrace_rechdr_t), then all
* actions store no data; set the size to 0.
*/
- ecb->dte_alignment = maxalign;
ecb->dte_size = 0;
-
- /*
- * If the needed space is still sizeof (dtrace_epid_t), then
- * all actions need no additional space; set the needed
- * size to 0.
- */
- if (ecb->dte_needed == sizeof (dtrace_epid_t))
- ecb->dte_needed = 0;
-
- return;
- }
-
- /*
- * Set our alignment, and make sure that the dte_size and dte_needed
- * are aligned to the size of an EPID.
- */
- ecb->dte_alignment = maxalign;
- ecb->dte_size = (ecb->dte_size + (sizeof (dtrace_epid_t) - 1)) &
- ~(sizeof (dtrace_epid_t) - 1);
- ecb->dte_needed = (ecb->dte_needed + (sizeof (dtrace_epid_t) - 1)) &
- ~(sizeof (dtrace_epid_t) - 1);
- ASSERT(ecb->dte_size <= ecb->dte_needed);
+ }
+
+ ecb->dte_size = P2ROUNDUP(ecb->dte_size, sizeof (dtrace_epid_t));
+ ecb->dte_needed = P2ROUNDUP(ecb->dte_needed, (sizeof (dtrace_epid_t)));
+ ecb->dte_state->dts_needed = MAX(ecb->dte_state->dts_needed,
+ ecb->dte_needed);
}
static dtrace_action_t *
@@ -9955,7 +9979,7 @@
break;
case DTRACEACT_SPECULATE:
- if (ecb->dte_size > sizeof (dtrace_epid_t))
+ if (ecb->dte_size > sizeof (dtrace_rechdr_t))
return (EINVAL);
if (dp == NULL)
@@ -10068,7 +10092,7 @@
ecb->dte_action = NULL;
ecb->dte_action_last = NULL;
- ecb->dte_size = sizeof (dtrace_epid_t);
+ ecb->dte_size = 0;
}
static void
@@ -10339,12 +10363,13 @@
caddr_t tomax = buf->dtb_tomax;
caddr_t xamot = buf->dtb_xamot;
dtrace_icookie_t cookie;
- hrtime_t now = dtrace_gethrtime();
+ hrtime_t now;
ASSERT(!(buf->dtb_flags & DTRACEBUF_NOSWITCH));
ASSERT(!(buf->dtb_flags & DTRACEBUF_RING));
cookie = dtrace_interrupt_disable();
+ now = dtrace_gethrtime();
buf->dtb_tomax = xamot;
buf->dtb_xamot = tomax;
buf->dtb_xamot_drops = buf->dtb_drops;
@@ -10639,7 +10664,7 @@
if (epid == DTRACE_EPIDNONE) {
size = sizeof (uint32_t);
} else {
- ASSERT(epid <= state->dts_necbs);
+ ASSERT3U(epid, <=, state->dts_necbs);
ASSERT(state->dts_ecbs[epid - 1] != NULL);
size = state->dts_ecbs[epid - 1]->dte_size;
@@ -15623,6 +15648,7 @@
desc.dtbd_drops = buf->dtb_drops;
desc.dtbd_errors = buf->dtb_errors;
desc.dtbd_oldest = buf->dtb_xamot_offset;
+ desc.dtbd_timestamp = dtrace_gethrtime();
mutex_exit(&dtrace_lock);
@@ -15675,6 +15701,7 @@
desc.dtbd_drops = buf->dtb_xamot_drops;
desc.dtbd_errors = buf->dtb_xamot_errors;
desc.dtbd_oldest = 0;
+ desc.dtbd_timestamp = buf->dtb_switched;
mutex_exit(&dtrace_lock);
--- a/usr/src/uts/common/sys/dtrace.h Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/uts/common/sys/dtrace.h Wed Jul 25 19:05:31 2012 -0400
@@ -26,6 +26,7 @@
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#ifndef _SYS_DTRACE_H
@@ -919,10 +920,10 @@
* DTrace Metadata Description Structures
*
* DTrace separates the trace data stream from the metadata stream. The only
- * metadata tokens placed in the data stream are enabled probe identifiers
- * (EPIDs) or (in the case of aggregations) aggregation identifiers. In order
- * to determine the structure of the data, DTrace consumers pass the token to
- * the kernel, and receive in return a corresponding description of the enabled
+ * metadata tokens placed in the data stream are the dtrace_rechdr_t (EPID +
+ * timestamp) or (in the case of aggregations) aggregation identifiers. To
+ * determine the structure of the data, DTrace consumers pass the token to the
+ * kernel, and receive in return a corresponding description of the enabled
* probe (via the dtrace_eprobedesc structure) or the aggregation (via the
* dtrace_aggdesc structure). Both of these structures are expressed in terms
* of record descriptions (via the dtrace_recdesc structure) that describe the
@@ -1017,7 +1018,8 @@
#define DTRACEOPT_AGGSORTREV 24 /* reverse-sort aggregations */
#define DTRACEOPT_AGGSORTPOS 25 /* agg. position to sort on */
#define DTRACEOPT_AGGSORTKEYPOS 26 /* agg. key position to sort on */
-#define DTRACEOPT_MAX 27 /* number of options */
+#define DTRACEOPT_TEMPORAL 27 /* temporally ordered output */
+#define DTRACEOPT_MAX 28 /* number of options */
#define DTRACEOPT_UNSET (dtrace_optval_t)-2 /* unset option */
@@ -1037,7 +1039,9 @@
* where user-level wishes the kernel to snapshot the buffer to (the
* dtbd_data field). The kernel uses the same structure to pass back some
* information regarding the buffer: the size of data actually copied out, the
- * number of drops, the number of errors, and the offset of the oldest record.
+ * number of drops, the number of errors, the offset of the oldest record,
+ * and the time of the snapshot.
+ *
* If the buffer policy is a "switch" policy, taking a snapshot of the
* principal buffer has the additional effect of switching the active and
* inactive buffers. Taking a snapshot of the aggregation buffer _always_ has
@@ -1050,9 +1054,30 @@
uint64_t dtbd_drops; /* number of drops */
DTRACE_PTR(char, dtbd_data); /* data */
uint64_t dtbd_oldest; /* offset of oldest record */
+ uint64_t dtbd_timestamp; /* hrtime of snapshot */
} dtrace_bufdesc_t;
/*
+ * Each record in the buffer (dtbd_data) begins with a header that includes
+ * the epid and a timestamp. The timestamp is split into two 4-byte parts
+ * so that we do not require 8-byte alignment.
+ */
+typedef struct dtrace_rechdr {
+ dtrace_epid_t dtrh_epid; /* enabled probe id */
+ uint32_t dtrh_timestamp_hi; /* high bits of hrtime_t */
+ uint32_t dtrh_timestamp_lo; /* low bits of hrtime_t */
+} dtrace_rechdr_t;
+
+#define DTRACE_RECORD_LOAD_TIMESTAMP(dtrh) \
+ ((dtrh)->dtrh_timestamp_lo + \
+ ((uint64_t)(dtrh)->dtrh_timestamp_hi << 32))
+
+#define DTRACE_RECORD_STORE_TIMESTAMP(dtrh, hrtime) { \
+ (dtrh)->dtrh_timestamp_lo = (uint32_t)hrtime; \
+ (dtrh)->dtrh_timestamp_hi = hrtime >> 32; \
+}
+
+/*
* DTrace Status
*
* The status of DTrace is relayed via the dtrace_status structure. This
--- a/usr/src/uts/common/sys/dtrace_impl.h Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/uts/common/sys/dtrace_impl.h Wed Jul 25 19:05:31 2012 -0400
@@ -26,6 +26,7 @@
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#ifndef _SYS_DTRACE_IMPL_H
@@ -199,15 +200,18 @@
* predicate is non-NULL, the DIF object is executed. If the result is
* non-zero, the action list is processed, with each action being executed
* accordingly. When the action list has been completely executed, processing
- * advances to the next ECB. processing advances to the next ECB. If the
- * result is non-zero; For each ECB, it first determines the The ECB
- * abstraction allows disjoint consumers to multiplex on single probes.
+ * advances to the next ECB. The ECB abstraction allows disjoint consumers
+ * to multiplex on single probes.
+ *
+ * Execution of the ECB results in consuming dte_size bytes in the buffer
+ * to record data. During execution, dte_needed bytes must be available in
+ * the buffer. This space is used for both recorded data and tuple data.
*/
struct dtrace_ecb {
dtrace_epid_t dte_epid; /* enabled probe ID */
uint32_t dte_alignment; /* required alignment */
- size_t dte_needed; /* bytes needed */
- size_t dte_size; /* total size of payload */
+ size_t dte_needed; /* space needed for execution */
+ size_t dte_size; /* size of recorded payload */
dtrace_predicate_t *dte_predicate; /* predicate, if any */
dtrace_action_t *dte_action; /* actions, if any */
dtrace_ecb_t *dte_next; /* next ECB on probe */
@@ -265,27 +269,30 @@
* the EPID, the consumer can determine the data layout. (The data buffer
* layout is shown schematically below.) By assuring that one can determine
* data layout from the EPID, the metadata stream can be separated from the
- * data stream -- simplifying the data stream enormously.
+ * data stream -- simplifying the data stream enormously. The ECB always
+ * proceeds the recorded data as part of the dtrace_rechdr_t structure that
+ * includes the EPID and a high-resolution timestamp used for output ordering
+ * consistency.
*
- * base of data buffer ---> +------+--------------------+------+
- * | EPID | data | EPID |
- * +------+--------+------+----+------+
- * | data | EPID | data |
- * +---------------+------+-----------+
- * | data, cont. |
- * +------+--------------------+------+
- * | EPID | data | |
- * +------+--------------------+ |
- * | || |
- * | || |
- * | \/ |
- * : :
- * . .
- * . .
- * . .
- * : :
- * | |
- * limit of data buffer ---> +----------------------------------+
+ * base of data buffer ---> +--------+--------------------+--------+
+ * | rechdr | data | rechdr |
+ * +--------+------+--------+----+--------+
+ * | data | rechdr | data |
+ * +---------------+--------+-------------+
+ * | data, cont. |
+ * +--------+--------------------+--------+
+ * | rechdr | data | |
+ * +--------+--------------------+ |
+ * | || |
+ * | || |
+ * | \/ |
+ * : :
+ * . .
+ * . .
+ * . .
+ * : :
+ * | |
+ * limit of data buffer ---> +--------------------------------------+
*
* When evaluating an ECB, dtrace_probe() determines if the ECB's needs of the
* principal buffer (both scratch and payload) exceed the available space. If