On 7/18/12 11:41 AM, [email protected] wrote:
On 7/18/12 10:23 AM, Mark Wielaard wrote:
On Wed, Jul 18, 2012 at 10:10:43AM -0700,[email protected]  wrote:
This work includes investigation to find proper linux machine,
installation of the systemTap, building and testing, and so,
needs some engineering resources.
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.

Also, it needs a new unit test and submitting a CCC request.
You only can help by providing a test for the patch.
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

Normally a dtrace test needs 4 parts:
  java test program, d-script, shell script and README

All automated dtrace tests usually depend on the SQE testbase environment:
   .cfg file, testbase libraries and testbase build system

So that, I do not have a simple standalone test for the HotSpot probes.
But I can provide an example (just make a correction on this kind of dependency).

The test ThreadLifecycle001 includes ThreadLifecycle.d,

Need to complete the sentence above:
The test ThreadLifecycle001 includes ThreadLifecycle.d, ThreadLifecycle001.cfg, ThreadLifecycle001.java, ThreadLifecycle001.pl and ThreadLifecycle001.README


Thanks,
Serguei



Please, see below and let me know if you have any questions.
I can send you more examples if needed.

Thanks,
Serguei


% cat ThreadLifecycle.d

#!/usr/sbin/dtrace -Zs

#pragma D option quiet
#pragma D option destructive

/* %W% %G%
 * Copyright %G% Sun Microsystems, Inc.
 */

/*
* The script trace hotspot:::thread-start and hotspot:::thread-stop events.
 */

self char *str_ptr;
self string thread_name;

:::BEGIN {
    TEST_NAME = "Thread lifecycle";
    TEST_PASS = 1;

    EXIT_CODE_PASS = 0;
    EXIT_CODE_FAIL = 1;

    printf("BEGIN %s probes testing\n\n", TEST_NAME);
}

/*
 * hotspot:::thread-start, hotspot:::thread-stop probe arguments:
 *  arg0: char*,        thread name passed as UTF8 string
 *  arg1: uintptr_t,    thread name length
 *  arg2: uintptr_t,    Java thread id
 *  arg3: uintptr_t,    native/OS thread id
 *  arg4: uintptr_t,    is a daemon or not
 */

/* Check is_daemon is correct */
hotspot$target:::thread-start,
hotspot$target:::thread-stop
/ arg4 > 1 /
{
    TEST_PASS = 0;

    printf("FAIL: wrong is_daemon=%u is passed in %s\n",
        arg4, probename);
}

hotspot$target:::thread-start
{
    THREAD_START_CNT ++;
}

hotspot$target:::thread-stop
{
    THREAD_STOP_CNT ++;
}

hotspot$target:::thread-start,
hotspot$target:::thread-stop
{
/* Yes, we copy for one byte more from user space. This is temporal solution till support for
     * not-null terminated strings will be donein DTRACE
     */
    self->str_ptr = (char*) copyin(arg0, arg1+1);
    self->str_ptr[arg1] = '\0';
    self->thread_name = (string) self->str_ptr;

    printf("\nPROBE ARGS: %s:\n", probename);
    printf("PROBE ARGS:   arg0=%p (thread name pointer)\n", arg0);
    printf("PROBE ARGS:   arg1=%u (thread name length)\n", arg1);
    printf("PROBE ARGS:   arg2=%u (Java thread id)\n", arg2);
    printf("PROBE ARGS:   arg3=%u (native/OS id)\n", arg3);
    printf("PROBE ARGS:   arg4=%u (is daemon)\n", arg4);

    /* this output will be used by Perl script */
    printf("%s: id=%u, is_daemon=%u, name=%s\n",
            probename, arg2, arg4, self->thread_name);
}

/* check exit status of traced java process */
syscall::rexit:entry
/pid == $target && arg0 != 0 && arg0 != 95 /
{
    printf("\n");
    printf("ERROR: java process failed with status=%d\n", arg0);
    TEST_PASS = 0;
}

syscall::rexit:entry
/pid == $target && !THREAD_START_CNT/
{
    printf("ERROR: no 'thread-start' probes were fired\n");
    TEST_PASS = 0;
}

syscall::rexit:entry
/pid == $target && !THREAD_STOP_CNT/
{
    printf("ERROR: no 'thread-stop' probes were fired\n");
    TEST_PASS = 0;
}

syscall::rexit:entry
/pid == $target && !TEST_PASS/
{
    printf("FAIL\n");
    exit(EXIT_CODE_FAIL);
}

syscall::rexit:entry
/pid == $target && TEST_PASS/
{
    printf("PASS\n");
    exit(EXIT_CODE_PASS);
}

:::END {
    printf("\nEND %s tracing\n", TEST_NAME);
}


sspitsyn@hsdev-10 more *.* | cat
::::::::::::::
ThreadLifecycle001.cfg
::::::::::::::
# %W% %G%
# Copyright %G% Sun Microsystems, Inc.


DSCRIPT=${TESTBASE}/src/dtrace/share/dscripts/hotspot/ThreadLifecycle.d

EXECUTE_CLASS=dtrace.hotspot.ThreadLifecycle.ThreadLifecycle001.ThreadLifecycle001

export DSCRIPT
export JAVA
export JAVA_OPTS
export TESTDIR
export TEST_ARGS
export EXECUTE_CLASS
export TESTBASE
export TESTARGS

DTRACE_RESULTS_ANALYZER_SCRIPT=${TESTBASE}/src/dtrace/hotspot/ThreadLifecycle/ThreadLifecycle001/ThreadLifecycle001.pl
export DTRACE_RESULTS_ANALYZER_SCRIPT

TONGA_EXECUTE=$PERL ${TESTBASE}/src/dtrace/share/run_dtrace.pl


::::::::::::::
ThreadLifecycle001.java
::::::::::::::
/* %W% %G%
 * Copyright %G% Sun Microsystems, Inc.
 */

package dtrace.hotspot.ThreadLifecycle.ThreadLifecycle001;

import java.lang.*;

class NewThread extends Thread
{
    volatile private boolean stop = false;
    private boolean started = false;

    public NewThread(ThreadGroup group, String name)
    {
        super(group, name);
    }

    public void run()
    {
        synchronized(this) { started = true; }

        while (!stop)
        {
            for (int i=0; i<100; i++);
        }
    }


    synchronized public boolean isStarted()
    {
        return started;
    }

    public void terminate()
    {
        stop = true;
    }
}


public class ThreadLifecycle001
{
    public static void main(String[] args)
    {
        System.out.println("ThreadLifecycle001 test");

        // create and start NewThread
        ThreadGroup newGroup = new ThreadGroup("newGroup");
        NewThread newThread = new NewThread(newGroup, "NewThread");
        newThread.start();

        ThreadGroup parentGroup = Thread.currentThread().getThreadGroup();
        if (parentGroup == null)
            return;

        while (parentGroup.getParent() != null)
        {
            parentGroup = parentGroup.getParent();
        }

        // wait if newThread is not yet started
        while (!newThread.isStarted())
        {
            for (int i = 0; i < 100; i++);
        }

        System.out.println();
        listThreads(parentGroup);

        newThread.terminate();
        try
        {
            newThread.join();
        }
        catch(InterruptedException ex) {}
    }

    static void listThreads(ThreadGroup currentGroup)
    {
        int threadCount = currentGroup.activeCount();
        Thread listOfThreads[] = new Thread[threadCount];

        currentGroup.enumerate(listOfThreads, true);
        for (int i = 0; i < threadCount; i++)
        {
            System.out.println(
                "Thread: id=" + listOfThreads[i].getId() +
", is_daemon=" + (listOfThreads[i].isDaemon() ? "1" : "0") +
                ", name=" + listOfThreads[i].getName() +
", groupName=" + listOfThreads[i].getThreadGroup().getName() );
        }
    }
}


::::::::::::::
ThreadLifecycle001.pl
::::::::::::::
# %W% %G%
# Copyright %G% Sun Microsystems, Inc.
#
# Implement analyze_dtrace_results_proc function for ThreadLifecycle001 test.
#

sub analyze_dtrace_results_proc($$$)
{
    my ($dtrace_log_filename, $java_log_filename, $args) = @_;

    my $test_fail = 0;
my %java_threads = (); # threads started according to Java log file my %dtrace_start_threads = (); # threads started according to hotspot:::thread-start probes my %dtrace_stop_threads = (); # threads started according to hotspot:::thread-start probes

    if ( &read_java_log($java_log_filename, \%java_threads) ||
&read_dtrace_log($dtrace_log_filename, \%dtrace_start_threads, \%dtrace_stop_threads) )
    {
        return 1;
    }

    # Check that all probes have been fired
    foreach (keys %java_threads)
    {
        unless (exists $dtrace_start_threads{$_}) {
print STDOUT "ERROR: no 'thread-start' probe was fired for thread: $_\n";
            $test_fail = 1;
        }

        unless (exists $dtrace_stop_threads{$_}) {
print STDOUT "ERROR: no 'thread-stop' probe was fired for thread: $_\n";
            $test_fail = 1;
        }
    }

# check that 'thread-start' probes have been fired exactly 1 time for each thread
    foreach (keys %dtrace_start_threads) {
        if ($dtrace_start_threads{$_} > 1) {
            print STDOUT "ERROR: 'thread-start' probe for '$_' fired " .
                $dtrace_start_threads{$_} . " (>1) times\n";
            $test_fail = 1;
        }
    }

# check that 'thread-stop' probes have been fired exactly 1 time for each thread
    foreach (keys %dtrace_stop_threads) {
        if ($dtrace_stop_threads{$_} > 1) {
            print STDOUT "ERROR: 'thread-stop' probe for '$_' fired " .
                $dtrace_stop_threads{$_} . " (>1) times\n";
            $test_fail = 1;
        }
    }

    return $test_fail;
}

sub read_java_log($$)
{
    my ($java_log_filename, $java_threads) = @_;

    unless (open(IN, "<$java_log_filename"))
    {
        print STDOUT "Failed to read $java_log_filename: $!\n";
        return 1;
    }

    while(my $str = <IN>)
    {
        $str =~ s/\r*\n//;

        if ($str =~ s/^Thread: //)
        {
# thread group name is not passed in dtrace probes, so delete it
            $str =~ s/, groupName=.*$//;

            $java_threads->{$str} ++;
        }
    }

    close(IN);
    return 0;
}

sub read_dtrace_log($$$)
{
my ($dtrace_log_filename, $dtrace_start_threads, $dtrace_stop_threads) = @_;

    unless (open(IN, "<$dtrace_log_filename"))
    {
        print STDOUT "Failed to read $java_log_filename: $!\n";
        return 1;
    }

    my $probe_name;
    while(my $str = <IN>)
    {
        $str =~ s/\r*\n//;

        if ($str =~ s/^thread-start: //)
        {
            $dtrace_start_threads->{$str} ++;
        }
        elsif ($str =~ s/^thread-stop: //)
        {
            $dtrace_stop_threads->{$str} ++;
        }
    }

    close(IN);
    return 0;
}

1;

::::::::::::::
ThreadLifecycle001.README
::::::::::::::
%W% %G%
Copyright %G% Sun Microsystems, Inc.

DESCRIPTION

The test exercise hotspot:::thread-start and hotspot:::thread-stop Dtrace probes functionality.

    The test do:
    - run ThreadLifecycle001 java programm which dumps information abould
      all running threads in VM.
    - check if:
- for each Java thread thread-start and thread-stop probes are fired the same time
      - input probe's arguments are passed correctly
        (attempt to print them doesn't cause the error)
      - no any Dtrace errors are thrown

COMMENTS

AUTHOR
 . . .






Reply via email to