<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#CCCCCC" text="#000000">
<div class="moz-cite-prefix">On 7/18/12 11:41 AM,
<a class="moz-txt-link-abbreviated" href="mailto:serguei.spitsyn@oracle.com">serguei.spitsyn@oracle.com</a> wrote:<br>
</div>
<blockquote cite="mid:5007035E.8070602@oracle.com" type="cite">
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
<div class="moz-cite-prefix">On 7/18/12 10:23 AM, Mark Wielaard
wrote:<br>
</div>
<blockquote
cite="mid:20120718172306.GA4153@toonder.wildebeest.org"
type="cite">
<pre wrap="">On Wed, Jul 18, 2012 at 10:10:43AM -0700, <a moz-do-not-send="true" class="moz-txt-link-abbreviated" href="mailto:serguei.spitsyn@oracle.com">serguei.spitsyn@oracle.com</a> wrote:
</pre>
<blockquote type="cite">
<pre wrap="">This work includes investigation to find proper linux machine,
installation of the systemTap, building and testing, and so,
needs some engineering resources.
</pre>
</blockquote>
<pre wrap="">I can do that, the patch has already been included in various
distros so it shouldn't be a problem. Just let me know what you
need.
</pre>
<blockquote type="cite">
<pre wrap="">Also, it needs a new unit test and submitting a CCC request.
You only can help by providing a test for the patch.
</pre>
</blockquote>
<pre wrap="">Sure, I was looking for existing dtrace tests to see if I can
match them. Do you have a good example I can follow?
Thanks,
Mark
</pre>
</blockquote>
<br>
Normally a dtrace test needs 4 parts:<br>
java test program, d-script, shell script and README<br>
<br>
All automated dtrace tests usually depend on the SQE testbase
environment: <br>
.cfg file, testbase libraries and testbase build system<br>
<br>
So that, I do not have a simple standalone test for the HotSpot
probes.<br>
But I can provide an example (just make a correction on this kind
of dependency).<br>
<br>
The test ThreadLifecycle001 includes ThreadLifecycle.d, <br>
</blockquote>
<br>
Need to complete the sentence above:<br>
The test ThreadLifecycle001 includes ThreadLifecycle.d,
ThreadLifecycle001.cfg,<br>
ThreadLifecycle001.java, ThreadLifecycle001.pl and
ThreadLifecycle001.README<br>
<br>
<br>
Thanks,<br>
Serguei<br>
<br>
<blockquote cite="mid:5007035E.8070602@oracle.com" type="cite"> <br>
<br>
Please, see below and let me know if you have any questions.<br>
I can send you more examples if needed.<br>
<br>
Thanks,<br>
Serguei<br>
<br>
<br>
% cat ThreadLifecycle.d<br>
<br>
#!/usr/sbin/dtrace -Zs<br>
<br>
#pragma D option quiet<br>
#pragma D option destructive<br>
<br>
/* %W% %G%<br>
* Copyright %G% Sun Microsystems, Inc.<br>
*/<br>
<br>
/*<br>
* The script trace hotspot:::thread-start and
hotspot:::thread-stop events.<br>
*/<br>
<br>
self char *str_ptr;<br>
self string thread_name;<br>
<br>
:::BEGIN {<br>
TEST_NAME = "Thread lifecycle";<br>
TEST_PASS = 1;<br>
<br>
EXIT_CODE_PASS = 0;<br>
EXIT_CODE_FAIL = 1;<br>
<br>
printf("BEGIN %s probes testing\n\n", TEST_NAME);<br>
}<br>
<br>
/*<br>
* hotspot:::thread-start, hotspot:::thread-stop probe arguments:<br>
* arg0: char*, thread name passed as UTF8 string<br>
* arg1: uintptr_t, thread name length<br>
* arg2: uintptr_t, Java thread id<br>
* arg3: uintptr_t, native/OS thread id<br>
* arg4: uintptr_t, is a daemon or not<br>
*/<br>
<br>
/* Check is_daemon is correct */<br>
hotspot$target:::thread-start,<br>
hotspot$target:::thread-stop<br>
/ arg4 > 1 /<br>
{<br>
TEST_PASS = 0;<br>
<br>
printf("FAIL: wrong is_daemon=%u is passed in %s\n",<br>
arg4, probename);<br>
}<br>
<br>
hotspot$target:::thread-start<br>
{<br>
THREAD_START_CNT ++;<br>
}<br>
<br>
hotspot$target:::thread-stop<br>
{<br>
THREAD_STOP_CNT ++;<br>
}<br>
<br>
hotspot$target:::thread-start,<br>
hotspot$target:::thread-stop<br>
{<br>
/* Yes, we copy for one byte more from user space. This is
temporal solution till support for<br>
* not-null terminated strings will be donein DTRACE<br>
*/<br>
self->str_ptr = (char*) copyin(arg0, arg1+1);<br>
self->str_ptr[arg1] = '\0'; <br>
self->thread_name = (string) self->str_ptr;<br>
<br>
printf("\nPROBE ARGS: %s:\n", probename);<br>
printf("PROBE ARGS: arg0=%p (thread name pointer)\n", arg0);<br>
printf("PROBE ARGS: arg1=%u (thread name length)\n", arg1);<br>
printf("PROBE ARGS: arg2=%u (Java thread id)\n", arg2);<br>
printf("PROBE ARGS: arg3=%u (native/OS id)\n", arg3);<br>
printf("PROBE ARGS: arg4=%u (is daemon)\n", arg4);<br>
<br>
/* this output will be used by Perl script */<br>
printf("%s: id=%u, is_daemon=%u, name=%s\n",<br>
probename, arg2, arg4, self->thread_name);<br>
}<br>
<br>
/* check exit status of traced java process */<br>
syscall::rexit:entry<br>
/pid == $target && arg0 != 0 && arg0 != 95 /<br>
{<br>
printf("\n");<br>
printf("ERROR: java process failed with status=%d\n", arg0);<br>
TEST_PASS = 0;<br>
}<br>
<br>
syscall::rexit:entry<br>
/pid == $target && !THREAD_START_CNT/<br>
{<br>
printf("ERROR: no 'thread-start' probes were fired\n");<br>
TEST_PASS = 0;<br>
}<br>
<br>
syscall::rexit:entry<br>
/pid == $target && !THREAD_STOP_CNT/<br>
{<br>
printf("ERROR: no 'thread-stop' probes were fired\n");<br>
TEST_PASS = 0;<br>
}<br>
<br>
syscall::rexit:entry<br>
/pid == $target && !TEST_PASS/<br>
{<br>
printf("FAIL\n");<br>
exit(EXIT_CODE_FAIL);<br>
}<br>
<br>
syscall::rexit:entry<br>
/pid == $target && TEST_PASS/<br>
{<br>
printf("PASS\n");<br>
exit(EXIT_CODE_PASS);<br>
}<br>
<br>
:::END {<br>
printf("\nEND %s tracing\n", TEST_NAME);<br>
}<br>
<br>
<br>
sspitsyn@hsdev-10 more *.* | cat<br>
::::::::::::::<br>
ThreadLifecycle001.cfg<br>
::::::::::::::<br>
# %W% %G%<br>
# Copyright %G% Sun Microsystems, Inc.<br>
<br>
<br>
DSCRIPT=${TESTBASE}/src/dtrace/share/dscripts/hotspot/ThreadLifecycle.d<br>
<br>
EXECUTE_CLASS=dtrace.hotspot.ThreadLifecycle.ThreadLifecycle001.ThreadLifecycle001<br>
<br>
export DSCRIPT<br>
export JAVA<br>
export JAVA_OPTS<br>
export TESTDIR<br>
export TEST_ARGS<br>
export EXECUTE_CLASS<br>
export TESTBASE<br>
export TESTARGS<br>
<br>
DTRACE_RESULTS_ANALYZER_SCRIPT=${TESTBASE}/src/dtrace/hotspot/ThreadLifecycle/ThreadLifecycle001/ThreadLifecycle001.pl<br>
export DTRACE_RESULTS_ANALYZER_SCRIPT<br>
<br>
TONGA_EXECUTE=$PERL ${TESTBASE}/src/dtrace/share/run_dtrace.pl <br>
<br>
<br>
::::::::::::::<br>
ThreadLifecycle001.java<br>
::::::::::::::<br>
/* %W% %G%<br>
* Copyright %G% Sun Microsystems, Inc.<br>
*/<br>
<br>
package dtrace.hotspot.ThreadLifecycle.ThreadLifecycle001;<br>
<br>
import java.lang.*;<br>
<br>
class NewThread extends Thread<br>
{<br>
volatile private boolean stop = false;<br>
private boolean started = false;<br>
<br>
public NewThread(ThreadGroup group, String name)<br>
{<br>
super(group, name);<br>
}<br>
<br>
public void run()<br>
{<br>
synchronized(this) { started = true; }<br>
<br>
while (!stop)<br>
{<br>
for (int i=0; i<100; i++);<br>
}<br>
}<br>
<br>
<br>
synchronized public boolean isStarted()<br>
{<br>
return started;<br>
}<br>
<br>
public void terminate()<br>
{<br>
stop = true;<br>
}<br>
}<br>
<br>
<br>
public class ThreadLifecycle001<br>
{<br>
public static void main(String[] args)<br>
{<br>
System.out.println("ThreadLifecycle001 test");<br>
<br>
// create and start NewThread<br>
ThreadGroup newGroup = new ThreadGroup("newGroup");<br>
NewThread newThread = new NewThread(newGroup,
"NewThread");<br>
newThread.start();<br>
<br>
ThreadGroup parentGroup =
Thread.currentThread().getThreadGroup();<br>
if (parentGroup == null)<br>
return;<br>
<br>
while (parentGroup.getParent() != null)<br>
{<br>
parentGroup = parentGroup.getParent();<br>
}<br>
<br>
// wait if newThread is not yet started<br>
while (!newThread.isStarted())<br>
{<br>
for (int i = 0; i < 100; i++);<br>
}<br>
<br>
System.out.println();<br>
listThreads(parentGroup);<br>
<br>
newThread.terminate();<br>
try<br>
{<br>
newThread.join();<br>
}<br>
catch(InterruptedException ex) {}<br>
}<br>
<br>
static void listThreads(ThreadGroup currentGroup)<br>
{<br>
int threadCount = currentGroup.activeCount();<br>
Thread listOfThreads[] = new Thread[threadCount];<br>
<br>
currentGroup.enumerate(listOfThreads, true);<br>
for (int i = 0; i < threadCount; i++)<br>
{<br>
System.out.println(<br>
"Thread: id=" + listOfThreads[i].getId() +<br>
", is_daemon=" + (listOfThreads[i].isDaemon() ?
"1" : "0") +<br>
", name=" + listOfThreads[i].getName() +<br>
", groupName=" +
listOfThreads[i].getThreadGroup().getName() );<br>
}<br>
}<br>
}<br>
<br>
<br>
::::::::::::::<br>
ThreadLifecycle001.pl<br>
::::::::::::::<br>
# %W% %G%<br>
# Copyright %G% Sun Microsystems, Inc.<br>
#<br>
# Implement analyze_dtrace_results_proc function for
ThreadLifecycle001 test.<br>
#<br>
<br>
sub analyze_dtrace_results_proc($$$)<br>
{<br>
my ($dtrace_log_filename, $java_log_filename, $args) = @_;<br>
<br>
my $test_fail = 0;<br>
my %java_threads = (); # threads started according to
Java log file<br>
my %dtrace_start_threads = (); # threads started according to
hotspot:::thread-start probes<br>
my %dtrace_stop_threads = (); # threads started according to
hotspot:::thread-start probes<br>
<br>
if ( &read_java_log($java_log_filename, \%java_threads) ||<br>
&read_dtrace_log($dtrace_log_filename,
\%dtrace_start_threads, \%dtrace_stop_threads) )<br>
{<br>
return 1;<br>
}<br>
<br>
# Check that all probes have been fired<br>
foreach (keys %java_threads)<br>
{<br>
unless (exists $dtrace_start_threads{$_}) {<br>
print STDOUT "ERROR: no 'thread-start' probe was fired
for thread: $_\n";<br>
$test_fail = 1;<br>
}<br>
<br>
unless (exists $dtrace_stop_threads{$_}) {<br>
print STDOUT "ERROR: no 'thread-stop' probe was fired
for thread: $_\n";<br>
$test_fail = 1;<br>
}<br>
}<br>
<br>
# check that 'thread-start' probes have been fired exactly 1
time for each thread<br>
foreach (keys %dtrace_start_threads) {<br>
if ($dtrace_start_threads{$_} > 1) {<br>
print STDOUT "ERROR: 'thread-start' probe for '$_'
fired " .<br>
$dtrace_start_threads{$_} . " (>1) times\n";<br>
$test_fail = 1;<br>
}<br>
}<br>
<br>
# check that 'thread-stop' probes have been fired exactly 1
time for each thread<br>
foreach (keys %dtrace_stop_threads) {<br>
if ($dtrace_stop_threads{$_} > 1) {<br>
print STDOUT "ERROR: 'thread-stop' probe for '$_'
fired " .<br>
$dtrace_stop_threads{$_} . " (>1) times\n";<br>
$test_fail = 1;<br>
}<br>
}<br>
<br>
return $test_fail;<br>
}<br>
<br>
sub read_java_log($$)<br>
{<br>
my ($java_log_filename, $java_threads) = @_;<br>
<br>
unless (open(IN, "<$java_log_filename")) <br>
{<br>
print STDOUT "Failed to read $java_log_filename: $!\n";<br>
return 1;<br>
}<br>
<br>
while(my $str = <IN>)<br>
{<br>
$str =~ s/\r*\n//;<br>
<br>
if ($str =~ s/^Thread: //) <br>
{<br>
# thread group name is not passed in dtrace probes, so
delete it<br>
$str =~ s/, groupName=.*$//;<br>
<br>
$java_threads->{$str} ++;<br>
}<br>
}<br>
<br>
close(IN);<br>
return 0;<br>
}<br>
<br>
sub read_dtrace_log($$$)<br>
{<br>
my ($dtrace_log_filename, $dtrace_start_threads,
$dtrace_stop_threads) = @_;<br>
<br>
unless (open(IN, "<$dtrace_log_filename")) <br>
{<br>
print STDOUT "Failed to read $java_log_filename: $!\n";<br>
return 1;<br>
}<br>
<br>
my $probe_name;<br>
while(my $str = <IN>)<br>
{<br>
$str =~ s/\r*\n//;<br>
<br>
if ($str =~ s/^thread-start: //)<br>
{<br>
$dtrace_start_threads->{$str} ++;<br>
}<br>
elsif ($str =~ s/^thread-stop: //)<br>
{<br>
$dtrace_stop_threads->{$str} ++;<br>
}<br>
}<br>
<br>
close(IN);<br>
return 0;<br>
}<br>
<br>
1;<br>
<br>
::::::::::::::<br>
ThreadLifecycle001.README<br>
::::::::::::::<br>
%W% %G%<br>
Copyright %G% Sun Microsystems, Inc.<br>
<br>
DESCRIPTION<br>
<br>
The test exercise hotspot:::thread-start and
hotspot:::thread-stop Dtrace probes functionality.<br>
<br>
The test do:<br>
- run ThreadLifecycle001 java programm which dumps information
abould<br>
all running threads in VM.<br>
- check if:<br>
- for each Java thread thread-start and thread-stop probes
are fired the same time<br>
- input probe's arguments are passed correctly<br>
(attempt to print them doesn't cause the error)<br>
- no any Dtrace errors are thrown<br>
<br>
COMMENTS<br>
<br>
AUTHOR<br>
. . .<br>
<br>
<br>
<br>
<br>
</blockquote>
<br>
<br>
</body>
</html>