2
* Copyright (C) 2010 Thomas Neumann, Simon Kagstrom
4
* See COPYING for license details
11
#include <sys/types.h>
17
static const char icon_ruby[] =
18
{ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
19
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00,
20
0x25, 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd2, 0x07, 0x11, 0x0f,
21
0x18, 0x10, 0x5d, 0x57, 0x34, 0x6e, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b,
22
0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d,
23
0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45,
24
0xff, 0x35, 0x2f, 0x00, 0x00, 0x00, 0xd0, 0x33, 0x9a, 0x9d, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41,
25
0x54, 0x78, 0xda, 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, 0x00,
26
0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 };
28
static const char icon_amber[] =
29
{ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
30
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00,
31
0x25, 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd2, 0x07, 0x11, 0x0f,
32
0x28, 0x04, 0x98, 0xcb, 0xd6, 0xe0, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b,
33
0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d,
34
0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45,
35
0xff, 0xe0, 0x50, 0x00, 0x00, 0x00, 0xa2, 0x7a, 0xda, 0x7e, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41,
36
0x54, 0x78, 0xda, 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, 0x00,
37
0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 };
39
static const char icon_emerald[] =
40
{ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
41
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x25,
42
0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd2, 0x07, 0x11, 0x0f, 0x22, 0x2b,
43
0xc9, 0xf5, 0x03, 0x33, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00,
44
0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1,
45
0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0x1b, 0xea, 0x59, 0x0a, 0x0a,
46
0x0a, 0x0f, 0xba, 0x50, 0x83, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x00,
47
0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae,
50
static const char icon_snow[] =
51
{ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
52
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00,
53
0x25, 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd2, 0x07, 0x11, 0x0f,
54
0x1e, 0x1d, 0x75, 0xbc, 0xef, 0x55, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b,
55
0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d,
56
0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45,
57
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x55, 0xc2, 0xd3, 0x7e, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41,
58
0x54, 0x78, 0xda, 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, 0x00,
59
0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 };
61
static const char icon_glass[] =
62
{ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
63
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00,
64
0x25, 0xdb, 0x56, 0xca, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b,
65
0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
66
0x55, 0xc2, 0xd3, 0x7e, 0x00, 0x00, 0x00, 0x01, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x40, 0xe6, 0xd8, 0x66,
67
0x00, 0x00, 0x00, 0x01, 0x62, 0x4b, 0x47, 0x44, 0x00, 0x88, 0x05, 0x1d, 0x48, 0x00, 0x00, 0x00, 0x09,
68
0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc,
69
0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd2, 0x07, 0x13, 0x0f, 0x08, 0x19, 0xc4, 0x40,
70
0x56, 0x10, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0x9c, 0x63, 0x60, 0x00, 0x00, 0x00,
71
0x02, 0x00, 0x01, 0x48, 0xaf, 0xa4, 0x71, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42,
74
const char css_text[] = "/* Based upon the lcov CSS style, style files can be reused */\n"
75
"body { color: #000000; background-color: #FFFFFF; }\n"
76
"a:link { color: #284FA8; text-decoration: underline; }\n"
77
"a:visited { color: #00CB40; text-decoration: underline; }\n"
78
"a:active { color: #FF0040; text-decoration: underline; }\n"
79
"td.title { text-align: center; padding-bottom: 10px; font-size: 20pt; font-weight: bold; }\n"
80
"td.ruler { background-color: #6688D4; }\n"
81
"td.headerItem { text-align: right; padding-right: 6px; font-family: sans-serif; font-weight: bold; }\n"
82
"td.headerValue { text-align: left; color: #284FA8; font-family: sans-serif; font-weight: bold; }\n"
83
"td.versionInfo { text-align: center; padding-top: 2px; }\n"
84
"pre.source { font-family: monospace; white-space: pre; }\n"
85
"span.lineNum { background-color: #EFE383; }\n"
86
"span.lineCov { background-color: #CAD7FE; }\n"
87
"span.linePartCov { background-color: #FFEA20; }\n"
88
"span.lineNoCov { background-color: #FF6230; }\n"
89
"td.tableHead { text-align: center; color: #FFFFFF; background-color: #6688D4; font-family: sans-serif; font-size: 120%; font-weight: bold; }\n"
90
"td.coverFile { text-align: left; padding-left: 10px; padding-right: 20px; color: #284FA8; background-color: #DAE7FE; font-family: monospace; }\n"
91
"td.coverBar { padding-left: 10px; padding-right: 10px; background-color: #DAE7FE; }\n"
92
"td.coverBarOutline { background-color: #000000; }\n"
93
"td.coverPerHi { text-align: right; padding-left: 10px; padding-right: 10px; background-color: #A7FC9D; font-weight: bold; }\n"
94
"td.coverNumHi { text-align: right; padding-left: 10px; padding-right: 10px; background-color: #A7FC9D; }\n"
95
"td.coverPerMed { text-align: right; padding-left: 10px; padding-right: 10px; background-color: #FFEA20; font-weight: bold; }\n"
96
"td.coverNumMed { text-align: right; padding-left: 10px; padding-right: 10px; background-color: #FFEA20; }\n"
97
"td.coverPerLo { text-align: right; padding-left: 10px; padding-right: 10px; background-color: #FF0000; font-weight: bold; }\n"
98
"td.coverNumLo { text-align: right; padding-left: 10px; padding-right: 10px; background-color: #FF0000; }\n";
100
static const char **allocated_objs;
102
static int cur_allocation = 0;
103
static void cleanup_allocations(void)
107
for (i = 0; i < n_allocs; i++) {
108
free((void*)allocated_objs[i]);
109
allocated_objs[i] = NULL;
114
void *add_allocation(void *x)
116
if (cur_allocation >= n_allocs) {
120
n_allocs = n_allocs + 512;
121
allocated_objs = xrealloc(allocated_objs,
122
n_allocs * sizeof(const char *));
123
for (i = last; i < n_allocs; i++)
124
allocated_objs[i] = NULL;
127
allocated_objs[cur_allocation] = x;
133
static void write_pngs(const char *dir)
135
xwrite_file(dir, "ruby.png", icon_ruby, sizeof(icon_ruby));
136
xwrite_file(dir, "amber.png", icon_amber, sizeof(icon_amber));
137
xwrite_file(dir, "emerald.png", icon_emerald, sizeof(icon_emerald));
138
xwrite_file(dir, "snow.png", icon_snow, sizeof(icon_snow));
139
xwrite_file(dir, "glass.png", icon_glass, sizeof(icon_glass));
142
static const char *construct_bar(double percent)
144
const char* color = "ruby.png";
146
int width = (int)(percent+0.5);
149
color = "emerald.png";
150
else if (percent>=15)
152
else if (percent <= 1)
155
xsnprintf(buf, sizeof(buf),
156
"<img src=\"%s\" width=\"%d\" height=\"10\" alt=\"%.1f%%\"/><img src=\"snow.png\" width=\"%d\" height=\"10\" alt=\"%.1f%%\"/>",
157
color, width, percent, 100 - width, percent);
159
return add_allocation(xstrdup(buf));
162
static void write_css(const char *dir)
164
xwrite_file(dir, "/bcov.css", css_text, sizeof(css_text));
167
static char *escape_helper(char *dst, char *what)
169
int len = strlen(what);
176
static const char *outfile_name_from_kc_file(struct kc_file *kc_file)
178
char *p = strrchr(kc_file->filename, '/');
184
out = xmalloc(strlen(p) + 8);
185
xsnprintf(out, strlen(p) + 8, "%s.html", p + 1);
191
static const char *tmp_outfile_name_from_kc_file(struct kc_file *kc_file)
193
char *p = strrchr(kc_file->filename, '/');
199
out = xmalloc(strlen(p) + 16);
200
xsnprintf(out, strlen(p) + 16, "%s.html.tmp", p + 1);
207
static const char *dir_concat_report(const char *dir, const char *filename)
209
return add_allocation((void*)dir_concat(dir, filename));
212
static const char *escape_html(const char *s)
216
size_t len = strlen(s);
219
memset(buf, 0, sizeof(buf));
220
for (i = 0; i < len; i++) {
223
if ((c & 0xff) > 127) {
226
xsnprintf(tmp_val, sizeof(tmp_val), "&#%x;", c & 0xff);
227
dst = escape_helper(dst, tmp_val);
231
dst = escape_helper(dst, "<");
234
dst = escape_helper(dst, ">");
237
dst = escape_helper(dst, "&");
240
dst = escape_helper(dst, """);
242
case '\n': case '\r':
243
dst = escape_helper(dst, " ");
253
return add_allocation(strdup(buf));
256
static void write_header(FILE *fp, struct kc *kc, struct kc_file *file,
257
int lines, int active_lines)
265
strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", tm);
267
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
270
" <title>Coverage - %s</title>\n"
271
" <link rel=\"stylesheet\" type=\"text/css\" href=\"bcov.css\"/>\n"
274
"<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n"
275
" <tr><td class=\"title\">Coverage Report</td></tr>\n"
276
" <tr><td class=\"ruler\"><img src=\"glass.png\" width=\"3\" height=\"3\" alt=\"\"/></td></tr>\n"
278
" <td width=\"100%%\">\n"
279
" <table cellpadding=\"1\" border=\"0\" width=\"100%%\">\n"
281
" <td class=\"headerItem\" width=\"20%%\">Command:</td>\n"
282
" <td class=\"headerValue\" width=\"80%%\" colspan=6>%s</td>\n"
285
" <td class=\"headerItem\" width=\"20%%\">Date:</td>\n"
286
" <td class=\"headerValue\" width=\"15%%\">%s</td>\n"
287
" <td width=\"5%%\"></td>\n"
288
" <td class=\"headerItem\" width=\"20%%\">Instrumented lines:</td>\n"
289
" <td class=\"headerValue\" width=\"10%%\">%d</td>\n"
292
" <td class=\"headerItem\" width=\"20%%\">Code covered:</td>\n"
293
" <td class=\"headerValue\" width=\"15%%\">%.1f %%</td>\n"
294
" <td width=\"5%%\"></td>\n"
295
" <td class=\"headerItem\" width=\"20%%\">Executed lines:</td>\n"
296
" <td class=\"headerValue\" width=\"10%%\">%d</td>\n"
301
" <tr><td class=\"ruler\"><img src=\"glass.png\" width=\"3\" height=\"3\" alt=\"\"/></td></tr>\n"
303
escape_html(kc->module_name), /* Title */
304
escape_html(kc->module_name), /* Command */
307
lines == 0 ? 0 : ((float)active_lines / (float)lines) * 100,
312
static void write_footer(FILE *fp)
315
"<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n"
316
" <tr><td class=\"ruler\"><img src=\"glass.png\" width=\"3\" height=\"3\" alt=\"\"/></td></tr>\n"
317
" <tr><td class=\"versionInfo\">Generated by: <a href=\"http://simonkagstrom.github.com/kcov/index.html\">Kcov</a> (based on <a href=\"http://bcov.sourceforge.net\">bcov</a>)</td></tr>\n"
324
static int write_file_report(const char *dir, struct kc *kc, struct kc_file *kc_file)
326
const char *tmp_outfile_name = tmp_outfile_name_from_kc_file(kc_file);
327
const char *outfile_name = outfile_name_from_kc_file(kc_file);
333
if (!tmp_outfile_name)
336
fp = fopen(kc_file->filename, "r");
340
out_fp = fopen(dir_concat_report(dir, tmp_outfile_name), "w");
344
fprintf(out_fp, "<pre class=\"source\">\n");
346
/* Read the lines of the source file */
349
struct kc_line *kc_line = kc_file_lookup_line(kc_file, lineno);
352
if (getline(&line, &sz, fp) < 0) {
359
"<span class=\"lineNum\">%7d </span>",
363
const char *line_class = "lineNoCov";
368
for (i = 0; i < kc_line->n_addrs; i++) {
369
struct kc_addr *addr = kc_line->addrs[i];
373
/* Full, partial or no coverage? */
374
if (hits >= kc_line->possible_hits)
375
line_class = "lineCov";
377
line_class = "linePartCov";
379
"<span class=\"%s\"> %4u / %-4u : ",
380
line_class, hits, kc_line->possible_hits);
385
fprintf(out_fp, " : ");
387
fprintf(out_fp, "%s</span>\n", escape_html(line));
392
fprintf(out_fp, "</pre>\n");
394
write_footer(out_fp);
400
fp = fopen(dir_concat_report(dir, "tmp"), "w");
403
write_header(fp, kc, NULL, g_hash_table_size(kc_file->lines),
407
concat_files(dir_concat_report(dir, outfile_name),
408
dir_concat_report(dir, "tmp"),
409
dir_concat_report(dir, tmp_outfile_name));
410
unlink(dir_concat_report(dir, "tmp"));
411
unlink(dir_concat_report(dir, tmp_outfile_name));
417
static int kc_file_cmp(const void *pa, const void *pb)
419
struct kc_file *a = *(struct kc_file **)pa;
420
struct kc_file *b = *(struct kc_file **)pb;
422
return strcmp(a->filename, b->filename);
425
static int kc_percentage_cmp(const void *pa, const void *pb)
427
struct kc_file *a = *(struct kc_file **)pa;
428
struct kc_file *b = *(struct kc_file **)pb;
430
return (int)(a->percentage - b->percentage);
435
static int report_path(const char *path, struct kc *kc)
437
const char **p = kc->only_report_paths;
442
if (strstr(path, p[i]))
451
static int exclude_path(const char *path, struct kc *kc)
453
const char **p = kc->exclude_paths;
458
if (strstr(path, p[i]))
467
static int write_index(const char *dir, struct kc *kc)
471
struct kc_file *kc_file;
472
struct kc_file **files;
474
int total_active_lines = 0;
479
fp = fopen(dir_concat_report(dir, "index.html.main"), "w");
485
" <table width=\"80%%\" cellpadding=\"2\" cellspacing=\"1\" border=\"0\">\n"
487
" <td width=\"50%%\"><br/></td>\n"
488
" <td width=\"15%%\"></td>\n"
489
" <td width=\"15%%\"></td>\n"
490
" <td width=\"20%%\"></td>\n"
493
" <td class=\"tableHead\">Filename</td>\n"
494
" <td class=\"tableHead\" colspan=\"3\">Coverage</td>\n"
497
/* Sort the files by name */
498
files = add_allocation(xmalloc(g_hash_table_size(kc->files) * sizeof(struct kc_file *)));
499
g_hash_table_iter_init(&iter, kc->files);
500
while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&kc_file)) {
501
files[n_files] = kc_file;
504
qsort(files, g_hash_table_size(kc->files), sizeof(struct kc_file *),
505
kc->sort_type == COVERAGE_PERCENT ? kc_percentage_cmp : kc_file_cmp);
506
for (file_idx = 0; file_idx < n_files; file_idx++) {
507
double percentage = 0;
508
const char *percentage_text = "Lo";
509
int active_lines = 0;
510
GHashTableIter line_iter;
512
struct kc_line *line_val;
515
kc_file = files[file_idx];
517
if (!report_path(kc_file->filename, kc))
520
if (exclude_path(kc_file->filename, kc))
523
if (!file_exists(kc_file->filename))
526
/* Count the percentage of hits */
527
n_lines = g_hash_table_size(kc_file->lines);
528
g_hash_table_iter_init(&line_iter, kc_file->lines);
529
while (g_hash_table_iter_next(&line_iter,
530
(gpointer*)&line_key, (gpointer*)&line_val)) {
533
for (i = 0; i < line_val->n_addrs; i++) {
534
if (line_val->addrs[i]->hits > 0) {
535
/* Only care about full lines */
543
percentage = ((double)active_lines / (double)n_lines) * 100;
544
kc_file->percentage = percentage;
546
total_lines += n_lines;
547
total_active_lines += active_lines;
549
if (percentage > kc->low_limit && percentage < kc->high_limit)
550
percentage_text = "Med";
551
else if (percentage >= kc->high_limit)
552
percentage_text = "Hi";
556
" <td class=\"coverFile\"><a href=\"%s\">%s</a></td>\n"
557
" <td class=\"coverBar\" align=\"center\">\n"
558
" <table border=\"0\" cellspacing=\"0\" cellpadding=\"1\"><tr><td class=\"coverBarOutline\">%s</td></tr></table>\n"
560
" <td class=\"coverPer%s\">%.1f %%</td>\n"
561
" <td class=\"coverNum%s\">%d / %d lines</td>\n"
563
outfile_name_from_kc_file(kc_file),
565
construct_bar(percentage),
566
percentage_text, percentage,
567
percentage_text, active_lines, n_lines);
577
fp = fopen(dir_concat_report(dir, "index.html.hdr"), "w");
580
write_header(fp, kc, NULL, total_lines, total_active_lines);
583
concat_files(dir_concat_report(dir, "index.html"),
584
dir_concat_report(dir, "index.html.hdr"),
585
dir_concat_report(dir, "index.html.main"));
586
unlink(dir_concat_report(dir, "index.html.hdr"));
587
unlink(dir_concat_report(dir, "index.html.main"));
592
static void write_report(const char *dir, struct kc *kc)
598
/* Write an index first */
599
write_index(dir, kc);
601
g_hash_table_iter_init(&iter, kc->files);
602
while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&val)) {
603
if (file_exists(val->filename))
604
write_file_report(dir, kc, val);
607
cleanup_allocations();
612
static pthread_t thread;
613
static const char *g_dir;
614
static struct kc *g_kc;
615
static int should_exit;
617
static void *report_thread(void *priv)
628
write_report(g_dir, g_kc);
635
/* Do this twice to collect percentages from last round */
636
write_report(g_dir, g_kc);
637
write_report(g_dir, g_kc);
644
void stop_report_thread(void)
647
pthread_join(thread, NULL);
648
cleanup_allocations();
650
if (g_kc->type == PTRACE_PID || g_kc->type == PTRACE_FILE)
655
void run_report_thread(const char *dir, struct kc *kc)
661
ret = pthread_create(&thread, NULL, report_thread, NULL);
662
panic_if (ret < 0, "Can't create thread");