DTrace: Revert r249367

The following change from illumos brought caused DTrace to
pause in an interactive environment:

3026 libdtrace should set LD_NOLAZYLOAD=1 to help the pid provider

This was not detected during testing because it doesn't
affect scripts.

We shouldn't be changing the environment, especially since the
LD_NOLAZYLOAD option doesn't apply to our (GNU) ld.
Unfortunately the change from upstream was made in such a way
that it is very difficult to separate this change from the
others so, at least for now, it's better to just revert
everything.

Reference:
https://www.illumos.org/issues/3026

Reported by:	Navdeep Parhar and Mark Johnston
This commit is contained in:
Pedro F. Giffuni 2013-04-17 02:20:17 +00:00
parent 9f08548d20
commit 03836978be
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=249573
62 changed files with 918 additions and 2302 deletions

View File

@ -23,9 +23,8 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
#include <sys/stat.h>
@ -1410,7 +1409,6 @@ main(int argc, char *argv[])
(void) dtrace_setopt(g_dtp, "bufsize", "4m");
(void) dtrace_setopt(g_dtp, "aggsize", "4m");
#endif
(void) dtrace_setopt(g_dtp, "temporal", "yes");
/*
* If -G is specified, enable -xlink=dynamic and -xunodefs to permit

View File

@ -583,8 +583,6 @@ if ($opt_x) {
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';

View File

@ -1,35 +0,0 @@
/*
* 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);
}

View File

@ -1,6 +0,0 @@
1 0 10
2 0 20
3 0 30
4 0 40

View File

@ -1,8 +0,0 @@
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

View File

@ -1,50 +0,0 @@
/*
* 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);
}

View File

@ -1,10 +0,0 @@
fffffffffffffff0 -16 18446744073709551600
fff0 65520 65520
fffffff0 4294967280 4294967280
fff0 65520 65520
fffffffffffffff0 -16 18446744073709551600
fffffffffffffff0 -16 18446744073709551600
fff0 65520 65520
fff0 65520 65520

View File

@ -0,0 +1,57 @@
/*
* 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);
}

View File

@ -1,36 +0,0 @@
/*
* 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);
}

View File

@ -1,52 +0,0 @@
/*
* 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);
}

View File

@ -1,10 +0,0 @@
fffffffffffffff0 -16 18446744073709551600
fff0 65520 65520
fffffff0 4294967280 4294967280
fff0 65520 65520
fffffffffffffff0 -16 18446744073709551600
fffffffffffffff0 -16 18446744073709551600
fff0 65520 65520
fff0 65520 65520

View File

@ -23,29 +23,26 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* 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 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.
* 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.
*/
#pragma D option bufpolicy=fill
#pragma D option bufsize=128
#pragma D option bufsize=64
#pragma D option statusrate=10ms
#pragma D option quiet

View File

@ -23,9 +23,8 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ASSERTION:
@ -38,20 +37,19 @@
*/
/*
* 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.
* 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.
*/
#pragma D option bufpolicy=ring
#pragma D option bufsize=80
#pragma D option bufsize=40
#pragma D option quiet
int n;

View File

@ -1,41 +0,0 @@
/*
* 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);
}

View File

@ -1,44 +0,0 @@
/*
* 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);
}

View File

@ -24,9 +24,7 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
# Copyright (c) 2012 by Delphix. All rights reserved.
# ident "%Z%%M% %I% %E% SMI"
#
if [ $# != 1 ]; then
@ -51,13 +49,13 @@ tick-1s
tick-1s
/(i % 2) == 0/
{
system("dtrace -c date -n 'pid\$target::main:entry' >/dev/null");
system("dtrace -c date -ln 'pid\$target::main:entry' >/dev/null");
}
tick-1s
/(i % 2) == 1/
{
system("dtrace -c date -n 'pid\$target::main:return' >/dev/null");
system("dtrace -c date -ln 'pid\$target::main:return' >/dev/null");
}
EOF

View File

@ -1,28 +0,0 @@
/*
* 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);
}

View File

@ -1,29 +0,0 @@
/*
* 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);
}

View File

@ -1,106 +0,0 @@
#!/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

View File

@ -1,102 +0,0 @@
#!/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

View File

@ -1,48 +0,0 @@
/*
* 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);
}

View File

@ -0,0 +1,197 @@
#
# 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

View File

@ -0,0 +1,29 @@
/*
* 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);
}

View File

@ -1,28 +0,0 @@
/*
* 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);
}

View File

@ -1,42 +0,0 @@
/*
* 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);
}

View File

@ -1,8 +0,0 @@
pancakes_t {
int i = 0x14
string s = [ "I like pancakes" ]
timespec_t t = {
time_t tv_sec = 0
long tv_nsec = 0
}
}

View File

@ -1,6 +1,6 @@
-17
-12817
239
52719
-1867788817
1311768467294899695

View File

@ -1,38 +0,0 @@
/*
* 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);
}

View File

@ -1,3 +0,0 @@
65535 -1 65535
-1 -1 65535

View File

@ -24,10 +24,7 @@
* Use is subject to license terms.
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ASSERTION:
@ -38,10 +35,17 @@
*
* 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=49
#pragma D option bufsize=41
BEGIN
{

View File

@ -24,10 +24,7 @@
* Use is subject to license terms.
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ASSERTION:
* Verify the behavior of speculations with changes in specsize.
@ -38,7 +35,7 @@
*/
#pragma D option quiet
#pragma D option specsize=48
#pragma D option specsize=40
BEGIN
{

View File

@ -1,28 +0,0 @@
/*
* 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);
}

View File

@ -0,0 +1,61 @@
/*
* 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);
}

View File

@ -1,62 +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.
#
#
# 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 $?

View File

@ -1,14 +0,0 @@
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

View File

@ -1,60 +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.
#
#
# 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 $?

View File

@ -1,14 +0,0 @@
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

View File

@ -26,7 +26,6 @@
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <stdlib.h>
@ -895,14 +894,33 @@ dt_aggregate_valcmp(const void *lhs, const void *rhs)
caddr_t rdata = rh->dtahe_data.dtada_data;
dtrace_recdesc_t *lrec, *rrec;
int64_t *laddr, *raddr;
int rval;
int rval, i;
assert(lagg->dtagd_nrecs == ragg->dtagd_nrecs);
if ((rval = dt_aggregate_hashcmp(lhs, rhs)) != 0)
return (rval);
lrec = &lagg->dtagd_rec[lagg->dtagd_nrecs - 1];
rrec = &ragg->dtagd_rec[ragg->dtagd_nrecs - 1];
if (lagg->dtagd_nrecs > ragg->dtagd_nrecs)
return (DT_GREATERTHAN);
assert(lrec->dtrd_action == rrec->dtrd_action);
if (lagg->dtagd_nrecs < ragg->dtagd_nrecs)
return (DT_LESSTHAN);
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);
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);
}
laddr = (int64_t *)(uintptr_t)(ldata + lrec->dtrd_offset);
raddr = (int64_t *)(uintptr_t)(rdata + rrec->dtrd_offset);

View File

@ -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) 2012 by Delphix. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
*/
/*
@ -664,17 +664,15 @@ static void
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, istrace ? D_TRACE_VOID : D_PRINT_VOID,
"%s( ) may not be applied to a void expression\n", act);
dnerror(dnp->dn_args, D_TRACE_VOID,
"trace( ) may not be applied to a void 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);
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 (dnp->dn_args->dn_kind == DT_NODE_AGG) {
@ -684,34 +682,51 @@ dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
}
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.
*/
if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
dt_node_t *dret;
size_t n;
dt_module_t *dmp;
/*
* 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;
dret = yypcb->pcb_dret;
dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
n = snprintf(NULL, 0, "%s`%ld", 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`%ld", dmp->dm_name,
dret->dn_type);
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");
}
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`%ld", 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`%ld", dmp->dm_name,
dret->dn_type);
ap->dtad_difo = dt_as(yypcb);
ap->dtad_kind = DTRACEACT_DIFEXPR;
}
@ -1136,9 +1151,6 @@ dt_compile_fun(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
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;
@ -1175,6 +1187,9 @@ dt_compile_fun(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
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;
@ -2550,8 +2565,7 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg,
}
out:
if (context != DT_CTX_DTYPE && yypcb->pcb_root != NULL &&
DT_TREEDUMP_PASS(dtp, 3))
if (context != DT_CTX_DTYPE && 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 ||

View File

@ -19,15 +19,12 @@
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
#include <sys/sysmacros.h>
@ -196,6 +193,9 @@ dt_cg_ptrsize(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
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,7 +212,6 @@ dt_cg_ptrsize(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
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));
@ -252,7 +251,9 @@ dt_cg_field_get(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
assert(dnp->dn_op == DT_TOK_PTR || dnp->dn_op == DT_TOK_DOT);
r1 = dnp->dn_left->dn_reg;
r2 = dt_regset_alloc(drp);
if ((r2 = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
/*
* On little-endian architectures, ctm_offset counts from the right so
@ -355,9 +356,10 @@ dt_cg_field_set(dt_node_t *src, dt_irlist_t *dlp,
"bits %u\n", m.ctm_offset, m.ctm_type, e.cte_bits);
}
r1 = dt_regset_alloc(drp);
r2 = dt_regset_alloc(drp);
r3 = dt_regset_alloc(drp);
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);
/*
* Compute shifts and masks. We need to compute "shift" as the amount
@ -421,7 +423,8 @@ dt_cg_store(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp, dt_node_t *dst)
size = dt_node_type_size(src);
if (src->dn_flags & DT_NF_REF) {
reg = dt_regset_alloc(drp);
if ((reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
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));
@ -471,58 +474,30 @@ dt_cg_typecast(const dt_node_t *src, const dt_node_t *dst,
size_t dstsize = dt_node_type_size(dst);
dif_instr_t instr;
int rg;
int reg, n;
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)
n = sizeof (uint64_t) * NBBY - dstsize * NBBY;
else
n = sizeof (uint64_t) * NBBY - srcsize * NBBY;
if (dstsize > srcsize) {
int n = sizeof (uint64_t) * NBBY - srcsize * NBBY;
int s = (dstsize - srcsize) * NBBY;
dt_cg_setx(dlp, reg, n);
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 ((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, rg, n);
instr = DIF_INSTR_FMT(DIF_OP_SLL, src->dn_reg, rg, dst->dn_reg);
instr = DIF_INSTR_FMT(DIF_OP_SLL,
src->dn_reg, reg, 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, rg, dst->dn_reg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
}
DIF_OP_SRA : DIF_OP_SRL, dst->dn_reg, reg, dst->dn_reg);
dt_regset_free(drp, rg);
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
dt_regset_free(drp, reg);
}
}
/*
@ -548,7 +523,8 @@ dt_cg_arglist(dt_ident_t *idp, dt_node_t *args,
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;
@ -562,18 +538,17 @@ dt_cg_arglist(dt_ident_t *idp, dt_node_t *args,
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;
if (t.dtdt_size != 0) {
reg = dt_regset_alloc(drp);
dt_cg_setx(dlp, reg, t.dtdt_size);
} else {
reg = DIF_REG_R0;
}
} else {
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));
@ -654,7 +629,9 @@ dt_cg_prearith_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op)
dt_cg_node(dnp->dn_child, dlp, drp);
dnp->dn_reg = dnp->dn_child->dn_reg;
reg = dt_regset_alloc(drp);
if ((reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
dt_cg_setx(dlp, reg, size);
instr = DIF_INSTR_FMT(op, dnp->dn_reg, reg, dnp->dn_reg);
@ -711,7 +688,9 @@ dt_cg_postarith_op(dt_node_t *dnp, dt_irlist_t *dlp,
dt_cg_node(dnp->dn_child, dlp, drp);
dnp->dn_reg = dnp->dn_child->dn_reg;
nreg = dt_regset_alloc(drp);
if ((nreg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
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));
@ -1029,7 +1008,9 @@ dt_cg_asgn_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
* set it to the size of our data structure, and then replace
* it with the result of an allocs of the specified size.
*/
r1 = dt_regset_alloc(drp);
if ((r1 = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
dt_cg_setx(dlp, r1,
ctf_type_size(dxp->dx_dst_ctfp, dxp->dx_dst_base));
@ -1073,7 +1054,8 @@ dt_cg_asgn_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
* and add r1 to it before storing the result.
*/
if (ctm.ctm_offset != 0) {
r2 = dt_regset_alloc(drp);
if ((r2 = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
/*
* Add the member offset rounded down to the
@ -1160,7 +1142,8 @@ dt_cg_assoc_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
dnp->dn_reg = dt_regset_alloc(drp);
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)
op = DIF_OP_LDTAA;
@ -1290,7 +1273,9 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
if ((size = dt_node_type_size(dnp)) == sizeof (uint64_t))
return;
reg = dt_regset_alloc(drp);
if ((reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
assert(size < sizeof (uint64_t));
n = sizeof (uint64_t) * NBBY - size * NBBY;
@ -1387,162 +1372,6 @@ dt_cg_func_typeref(dtrace_hdl_t *dtp, dt_node_t *dnp)
typs->dn_value = ctf_type_size(dtt.dtt_ctfp, dtt.dtt_type);
}
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)
{
@ -1555,6 +1384,7 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
dt_ident_t *idp;
ssize_t stroff;
uint_t op;
int reg;
switch (dnp->dn_op) {
case DT_TOK_COMMA:
@ -1756,16 +1586,7 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
dt_cg_node(dnp->dn_child, dlp, drp);
dnp->dn_reg = dnp->dn_child->dn_reg;
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)) {
if (!(dnp->dn_flags & DT_NF_REF)) {
uint_t ubit = dnp->dn_flags & DT_NF_USERLAND;
/*
@ -1801,7 +1622,10 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
case DT_TOK_SIZEOF: {
size_t size = dt_node_sizeof(dnp->dn_child);
dnp->dn_reg = dt_regset_alloc(drp);
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
assert(size != 0);
dt_cg_setx(dlp, dnp->dn_reg, size);
break;
@ -1826,7 +1650,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
assert(dxp->dx_ident->di_flags & DT_IDFLG_CGREG);
assert(dxp->dx_ident->di_id != 0);
dnp->dn_reg = dt_regset_alloc(drp);
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
if (dxp->dx_arg == -1) {
instr = DIF_INSTR_MOV(
@ -1910,9 +1735,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
}
if (m.ctm_offset != 0) {
int reg;
reg = dt_regset_alloc(drp);
if ((reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
/*
* If the offset is not aligned on a byte boundary, it
@ -1958,7 +1782,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
break;
case DT_TOK_STRING:
dnp->dn_reg = dt_regset_alloc(drp);
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
assert(dnp->dn_kind == DT_NODE_STRING);
stroff = dt_strtab_insert(yypcb->pcb_strtab, dnp->dn_string);
@ -1981,7 +1806,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
*/
if (dnp->dn_kind == DT_NODE_VAR &&
(dnp->dn_ident->di_flags & DT_IDFLG_CGREG)) {
dnp->dn_reg = dt_regset_alloc(drp);
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
instr = DIF_INSTR_MOV(dnp->dn_ident->di_id,
dnp->dn_reg);
dt_irlist_append(dlp,
@ -2022,9 +1848,11 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
dnp->dn_reg = dt_regset_alloc(drp);
instr = DIF_INSTR_CALL(dnp->dn_ident->di_id,
dnp->dn_reg);
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);
dt_irlist_append(dlp,
dt_cg_node_alloc(DT_LBL_NONE, instr));
@ -2052,7 +1880,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
break;
}
dnp->dn_reg = dt_regset_alloc(drp);
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
if (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL)
op = DIF_OP_LDLS;
@ -2082,7 +1911,9 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
dtrace_errmsg(dtp, dtrace_errno(dtp)));
}
dnp->dn_reg = dt_regset_alloc(drp);
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
dt_cg_xsetx(dlp, dnp->dn_ident,
DT_LBL_NONE, dnp->dn_reg, sym.st_value);
@ -2102,7 +1933,9 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
break;
case DT_TOK_INT:
dnp->dn_reg = dt_regset_alloc(drp);
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
dt_cg_setx(dlp, dnp->dn_reg, dnp->dn_value);
break;
@ -2117,7 +1950,6 @@ dt_cg(dt_pcb_t *pcb, dt_node_t *dnp)
{
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)
@ -2144,9 +1976,9 @@ dt_cg(dt_pcb_t *pcb, dt_node_t *dnp)
assert(pcb->pcb_dret == NULL);
pcb->pcb_dret = dnp;
if (dt_node_resolve(dnp, DT_IDENT_XLPTR) != NULL) {
if (dt_node_is_dynamic(dnp)) {
dnerror(dnp, D_CG_DYN, "expression cannot evaluate to result "
"of a translated pointer\n");
"of dynamic type\n");
}
/*
@ -2162,14 +1994,6 @@ dt_cg(dt_pcb_t *pcb, dt_node_t *dnp)
}
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));
@ -2179,7 +2003,4 @@ dt_cg(dt_pcb_t *pcb, dt_node_t *dnp)
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);
}

View File

@ -25,7 +25,7 @@
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
*/
#include <stdlib.h>
@ -39,7 +39,6 @@
#include <alloca.h>
#endif
#include <dt_impl.h>
#include <dt_pq.h>
#if !defined(sun)
#include <libproc_compat.h>
#endif
@ -444,8 +443,17 @@ dt_flowindent(dtrace_hdl_t *dtp, dtrace_probedata_t *data, dtrace_epid_t last,
offs += epd->dtepd_size;
do {
if (offs >= buf->dtbd_size)
goto out;
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;
}
}
next = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs);
@ -2006,27 +2014,26 @@ dt_setopt(dtrace_hdl_t *dtp, const dtrace_probedata_t *data,
}
static int
dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
dtrace_bufdesc_t *buf, boolean_t just_one,
dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, dtrace_bufdesc_t *buf,
dtrace_consume_probe_f *efunc, dtrace_consume_rec_f *rfunc, void *arg)
{
dtrace_epid_t id;
size_t offs;
size_t offs, start = buf->dtbd_oldest, end = buf->dtbd_size;
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;
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; ) {
again:
for (offs = start; offs < end; ) {
dtrace_eprobedesc_t *epd;
/*
@ -2061,8 +2068,7 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
}
if (flow)
(void) dt_flowindent(dtp, &data, dtp->dt_last_epid,
buf, offs);
(void) dt_flowindent(dtp, &data, last, buf, offs);
rval = (*efunc)(&data, arg);
@ -2081,7 +2087,6 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
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;
@ -2453,16 +2458,14 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
rval = (*rfunc)(&data, NULL, arg);
nextepid:
offs += epd->dtepd_size;
dtp->dt_last_epid = id;
if (just_one) {
buf->dtbd_oldest = offs;
break;
}
last = id;
}
dtp->dt_flow = data.dtpda_flow;
dtp->dt_indent = data.dtpda_indent;
dtp->dt_prefix = data.dtpda_prefix;
if (buf->dtbd_oldest != 0 && start == buf->dtbd_oldest) {
end = buf->dtbd_oldest;
start = 0;
goto again;
}
if ((drops = buf->dtbd_drops) == 0)
return (0);
@ -2475,130 +2478,6 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
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 defined(sun)
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
#else
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
#endif
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;
@ -2611,7 +2490,7 @@ typedef struct dt_begin {
static int
dt_consume_begin_probe(const dtrace_probedata_t *data, void *arg)
{
dt_begin_t *begin = arg;
dt_begin_t *begin = (dt_begin_t *)arg;
dtrace_probedesc_t *pd = data->dtpda_pdesc;
int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0);
@ -2636,7 +2515,7 @@ static int
dt_consume_begin_record(const dtrace_probedata_t *data,
const dtrace_recdesc_t *rec, void *arg)
{
dt_begin_t *begin = arg;
dt_begin_t *begin = (dt_begin_t *)arg;
return (begin->dtbgn_recfunc(data, rec, begin->dtbgn_arg));
}
@ -2662,7 +2541,7 @@ dt_consume_begin_error(const dtrace_errdata_t *data, void *arg)
}
static int
dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp, dtrace_bufdesc_t *buf,
dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
{
/*
@ -2686,19 +2565,33 @@ dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
* 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;
#if !defined(sun)
dtrace_bufdesc_t *pbuf;
#endif
int rval, i;
static int max_ncpus;
dtrace_bufdesc_t *buf;
dtrace_optval_t size;
dtp->dt_beganon = -1;
if (dt_get_buf(dtp, cpu, &buf) != 0)
return (-1);
if (buf == NULL)
return (0);
#if defined(sun)
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
#else
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
#endif
/*
* 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 (!dtp->dt_stopped || buf->dtbd_cpu != dtp->dt_endedon) {
/*
@ -2706,10 +2599,7 @@ dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
* we are, we actually processed any END probes on another
* CPU. We can simply consume this buffer and return.
*/
rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
pf, rf, arg);
dt_put_buf(dtp, buf);
return (rval);
return (dt_consume_cpu(dtp, fp, cpu, buf, pf, rf, arg));
}
begin.dtbgn_probefunc = pf;
@ -2726,41 +2616,61 @@ dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
dtp->dt_errhdlr = dt_consume_begin_error;
dtp->dt_errarg = &begin;
rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
dt_consume_begin_probe, dt_consume_begin_record, &begin);
rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe,
dt_consume_begin_record, &begin);
dtp->dt_errhdlr = begin.dtbgn_errhdlr;
dtp->dt_errarg = begin.dtbgn_errarg;
if (rval != 0) {
dt_put_buf(dtp, buf);
if (rval != 0)
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++) {
dtrace_bufdesc_t *nbuf;
nbuf.dtbd_cpu = i;
if (i == cpu)
continue;
if (dt_get_buf(dtp, i, &nbuf) != 0) {
dt_put_buf(dtp, buf);
return (-1);
}
if (nbuf == NULL)
continue;
#if defined(sun)
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &nbuf) == -1) {
#else
pbuf = &nbuf;
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &pbuf) == -1) {
#endif
/*
* 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;
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);
free(nbuf.dtbd_data);
return (dt_set_errno(dtp, errno));
}
if ((rval = dt_consume_cpu(dtp, fp,
i, &nbuf, pf, rf, arg)) != 0) {
free(nbuf.dtbd_data);
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
@ -2775,8 +2685,8 @@ dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
dtp->dt_errhdlr = dt_consume_begin_error;
dtp->dt_errarg = &begin;
rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
dt_consume_begin_probe, dt_consume_begin_record, &begin);
rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe,
dt_consume_begin_record, &begin);
dtp->dt_errhdlr = begin.dtbgn_errhdlr;
dtp->dt_errarg = begin.dtbgn_errarg;
@ -2784,32 +2694,11 @@ dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
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 =
/* LINTED - alignment */
(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;
@ -2837,158 +2726,79 @@ dtrace_consume(dtrace_hdl_t *dtp, FILE *fp,
if (rf == NULL)
rf = (dtrace_consume_rec_f *)dt_nullrec;
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. */
if (buf->dtbd_data == NULL) {
(void) dtrace_getopt(dtp, "bufsize", &size);
for (i = 0; i < max_ncpus; i++) {
dtrace_bufdesc_t *buf;
if ((buf->dtbd_data = malloc(size)) == NULL)
return (dt_set_errno(dtp, EDT_NOMEM));
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);
/* XXX: 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);
}
}
/*
* Reduce memory usage by re-allocating smaller buffers
* for the "remnants".
*/
while (buf = dt_pq_walk(dtp->dt_bufq, &cookie))
dt_realloc_buf(dtp, buf, buf->dtbd_size);
buf->dtbd_size = size;
}
return (0);
/*
* 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;
/*
* 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 defined(sun)
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
#else
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
#endif
/*
* 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);
}
if (!dtp->dt_stopped)
return (0);
buf->dtbd_cpu = dtp->dt_endedon;
#if defined(sun)
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
#else
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
#endif
/*
* 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));
}

View File

@ -19,15 +19,12 @@
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <strings.h>
#include <stdio.h>
@ -215,22 +212,12 @@ dt_dis_pushts(const dtrace_difo_t *dp,
{
static const char *const tnames[] = { "D type", "string" };
uint_t type = DIF_INSTR_TYPE(in);
const char *pad;
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";
}
(void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u, %%r%u",
name, type, DIF_INSTR_R2(in), DIF_INSTR_RS(in));
if (type < sizeof (tnames) / sizeof (tnames[0])) {
(void) fprintf(fp, "%s! DT_TYPE(%u) = %s", pad,
type, tnames[type]);
}
if (type < sizeof (tnames) / sizeof (tnames[0]))
(void) fprintf(fp, "\t! DT_TYPE(%u) = %s", type, tnames[type]);
}
static void

View File

@ -18,16 +18,11 @@
*
* 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 <string.h>
#include <strings.h>
#include <dt_impl.h>
@ -42,6 +37,7 @@ static const struct {
{ 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" },

View File

@ -26,7 +26,7 @@
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
*/
#ifndef _DT_ERRTAGS_H
@ -262,7 +262,6 @@ typedef enum {
D_LLQUANT_FACTOREVEN, /* llquantize() bad # steps/factor */
D_LLQUANT_FACTORSMALL, /* llquantize() magnitude too small */
D_LLQUANT_MAGTOOBIG, /* llquantize() high mag too large */
D_NOREG, /* no available internal registers */
D_PRINTM_ADDR, /* printm() memref bad type */
D_PRINTM_SIZE, /* printm() size bad type */
D_PRINTT_ADDR, /* printt() typeref bad type */

View File

@ -26,7 +26,7 @@
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
*/
#ifndef _DT_IMPL_H
@ -64,7 +64,6 @@ extern "C" {
#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> */
@ -240,7 +239,6 @@ struct dtrace_hdl {
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 */
@ -259,7 +257,7 @@ struct dtrace_hdl {
int dt_maxstrdata; /* max strdata ID */
char **dt_strdata; /* pointer to strdata array */
dt_aggregate_t dt_aggregate; /* aggregate */
dt_pq_t *dt_bufq; /* CPU-specific data queue */
dtrace_bufdesc_t dt_buf; /* staging buffer */
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 */
@ -328,11 +326,6 @@ struct dtrace_hdl {
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 */
};
/*
@ -468,6 +461,7 @@ enum {
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 */

View File

@ -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) 2012 by Delphix. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
*/
#include <sys/types.h>
@ -92,7 +92,7 @@
/*
* The version number should be increased for every customer visible release
* of DTrace. The major number should be incremented when a fundamental
* of Solaris. 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
@ -121,9 +121,8 @@
#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_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"
#define DT_VERS_LATEST DT_VERS_1_9
#define DT_VERS_STRING "Sun D 1.9"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@ -144,7 +143,6 @@ const dt_version_t _dtrace_versions[] = {
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
};
@ -1153,7 +1151,7 @@ dt_vopen(int version, int flags, int *errp,
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_init(dtp);
dt_proc_hash_create(dtp);
dtp->dt_vmax = DT_VERS_LATEST;
dtp->dt_cpp_path = strdup(_dtrace_defcpp);
dtp->dt_cpp_argv = malloc(sizeof (char *));
@ -1167,9 +1165,8 @@ dt_vopen(int version, int flags, int *errp,
(void) uname(&dtp->dt_uts);
if (dtp->dt_mods == NULL || dtp->dt_provs == 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)
dtp->dt_procs == 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++)
@ -1581,7 +1578,7 @@ dtrace_close(dtrace_hdl_t *dtp)
int i;
if (dtp->dt_procs != NULL)
dt_proc_fini(dtp);
dt_proc_hash_destroy(dtp);
while ((pgp = dt_list_next(&dtp->dt_programs)) != NULL)
dt_program_destroy(dtp, pgp);
@ -1633,6 +1630,7 @@ dtrace_close(dtrace_hdl_t *dtp)
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);

View File

@ -26,10 +26,6 @@
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <sys/resource.h>
#include <sys/mman.h>
#include <sys/types.h>
@ -372,61 +368,6 @@ dt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
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)
@ -470,6 +411,7 @@ dt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
return (0);
}
/*ARGSUSED*/
static int
dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
@ -970,7 +912,6 @@ static const dt_option_t _dtrace_ctoptions[] = {
{ "pgmax", dt_opt_pgmax },
{ "preallocate", dt_opt_preallocate },
{ "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 },
@ -979,7 +920,6 @@ static const dt_option_t _dtrace_ctoptions[] = {
{ "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 },
@ -1007,7 +947,6 @@ static const dt_option_t _dtrace_rtoptions[] = {
{ "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, NULL, 0 }
};

View File

@ -23,7 +23,6 @@
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2011, Joyent Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@ -97,7 +96,6 @@
*/
#include <sys/param.h>
#include <sys/sysmacros.h>
#include <limits.h>
#include <setjmp.h>
#include <strings.h>
@ -1864,38 +1862,6 @@ dt_node_op1(int op, dt_node_t *cp)
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)
{
@ -2045,9 +2011,32 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
}
}
/*
* 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)) {
dt_cast(lp, rp);
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_node_type_propagate(lp, rp);
dt_node_attr_assign(rp, dt_attr_min(lp->dn_attr, rp->dn_attr));
dt_node_free(lp);
@ -2906,14 +2895,14 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
case DT_TOK_DEREF:
/*
* If the deref operator is applied to a translated pointer,
* we set our output type to the output of the translation.
* we can just set our output type to the base 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,
dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
break;
}
@ -3089,31 +3078,6 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
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)
{
@ -3592,7 +3556,19 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
}
}
asgn_common:
dt_assign_common(dnp);
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));
break;
case DT_TOK_PTR:
@ -3897,14 +3873,6 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
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;
}

View File

@ -1,161 +0,0 @@
/*
* 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;
#if !defined(sun)
if (p->dtpq_last >= p->dtpq_size)
return;
#endif
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);
}

View File

@ -1,51 +0,0 @@
/*
* 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 */

View File

@ -22,7 +22,6 @@
/*
* 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.
*/
#if defined(sun)
@ -162,7 +161,7 @@ static int
pfcheck_dint(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp)
{
if (dnp->dn_flags & DT_NF_SIGNED)
pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'i';
pfd->pfd_flags |= DT_PFCONV_SIGNED;
else
pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'u';
@ -665,7 +664,7 @@ static const dt_pfconv_t _dtrace_conversions[] = {
{ "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_xint, pfprint_sint },
{ "i", "i", pfproto_xint, pfcheck_dint, pfprint_dint },
{ "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 */

View File

@ -24,10 +24,6 @@
* Use is subject to license terms.
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
* DTrace Process Control
*
@ -507,7 +503,7 @@ dt_proc_control(void *arg)
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 = dtp->dt_procs;
dt_proc_hash_t *dph = dpr->dpr_hdl->dt_procs;
struct ps_prochandle *P = dpr->dpr_proc;
int pid = dpr->dpr_pid;
@ -968,8 +964,7 @@ dt_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv,
(void) pthread_cond_init(&dpr->dpr_cv, NULL);
#if defined(sun)
dpr->dpr_proc = Pxcreate(file, argv, dtp->dt_proc_env, &err, NULL, 0);
if (dpr->dpr_proc == NULL) {
if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0)) == NULL) {
#else
if ((err = proc_create(file, argv, pcf, child_arg,
&dpr->dpr_proc)) != 0) {
@ -1145,75 +1140,30 @@ dt_proc_unlock(dtrace_hdl_t *dtp, struct ps_prochandle *P)
}
void
dt_proc_init(dtrace_hdl_t *dtp)
dt_proc_hash_create(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)
return;
sizeof (dt_proc_t *) * _dtrace_pidbuckets - 1)) != NULL) {
(void) pthread_mutex_init(&dtp->dt_procs->dph_lock, NULL);
(void) pthread_cond_init(&dtp->dt_procs->dph_cv, NULL);
(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;
/*
* 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;
for (i = 0, p = environ; *p != NULL; i++, p++) {
if ((dtp->dt_proc_env[i] = strdup(*p)) == NULL)
goto err;
dtp->dt_procs->dph_hashlen = _dtrace_pidbuckets;
dtp->dt_procs->dph_lrulim = _dtrace_pidlrulim;
}
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_fini(dtrace_hdl_t *dtp)
dt_proc_hash_destroy(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 *

View File

@ -24,13 +24,11 @@
* 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>
@ -108,8 +106,8 @@ extern void dt_proc_lock(dtrace_hdl_t *, struct ps_prochandle *);
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_init(dtrace_hdl_t *);
extern void dt_proc_fini(dtrace_hdl_t *);
extern void dt_proc_hash_create(dtrace_hdl_t *);
extern void dt_proc_hash_destroy(dtrace_hdl_t *);
#ifdef __cplusplus
}

View File

@ -19,15 +19,12 @@
*
* 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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
#include <sys/bitmap.h>
@ -36,19 +33,18 @@
#include <stdlib.h>
#include <dt_regset.h>
#include <dt_impl.h>
dt_regset_t *
dt_regset_create(ulong_t nregs)
dt_regset_create(ulong_t size)
{
ulong_t n = BT_BITOUL(nregs);
ulong_t n = BT_BITOUL(size + 1); /* + 1 for %r0 */
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 = nregs;
drp->dr_size = size + 1;
if (drp->dr_bitmap == NULL) {
dt_regset_destroy(drp);
@ -72,25 +68,6 @@ dt_regset_reset(dt_regset_t *drp)
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)
{
@ -118,15 +95,13 @@ dt_regset_alloc(dt_regset_t *drp)
}
}
xyerror(D_NOREG, "Insufficient registers to generate code");
/*NOTREACHED*/
return (-1);
return (-1); /* no available registers */
}
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);
}

View File

@ -19,19 +19,16 @@
*
* 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
@ -48,7 +45,6 @@ extern void dt_regset_destroy(dt_regset_t *);
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
}

View File

@ -21,7 +21,6 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Use is subject to license terms.
*/
@ -618,8 +617,8 @@ dt_printf(dtrace_hdl_t *dtp, FILE *fp, const char *format, ...)
size_t avail;
/*
* Using buffered output is not allowed if a handler has
* not been installed.
* It's not legal to use buffered ouput if there is not a
* handler for buffered output.
*/
if (dtp->dt_bufhdlr == NULL) {
va_end(ap);

View File

@ -24,10 +24,6 @@
* Use is subject to license terms.
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
@ -529,8 +525,7 @@ dt_instr_size(uchar_t *instr, dtrace_hdl_t *dtp, pid_t pid, uintptr_t addr,
* another debugger attached to this process. The original instruction
* can't be recovered so this must fail.
*/
if (x86dis.d86_len == 1 &&
(uchar_t)x86dis.d86_bytes[0] == FASTTRAP_INSTR)
if (x86dis.d86_len == 1 && instr[0] == FASTTRAP_INSTR)
return (-1);
return (x86dis.d86_len);

View File

@ -31,7 +31,6 @@ SRCS= dt_aggregate.c \
dt_parser.c \
dt_pcb.c \
dt_pid.c \
dt_pq.c \
dt_pragma.c \
dt_print.c \
dt_printf.c \

View File

@ -23,7 +23,6 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved
* Use is subject to license terms.
*/
@ -2346,10 +2345,9 @@ dtrace_speculation_commit(dtrace_state_t *state, processorid_t cpu,
{
dtrace_speculation_t *spec;
dtrace_buffer_t *src, *dest;
uintptr_t daddr, saddr, dlimit, slimit;
uintptr_t daddr, saddr, dlimit;
dtrace_speculation_state_t current, new = 0;
intptr_t offs;
uint64_t timestamp;
if (which == 0)
return;
@ -2425,37 +2423,7 @@ dtrace_speculation_commit(dtrace_state_t *state, processorid_t cpu,
}
/*
* 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
* We have the space; 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.)
@ -6238,7 +6206,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
if (now - state->dts_alive > dtrace_deadman_timeout) {
/*
* We seem to be dead. Unless we (a) have kernel
* destructive permissions (b) have explicitly enabled
* destructive permissions (b) have expicitly 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
@ -6266,18 +6234,8 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
tomax = buf->dtb_tomax;
ASSERT(tomax != NULL);
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;
}
if (ecb->dte_size != 0)
DTRACE_STORE(uint32_t, tomax, offs, ecb->dte_epid);
mstate.dtms_epid = ecb->dte_epid;
mstate.dtms_present |= DTRACE_MSTATE_EPID;
@ -6424,9 +6382,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
continue;
switch (act->dta_kind) {
case DTRACEACT_SPECULATE: {
dtrace_rechdr_t *dtrh;
case DTRACEACT_SPECULATE:
ASSERT(buf == &state->dts_buffer[cpuid]);
buf = dtrace_speculation_buffer(state,
cpuid, val);
@ -6448,23 +6404,10 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
tomax = buf->dtb_tomax;
ASSERT(tomax != NULL);
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);
if (ecb->dte_size != 0)
DTRACE_STORE(uint32_t, tomax, offs,
ecb->dte_epid);
continue;
}
case DTRACEACT_PRINTM: {
/* The DIF returns a 'memref'. */
@ -9811,9 +9754,9 @@ dtrace_ecb_add(dtrace_state_t *state, dtrace_probe_t *probe)
/*
* The default size is the size of the default action: recording
* the header.
* the epid.
*/
ecb->dte_size = ecb->dte_needed = sizeof (dtrace_rechdr_t);
ecb->dte_size = ecb->dte_needed = sizeof (dtrace_epid_t);
ecb->dte_alignment = sizeof (dtrace_epid_t);
epid = state->dts_epid++;
@ -9911,89 +9854,122 @@ dtrace_ecb_enable(dtrace_ecb_t *ecb)
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;
uint32_t curneeded = UINT32_MAX;
int wastuple = 0;
uint32_t aggbase = UINT32_MAX;
dtrace_state_t *state = ecb->dte_state;
/*
* If we record anything, we always record the dtrace_rechdr_t. (And
* we always record it first.)
* If we record anything, we always record the epid. (And we always
* record it first.)
*/
ecb->dte_size = sizeof (dtrace_rechdr_t);
ecb->dte_alignment = sizeof (dtrace_epid_t);
offs = sizeof (dtrace_epid_t);
ecb->dte_size = ecb->dte_needed = sizeof (dtrace_epid_t);
for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
dtrace_recdesc_t *rec = &act->dta_rec;
ASSERT(rec->dtrd_size > 0 || rec->dtrd_alignment == 1);
ecb->dte_alignment = MAX(ecb->dte_alignment,
rec->dtrd_alignment);
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;
}
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);
ASSERT(agg->dtag_first != NULL);
ASSERT(act->dta_prev->dta_intuple);
ASSERT(rec->dtrd_size != 0 && first != NULL);
ASSERT(wastuple);
ASSERT(aggbase != UINT32_MAX);
ASSERT(curneeded != UINT32_MAX);
agg->dtag_base = aggbase;
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)));
while ((prev = first->dta_prev) != NULL &&
DTRACEACT_ISAGG(prev->dta_kind)) {
agg = (dtrace_aggregation_t *)prev;
first = agg->dtag_first;
}
curneeded = P2ROUNDUP(curneeded, rec->dtrd_alignment);
rec->dtrd_offset = curneeded;
curneeded += rec->dtrd_size;
} else {
/* 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 (prev != NULL) {
offs = prev->dta_rec.dtrd_offset +
prev->dta_rec.dtrd_size;
} else {
offs = sizeof (dtrace_epid_t);
}
wastuple = 0;
} else {
if (!act->dta_intuple)
ecb->dte_size = offs + rec->dtrd_size;
offs += rec->dtrd_size;
}
wastuple = act->dta_intuple;
}
if ((act = ecb->dte_action) != NULL &&
!(act->dta_kind == DTRACEACT_SPECULATE && act->dta_next == NULL) &&
ecb->dte_size == sizeof (dtrace_rechdr_t)) {
ecb->dte_size == sizeof (dtrace_epid_t)) {
/*
* If the size is still sizeof (dtrace_rechdr_t), then all
* If the size is still sizeof (dtrace_epid_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;
}
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);
/*
* 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);
}
static dtrace_action_t *
@ -10373,7 +10349,7 @@ dtrace_ecb_action_add(dtrace_ecb_t *ecb, dtrace_actdesc_t *desc)
break;
case DTRACEACT_SPECULATE:
if (ecb->dte_size > sizeof (dtrace_rechdr_t))
if (ecb->dte_size > sizeof (dtrace_epid_t))
return (EINVAL);
if (dp == NULL)
@ -10494,7 +10470,7 @@ dtrace_ecb_action_remove(dtrace_ecb_t *ecb)
ecb->dte_action = NULL;
ecb->dte_action_last = NULL;
ecb->dte_size = 0;
ecb->dte_size = sizeof (dtrace_epid_t);
}
static void
@ -10763,13 +10739,12 @@ dtrace_buffer_switch(dtrace_buffer_t *buf)
caddr_t tomax = buf->dtb_tomax;
caddr_t xamot = buf->dtb_xamot;
dtrace_icookie_t cookie;
hrtime_t now;
hrtime_t now = dtrace_gethrtime();
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;
@ -11135,7 +11110,7 @@ dtrace_buffer_reserve(dtrace_buffer_t *buf, size_t needed, size_t align,
if (epid == DTRACE_EPIDNONE) {
size = sizeof (uint32_t);
} else {
ASSERT3U(epid, <=, state->dts_necbs);
ASSERT(epid <= state->dts_necbs);
ASSERT(state->dts_ecbs[epid - 1] != NULL);
size = state->dts_ecbs[epid - 1]->dte_size;
@ -16412,7 +16387,6 @@ dtrace_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv)
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);

View File

@ -26,7 +26,6 @@
/*
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#ifndef _SYS_DTRACE_H
@ -931,10 +930,10 @@ typedef struct dtrace_ecbdesc {
* DTrace Metadata Description Structures
*
* DTrace separates the trace data stream from the metadata stream. The only
* 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
* 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
* 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
@ -1029,8 +1028,7 @@ typedef struct dtrace_fmtdesc {
#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_TEMPORAL 27 /* temporally ordered output */
#define DTRACEOPT_MAX 28 /* number of options */
#define DTRACEOPT_MAX 27 /* number of options */
#define DTRACEOPT_UNSET (dtrace_optval_t)-2 /* unset option */
@ -1050,9 +1048,7 @@ typedef struct dtrace_fmtdesc {
* 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, the offset of the oldest record,
* and the time of the snapshot.
*
* number of drops, the number of errors, and the offset of the oldest record.
* 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
@ -1065,29 +1061,8 @@ typedef struct dtrace_bufdesc {
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
*

View File

@ -23,7 +23,6 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Use is subject to license terms.
*/
@ -210,18 +209,15 @@ typedef struct dtrace_hash {
* 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. 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.
* 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.
*/
struct dtrace_ecb {
dtrace_epid_t dte_epid; /* enabled probe ID */
uint32_t dte_alignment; /* required alignment */
size_t dte_needed; /* space needed for execution */
size_t dte_size; /* size of recorded payload */
size_t dte_needed; /* bytes needed */
size_t dte_size; /* total size of 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 */
@ -279,30 +275,27 @@ typedef struct dtrace_aggregation {
* 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. 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.
* data stream -- simplifying the data stream enormously.
*
* base of data buffer ---> +--------+--------------------+--------+
* | rechdr | data | rechdr |
* +--------+------+--------+----+--------+
* | data | rechdr | data |
* +---------------+--------+-------------+
* | data, cont. |
* +--------+--------------------+--------+
* | rechdr | data | |
* +--------+--------------------+ |
* | || |
* | || |
* | \/ |
* : :
* . .
* . .
* . .
* : :
* | |
* limit of data buffer ---> +--------------------------------------+
* base of data buffer ---> +------+--------------------+------+
* | EPID | data | EPID |
* +------+--------+------+----+------+
* | data | EPID | data |
* +---------------+------+-----------+
* | data, cont. |
* +------+--------------------+------+
* | EPID | 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