commit 20c42c844382d3f5ec2eb5e82a67d119fbc3e84c
parent b646474ac3b1a658a91df3bfcf8f4ee6f5fac747
Author: Kyle Milz <kyle@getaddrinfo.net>
Date: Tue, 15 Mar 2016 18:34:08 -0600
runtime: add get metadata message type
- add message type for requesting metadata
- we don't really need to send sizes and filenames every time we request the
execution counters anyways
Diffstat:
4 files changed, 72 insertions(+), 55 deletions(-)
diff --git a/SCV/Viewer.pm b/SCV/Viewer.pm
@@ -27,21 +27,17 @@ sub accept {
$self->{client_socket} = $socket->accept();
}
-sub request_data {
+sub get_metadata {
my ($self) = @_;
my $client = $self->{client_socket};
$client->syswrite("\x00", 1);
- # First thing sent back is total message size and then the total number
- # of translation units.
- my $buf = read_all($client, 8);
- my $msg_size = unpack("Q", $buf);
-
+ # First thing sent is total number of translation units
my $buf = read_all($client, 8);
my $num_tus = unpack("Q", $buf);
- my %tu_data;
+ my @tus;
for (1..$num_tus) {
my $buf = read_all($client, 8);
my $file_name_sz = unpack("Q", $buf);
@@ -51,13 +47,30 @@ sub request_data {
$buf = read_all($client, 8);
my $num_lines = unpack("Q", $buf);
- $buf = read_all($client, 8 * $num_lines);
- my @data = unpack("Q$num_lines", $buf);
-
- $tu_data{$file_name} = \@data ;
+ push @tus, { filename => $file_name, lines => $num_lines };
}
- return \%tu_data;
+ $self->{tus} = \@tus;
+ return \@tus;
+}
+
+sub get_execution_data {
+ my ($self) = @_;
+ my $client = $self->{client_socket};
+ my @tus = @{ $self->{tus} };
+
+ $client->syswrite("\x01", 1);
+
+ my @data;
+ for (@tus) {
+ my $num_lines = $_->{lines};
+
+ my $buf = read_all($client, 8 * $num_lines);
+ my @data_tmp = unpack("Q$num_lines", $buf);
+
+ push @data, [@data_tmp];
+ }
+ return \@data;
}
sub read_all {
diff --git a/lib/runtime.c b/lib/runtime.c
@@ -10,7 +10,8 @@
/* Entry point into instrumented application */
extern struct scv_node node0;
-void walk_nodes(int);
+void send_metadata(int);
+void send_execution_data(int);
void *
@@ -37,7 +38,9 @@ control_thread(void *arg)
xread(fd, &msg_type, 1);
if (msg_type == 0)
- walk_nodes(fd);
+ send_metadata(fd);
+ else if (msg_type == 1)
+ send_execution_data(fd);
else
errx(1, "unknown message type %i", msg_type);
}
@@ -51,50 +54,41 @@ static void runtime_init()
}
void
-walk_nodes(int fd)
+send_metadata(int fd)
{
size_t file_name_sz;
uint64_t num_tus = 0;
- uint64_t msg_size = 0;
-
struct scv_node walk = node0;
- /* Find out the total size of data we're going to send */
while (walk.size != 0) {
- /* Number of tus is 8 bytes */
- msg_size += sizeof(num_tus);
-
- /* File name size, 8 bytes */
- msg_size += sizeof(file_name_sz);
- /* The file name */
- msg_size += strnlen(walk.file_name, PATH_MAX);
-
- /* Number of coverage lines */
- msg_size += sizeof(uint64_t);
- /* Coverage lines, one 8 byte integer each */
- msg_size += walk.size * sizeof(uint64_t);
-
- num_tus++;
+ ++num_tus;
walk = *walk.next;
}
- /* Send total size and total number of translation units */
- xwrite(fd, &msg_size, sizeof(msg_size));
xwrite(fd, &num_tus, sizeof(num_tus));
- /* Reset walk back to the start */
walk = node0;
while (walk.size != 0) {
- file_name_sz = strnlen(walk.file_name, PATH_MAX);
-
/* Send file name size and then the file name itself. */
+ file_name_sz = strnlen(walk.file_name, PATH_MAX);
xwrite(fd, &file_name_sz, sizeof(file_name_sz));
xwrite(fd, walk.file_name, file_name_sz);
- /* Send the contents of the coverage buffer */
- xwrite(fd, &walk.size, sizeof(uint64_t));
- xwrite(fd, walk.lines_ptr, walk.size * sizeof(uint64_t));
+ /* Send the size of the execution buffers */
+ xwrite(fd, &walk.size, sizeof(walk.size));
+
+ walk = *walk.next;
+ }
+}
+void
+send_execution_data(int fd)
+{
+ struct scv_node walk = node0;
+
+ while (walk.size != 0) {
+ /* Write execution buffer, one 8 byte counter per source line */
+ xwrite(fd, walk.lines_ptr, walk.size * sizeof(uint64_t));
walk = *walk.next;
}
}
diff --git a/t/runtime_counters_increase.t b/t/runtime_counters_increase.t
@@ -53,17 +53,17 @@ $project->run(45);
# Accept the runtime's connection
$viewer->accept();
+my $metadata = $viewer->get_metadata();
+is( scalar(@{ $metadata }), 1, "runtime check for a single tu" );
-usleep(100 * 1000);
-my $data = $viewer->request_data();
-
-my ($file_name, @others) = keys %$data;
-like ($file_name, qr/tmp\/.*source_0\.c/, "runtime filename check");
-is( @others, 0, "runtime check for a single tu" );
+my $source_0 = $metadata->[0];
+like ($source_0->{filename}, qr/tmp\/.*source_0\.c/, "runtime filename check");
+is( $source_0->{lines}, 33, "runtime lines count" );
-my @lines = @{ $data->{$file_name} };
-is (scalar(@lines), 33, "runtime lines count");
+usleep(100 * 1000);
+my $data = $viewer->get_execution_data();
+my @lines = @{ $data->[0] };
# Do a pretty thorough coverage check
is ( $lines[$_], 0, "line $_ check" ) for (0..8);
cmp_ok ( $lines[$_], ">", 0, "line $_ check" ) for (9..12);
diff --git a/t/runtime_sanity.t b/t/runtime_sanity.t
@@ -2,7 +2,7 @@ use strict;
use Data::Dumper;
use SCV::Project;
use SCV::Viewer;
-use Test::More tests => 47;
+use Test::More tests => 50;
use Test::Differences;
my $viewer = SCV::Viewer->new();
@@ -66,12 +66,22 @@ $project->compile();
$project->run(45);
$viewer->accept();
-my $data = $viewer->request_data();
-like ($_, qr/tmp\/.*source_.*\.c/, "runtime filename check") for (keys %$data);
-my ($src_filename_0, $src_filename_1, $src_filename_2) = sort keys %$data;
+# Request and check metadata first
+my $metadata = $viewer->get_metadata();
-my @lines = @{ $data->{$src_filename_0} };
+my ($source_0, $source_1, $source_2) = @{ $metadata };
+like ($source_0->{filename}, qr/tmp\/.*source_0.c/, "runtime filename check 0") ;
+is ($source_0->{lines}, 24, "runtime line count check 0");
+like ($source_1->{filename}, qr/tmp\/.*source_1.c/, "runtime filename check 1") ;
+is ($source_1->{lines}, 11, "runtime line count check 1");
+like ($source_2->{filename}, qr/tmp\/.*source_2.c/, "runtime filename check 2") ;
+is ($source_2->{lines}, 9, "runtime line count check 2");
+
+# Request and check execution data
+my $data = $viewer->get_execution_data();
+
+my @lines = @{ $data->[0] };
is ( $lines[$_], 0, "src 0 line $_ check" ) for (0..13);
is ( $lines[14], 1, "src 0 line 14 check" );
is ( $lines[$_], 0, "src 0 line $_ check" ) for (15..16);
@@ -80,12 +90,12 @@ is ( $lines[$_], 0, "src 0 line $_ check" ) for (19..20);
is ( $lines[21], 2, "src 0 line 21 check" );
is ( $lines[$_], 0, "src 0 line $_ check" ) for (22..23);
-my @lines = @{ $data->{$src_filename_1} };
+my @lines = @{ $data->[1] };
is ( $lines[$_], 0, "src 1 line $_ check" ) for (0..3);
cmp_ok ( $lines[$_], ">", 100, "src 1 line $_ check" ) for (4..7);
is ( $lines[8], 0, "src 1 line 8 check" );
-my @lines = @{ $data->{$src_filename_2} };
+my @lines = @{ $data->[2] };
is ( $lines[$_], 0, "src 2 line $_ check" ) for (0..8);
$project->kill();