mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
Merge tag 'perf-core-for-mingo-20160510' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: - Recording 'dwarf' callchains do not need DWARF unwinding support (He Kuang) - Print recently added perf_event_attr.write_backward bit flag in -vv verbose mode (Arnaldo Carvalho de Melo) - Fix incorrect python db-export error message in 'perf script' (Chris Phlipot) - Fix handling of zero-length symbols (Chris Phlipot) - perf stat: Scale values by unit before metrics (Andi Kleen) Infrastructure changes: - Rewrite strbuf not to die(), making tools using it to check its return value instead (Masami Hiramatsu) - Support reading from backward ring buffer, add a 'perf test' entry for it (Wang Nan) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
38f5d8b32f
@ -61,6 +61,7 @@ static int check_emacsclient_version(void)
|
|||||||
struct child_process ec_process;
|
struct child_process ec_process;
|
||||||
const char *argv_ec[] = { "emacsclient", "--version", NULL };
|
const char *argv_ec[] = { "emacsclient", "--version", NULL };
|
||||||
int version;
|
int version;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
/* emacsclient prints its version number on stderr */
|
/* emacsclient prints its version number on stderr */
|
||||||
memset(&ec_process, 0, sizeof(ec_process));
|
memset(&ec_process, 0, sizeof(ec_process));
|
||||||
@ -71,7 +72,10 @@ static int check_emacsclient_version(void)
|
|||||||
fprintf(stderr, "Failed to start emacsclient.\n");
|
fprintf(stderr, "Failed to start emacsclient.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
strbuf_read(&buffer, ec_process.err, 20);
|
if (strbuf_read(&buffer, ec_process.err, 20) < 0) {
|
||||||
|
fprintf(stderr, "Failed to read emacsclient version\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
close(ec_process.err);
|
close(ec_process.err);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -82,8 +86,7 @@ static int check_emacsclient_version(void)
|
|||||||
|
|
||||||
if (prefixcmp(buffer.buf, "emacsclient")) {
|
if (prefixcmp(buffer.buf, "emacsclient")) {
|
||||||
fprintf(stderr, "Failed to parse emacsclient version.\n");
|
fprintf(stderr, "Failed to parse emacsclient version.\n");
|
||||||
strbuf_release(&buffer);
|
goto out;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
version = atoi(buffer.buf + strlen("emacsclient"));
|
version = atoi(buffer.buf + strlen("emacsclient"));
|
||||||
@ -92,12 +95,11 @@ static int check_emacsclient_version(void)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"emacsclient version '%d' too old (< 22).\n",
|
"emacsclient version '%d' too old (< 22).\n",
|
||||||
version);
|
version);
|
||||||
strbuf_release(&buffer);
|
} else
|
||||||
return -1;
|
ret = 0;
|
||||||
}
|
out:
|
||||||
|
|
||||||
strbuf_release(&buffer);
|
strbuf_release(&buffer);
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exec_woman_emacs(const char *path, const char *page)
|
static void exec_woman_emacs(const char *path, const char *page)
|
||||||
|
@ -309,9 +309,11 @@ static int handle_alias(int *argcp, const char ***argv)
|
|||||||
if (*argcp > 1) {
|
if (*argcp > 1) {
|
||||||
struct strbuf buf;
|
struct strbuf buf;
|
||||||
|
|
||||||
strbuf_init(&buf, PATH_MAX);
|
if (strbuf_init(&buf, PATH_MAX) < 0 ||
|
||||||
strbuf_addstr(&buf, alias_string);
|
strbuf_addstr(&buf, alias_string) < 0 ||
|
||||||
sq_quote_argv(&buf, (*argv) + 1, PATH_MAX);
|
sq_quote_argv(&buf, (*argv) + 1,
|
||||||
|
PATH_MAX) < 0)
|
||||||
|
die("Failed to allocate memory.");
|
||||||
free(alias_string);
|
free(alias_string);
|
||||||
alias_string = buf.buf;
|
alias_string = buf.buf;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ perf-y += cpumap.o
|
|||||||
perf-y += stat.o
|
perf-y += stat.o
|
||||||
perf-y += event_update.o
|
perf-y += event_update.o
|
||||||
perf-y += event-times.o
|
perf-y += event-times.o
|
||||||
|
perf-y += backward-ring-buffer.o
|
||||||
|
|
||||||
$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
|
$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
|
||||||
$(call rule_mkdir)
|
$(call rule_mkdir)
|
||||||
|
151
tools/perf/tests/backward-ring-buffer.c
Normal file
151
tools/perf/tests/backward-ring-buffer.c
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* Test backward bit in event attribute, read ring buffer from end to
|
||||||
|
* beginning
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <perf.h>
|
||||||
|
#include <evlist.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#include "tests.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#define NR_ITERS 111
|
||||||
|
|
||||||
|
static void testcase(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < NR_ITERS; i++) {
|
||||||
|
char proc_name[10];
|
||||||
|
|
||||||
|
snprintf(proc_name, sizeof(proc_name), "p:%d\n", i);
|
||||||
|
prctl(PR_SET_NAME, proc_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int count_samples(struct perf_evlist *evlist, int *sample_count,
|
||||||
|
int *comm_count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < evlist->nr_mmaps; i++) {
|
||||||
|
union perf_event *event;
|
||||||
|
|
||||||
|
perf_evlist__mmap_read_catchup(evlist, i);
|
||||||
|
while ((event = perf_evlist__mmap_read_backward(evlist, i)) != NULL) {
|
||||||
|
const u32 type = event->header.type;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case PERF_RECORD_SAMPLE:
|
||||||
|
(*sample_count)++;
|
||||||
|
break;
|
||||||
|
case PERF_RECORD_COMM:
|
||||||
|
(*comm_count)++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_err("Unexpected record of type %d\n", type);
|
||||||
|
return TEST_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TEST_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_test(struct perf_evlist *evlist, int mmap_pages,
|
||||||
|
int *sample_count, int *comm_count)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
char sbuf[STRERR_BUFSIZE];
|
||||||
|
|
||||||
|
err = perf_evlist__mmap(evlist, mmap_pages, true);
|
||||||
|
if (err < 0) {
|
||||||
|
pr_debug("perf_evlist__mmap: %s\n",
|
||||||
|
strerror_r(errno, sbuf, sizeof(sbuf)));
|
||||||
|
return TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
perf_evlist__enable(evlist);
|
||||||
|
testcase();
|
||||||
|
perf_evlist__disable(evlist);
|
||||||
|
|
||||||
|
err = count_samples(evlist, sample_count, comm_count);
|
||||||
|
perf_evlist__munmap(evlist);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int test__backward_ring_buffer(int subtest __maybe_unused)
|
||||||
|
{
|
||||||
|
int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0;
|
||||||
|
char pid[16], sbuf[STRERR_BUFSIZE];
|
||||||
|
struct perf_evlist *evlist;
|
||||||
|
struct perf_evsel *evsel __maybe_unused;
|
||||||
|
struct parse_events_error parse_error;
|
||||||
|
struct record_opts opts = {
|
||||||
|
.target = {
|
||||||
|
.uid = UINT_MAX,
|
||||||
|
.uses_mmap = true,
|
||||||
|
},
|
||||||
|
.freq = 0,
|
||||||
|
.mmap_pages = 256,
|
||||||
|
.default_interval = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
snprintf(pid, sizeof(pid), "%d", getpid());
|
||||||
|
pid[sizeof(pid) - 1] = '\0';
|
||||||
|
opts.target.tid = opts.target.pid = pid;
|
||||||
|
|
||||||
|
evlist = perf_evlist__new();
|
||||||
|
if (!evlist) {
|
||||||
|
pr_debug("No ehough memory to create evlist\n");
|
||||||
|
return TEST_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = perf_evlist__create_maps(evlist, &opts.target);
|
||||||
|
if (err < 0) {
|
||||||
|
pr_debug("Not enough memory to create thread/cpu maps\n");
|
||||||
|
goto out_delete_evlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(&parse_error, sizeof(parse_error));
|
||||||
|
err = parse_events(evlist, "syscalls:sys_enter_prctl", &parse_error);
|
||||||
|
if (err) {
|
||||||
|
pr_debug("Failed to parse tracepoint event, try use root\n");
|
||||||
|
ret = TEST_SKIP;
|
||||||
|
goto out_delete_evlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
perf_evlist__config(evlist, &opts, NULL);
|
||||||
|
|
||||||
|
/* Set backward bit, ring buffer should be writing from end */
|
||||||
|
evlist__for_each(evlist, evsel)
|
||||||
|
evsel->attr.write_backward = 1;
|
||||||
|
|
||||||
|
err = perf_evlist__open(evlist);
|
||||||
|
if (err < 0) {
|
||||||
|
pr_debug("perf_evlist__open: %s\n",
|
||||||
|
strerror_r(errno, sbuf, sizeof(sbuf)));
|
||||||
|
goto out_delete_evlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TEST_FAIL;
|
||||||
|
err = do_test(evlist, opts.mmap_pages, &sample_count,
|
||||||
|
&comm_count);
|
||||||
|
if (err != TEST_OK)
|
||||||
|
goto out_delete_evlist;
|
||||||
|
|
||||||
|
if ((sample_count != NR_ITERS) || (comm_count != NR_ITERS)) {
|
||||||
|
pr_err("Unexpected counter: sample_count=%d, comm_count=%d\n",
|
||||||
|
sample_count, comm_count);
|
||||||
|
goto out_delete_evlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = do_test(evlist, 1, &sample_count, &comm_count);
|
||||||
|
if (err != TEST_OK)
|
||||||
|
goto out_delete_evlist;
|
||||||
|
|
||||||
|
ret = TEST_OK;
|
||||||
|
out_delete_evlist:
|
||||||
|
perf_evlist__delete(evlist);
|
||||||
|
return ret;
|
||||||
|
}
|
@ -207,6 +207,10 @@ static struct test generic_tests[] = {
|
|||||||
.desc = "Test events times",
|
.desc = "Test events times",
|
||||||
.func = test__event_times,
|
.func = test__event_times,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.desc = "Test backward reading from ring buffer",
|
||||||
|
.func = test__backward_ring_buffer,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.func = NULL,
|
.func = NULL,
|
||||||
},
|
},
|
||||||
|
@ -86,6 +86,7 @@ int test__synthesize_stat(int subtest);
|
|||||||
int test__synthesize_stat_round(int subtest);
|
int test__synthesize_stat_round(int subtest);
|
||||||
int test__event_update(int subtest);
|
int test__event_update(int subtest);
|
||||||
int test__event_times(int subtest);
|
int test__event_times(int subtest);
|
||||||
|
int test__backward_ring_buffer(int subtest);
|
||||||
|
|
||||||
#if defined(__arm__) || defined(__aarch64__)
|
#if defined(__arm__) || defined(__aarch64__)
|
||||||
#ifdef HAVE_DWARF_UNWIND_SUPPORT
|
#ifdef HAVE_DWARF_UNWIND_SUPPORT
|
||||||
|
@ -27,7 +27,6 @@ libperf-y += strlist.o
|
|||||||
libperf-y += strfilter.o
|
libperf-y += strfilter.o
|
||||||
libperf-y += top.o
|
libperf-y += top.o
|
||||||
libperf-y += usage.o
|
libperf-y += usage.o
|
||||||
libperf-y += wrapper.o
|
|
||||||
libperf-y += dso.o
|
libperf-y += dso.o
|
||||||
libperf-y += symbol.o
|
libperf-y += symbol.o
|
||||||
libperf-y += symbol_fprintf.o
|
libperf-y += symbol_fprintf.o
|
||||||
|
@ -40,25 +40,6 @@ int split_cmdline(char *cmdline, const char ***argv);
|
|||||||
|
|
||||||
#define alloc_nr(x) (((x)+16)*3/2)
|
#define alloc_nr(x) (((x)+16)*3/2)
|
||||||
|
|
||||||
/*
|
|
||||||
* Realloc the buffer pointed at by variable 'x' so that it can hold
|
|
||||||
* at least 'nr' entries; the number of entries currently allocated
|
|
||||||
* is 'alloc', using the standard growing factor alloc_nr() macro.
|
|
||||||
*
|
|
||||||
* DO NOT USE any expression with side-effect for 'x' or 'alloc'.
|
|
||||||
*/
|
|
||||||
#define ALLOC_GROW(x, nr, alloc) \
|
|
||||||
do { \
|
|
||||||
if ((nr) > alloc) { \
|
|
||||||
if (alloc_nr(alloc) < (nr)) \
|
|
||||||
alloc = (nr); \
|
|
||||||
else \
|
|
||||||
alloc = alloc_nr(alloc); \
|
|
||||||
x = xrealloc((x), alloc * sizeof(*(x))); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
|
|
||||||
static inline int is_absolute_path(const char *path)
|
static inline int is_absolute_path(const char *path)
|
||||||
{
|
{
|
||||||
return path[0] == '/';
|
return path[0] == '/';
|
||||||
|
@ -915,8 +915,7 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
|
|||||||
tmp = "*";
|
tmp = "*";
|
||||||
else if (tag == DW_TAG_subroutine_type) {
|
else if (tag == DW_TAG_subroutine_type) {
|
||||||
/* Function pointer */
|
/* Function pointer */
|
||||||
strbuf_add(buf, "(function_type)", 15);
|
return strbuf_add(buf, "(function_type)", 15);
|
||||||
return 0;
|
|
||||||
} else {
|
} else {
|
||||||
if (!dwarf_diename(&type))
|
if (!dwarf_diename(&type))
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@ -927,14 +926,10 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
|
|||||||
else if (tag == DW_TAG_enumeration_type)
|
else if (tag == DW_TAG_enumeration_type)
|
||||||
tmp = "enum ";
|
tmp = "enum ";
|
||||||
/* Write a base name */
|
/* Write a base name */
|
||||||
strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));
|
return strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
ret = die_get_typename(&type, buf);
|
ret = die_get_typename(&type, buf);
|
||||||
if (ret == 0)
|
return ret ? ret : strbuf_addstr(buf, tmp);
|
||||||
strbuf_addstr(buf, tmp);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -951,12 +946,10 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
|
|||||||
ret = die_get_typename(vr_die, buf);
|
ret = die_get_typename(vr_die, buf);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_debug("Failed to get type, make it unknown.\n");
|
pr_debug("Failed to get type, make it unknown.\n");
|
||||||
strbuf_add(buf, " (unknown_type)", 14);
|
ret = strbuf_add(buf, " (unknown_type)", 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
|
return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DWARF_GETLOCATIONS
|
#ifdef HAVE_DWARF_GETLOCATIONS
|
||||||
@ -999,22 +992,24 @@ static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
|
|||||||
}
|
}
|
||||||
|
|
||||||
while ((offset = dwarf_ranges(&scopes[1], offset, &base,
|
while ((offset = dwarf_ranges(&scopes[1], offset, &base,
|
||||||
&start, &end)) > 0) {
|
&start, &end)) > 0) {
|
||||||
start -= entry;
|
start -= entry;
|
||||||
end -= entry;
|
end -= entry;
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
|
ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
|
||||||
name, start, end);
|
name, start, end);
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
|
ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
|
||||||
start, end);
|
start, end);
|
||||||
}
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first)
|
if (!first)
|
||||||
strbuf_add(buf, "]>", 2);
|
ret = strbuf_add(buf, "]>", 2);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(scopes);
|
free(scopes);
|
||||||
@ -1054,31 +1049,32 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf)
|
|||||||
if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
|
if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
while ((offset = dwarf_getlocations(
|
while ((offset = dwarf_getlocations(&attr, offset, &base,
|
||||||
&attr, offset, &base,
|
&start, &end, &op, &nops)) > 0) {
|
||||||
&start, &end, &op, &nops)) > 0) {
|
|
||||||
if (start == 0) {
|
if (start == 0) {
|
||||||
/* Single Location Descriptions */
|
/* Single Location Descriptions */
|
||||||
ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
|
ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
|
||||||
return ret;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Location Lists */
|
/* Location Lists */
|
||||||
start -= entry;
|
start -= entry;
|
||||||
end -= entry;
|
end -= entry;
|
||||||
if (first) {
|
if (first) {
|
||||||
strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
|
ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
|
||||||
name, start, end);
|
name, start, end);
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
|
ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
|
||||||
start, end);
|
start, end);
|
||||||
}
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first)
|
if (!first)
|
||||||
strbuf_add(buf, "]>", 2);
|
ret = strbuf_add(buf, "]>", 2);
|
||||||
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -766,6 +766,56 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
|
|||||||
return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev);
|
return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
union perf_event *
|
||||||
|
perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
|
||||||
|
{
|
||||||
|
struct perf_mmap *md = &evlist->mmap[idx];
|
||||||
|
u64 head, end;
|
||||||
|
u64 start = md->prev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if event was unmapped due to a POLLHUP/POLLERR.
|
||||||
|
*/
|
||||||
|
if (!atomic_read(&md->refcnt))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
head = perf_mmap__read_head(md);
|
||||||
|
if (!head)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 'head' pointer starts from 0. Kernel minus sizeof(record) form
|
||||||
|
* it each time when kernel writes to it, so in fact 'head' is
|
||||||
|
* negative. 'end' pointer is made manually by adding the size of
|
||||||
|
* the ring buffer to 'head' pointer, means the validate data can
|
||||||
|
* read is the whole ring buffer. If 'end' is positive, the ring
|
||||||
|
* buffer has not fully filled, so we must adjust 'end' to 0.
|
||||||
|
*
|
||||||
|
* However, since both 'head' and 'end' is unsigned, we can't
|
||||||
|
* simply compare 'end' against 0. Here we compare '-head' and
|
||||||
|
* the size of the ring buffer, where -head is the number of bytes
|
||||||
|
* kernel write to the ring buffer.
|
||||||
|
*/
|
||||||
|
if (-head < (u64)(md->mask + 1))
|
||||||
|
end = 0;
|
||||||
|
else
|
||||||
|
end = head + md->mask + 1;
|
||||||
|
|
||||||
|
return perf_mmap__read(md, false, start, end, &md->prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
|
||||||
|
{
|
||||||
|
struct perf_mmap *md = &evlist->mmap[idx];
|
||||||
|
u64 head;
|
||||||
|
|
||||||
|
if (!atomic_read(&md->refcnt))
|
||||||
|
return;
|
||||||
|
|
||||||
|
head = perf_mmap__read_head(md);
|
||||||
|
md->prev = head;
|
||||||
|
}
|
||||||
|
|
||||||
static bool perf_mmap__empty(struct perf_mmap *md)
|
static bool perf_mmap__empty(struct perf_mmap *md)
|
||||||
{
|
{
|
||||||
return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
|
return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
|
||||||
|
@ -129,6 +129,10 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
|
|||||||
|
|
||||||
union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
|
union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
|
||||||
|
|
||||||
|
union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist,
|
||||||
|
int idx);
|
||||||
|
void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
|
||||||
|
|
||||||
void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
|
void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
|
||||||
|
|
||||||
int perf_evlist__open(struct perf_evlist *evlist);
|
int perf_evlist__open(struct perf_evlist *evlist);
|
||||||
|
@ -1316,6 +1316,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
|
|||||||
PRINT_ATTRf(comm_exec, p_unsigned);
|
PRINT_ATTRf(comm_exec, p_unsigned);
|
||||||
PRINT_ATTRf(use_clockid, p_unsigned);
|
PRINT_ATTRf(use_clockid, p_unsigned);
|
||||||
PRINT_ATTRf(context_switch, p_unsigned);
|
PRINT_ATTRf(context_switch, p_unsigned);
|
||||||
|
PRINT_ATTRf(write_backward, p_unsigned);
|
||||||
|
|
||||||
PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
|
PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
|
||||||
PRINT_ATTRf(bp_type, p_unsigned);
|
PRINT_ATTRf(bp_type, p_unsigned);
|
||||||
|
@ -1819,7 +1819,8 @@ static int process_cpu_topology(struct perf_file_section *section,
|
|||||||
|
|
||||||
ph->env.nr_sibling_cores = nr;
|
ph->env.nr_sibling_cores = nr;
|
||||||
size += sizeof(u32);
|
size += sizeof(u32);
|
||||||
strbuf_init(&sb, 128);
|
if (strbuf_init(&sb, 128) < 0)
|
||||||
|
goto free_cpu;
|
||||||
|
|
||||||
for (i = 0; i < nr; i++) {
|
for (i = 0; i < nr; i++) {
|
||||||
str = do_read_string(fd, ph);
|
str = do_read_string(fd, ph);
|
||||||
@ -1827,7 +1828,8 @@ static int process_cpu_topology(struct perf_file_section *section,
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* include a NULL character at the end */
|
/* include a NULL character at the end */
|
||||||
strbuf_add(&sb, str, strlen(str) + 1);
|
if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
|
||||||
|
goto error;
|
||||||
size += string_size(str);
|
size += string_size(str);
|
||||||
free(str);
|
free(str);
|
||||||
}
|
}
|
||||||
@ -1849,7 +1851,8 @@ static int process_cpu_topology(struct perf_file_section *section,
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* include a NULL character at the end */
|
/* include a NULL character at the end */
|
||||||
strbuf_add(&sb, str, strlen(str) + 1);
|
if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
|
||||||
|
goto error;
|
||||||
size += string_size(str);
|
size += string_size(str);
|
||||||
free(str);
|
free(str);
|
||||||
}
|
}
|
||||||
@ -1912,13 +1915,14 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
|
|||||||
/* nr nodes */
|
/* nr nodes */
|
||||||
ret = readn(fd, &nr, sizeof(nr));
|
ret = readn(fd, &nr, sizeof(nr));
|
||||||
if (ret != sizeof(nr))
|
if (ret != sizeof(nr))
|
||||||
goto error;
|
return -1;
|
||||||
|
|
||||||
if (ph->needs_swap)
|
if (ph->needs_swap)
|
||||||
nr = bswap_32(nr);
|
nr = bswap_32(nr);
|
||||||
|
|
||||||
ph->env.nr_numa_nodes = nr;
|
ph->env.nr_numa_nodes = nr;
|
||||||
strbuf_init(&sb, 256);
|
if (strbuf_init(&sb, 256) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
for (i = 0; i < nr; i++) {
|
for (i = 0; i < nr; i++) {
|
||||||
/* node number */
|
/* node number */
|
||||||
@ -1940,15 +1944,17 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
|
|||||||
mem_free = bswap_64(mem_free);
|
mem_free = bswap_64(mem_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":",
|
if (strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":",
|
||||||
node, mem_total, mem_free);
|
node, mem_total, mem_free) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
str = do_read_string(fd, ph);
|
str = do_read_string(fd, ph);
|
||||||
if (!str)
|
if (!str)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* include a NULL character at the end */
|
/* include a NULL character at the end */
|
||||||
strbuf_add(&sb, str, strlen(str) + 1);
|
if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
|
||||||
|
goto error;
|
||||||
free(str);
|
free(str);
|
||||||
}
|
}
|
||||||
ph->env.numa_nodes = strbuf_detach(&sb, NULL);
|
ph->env.numa_nodes = strbuf_detach(&sb, NULL);
|
||||||
@ -1982,7 +1988,8 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
|
|||||||
}
|
}
|
||||||
|
|
||||||
ph->env.nr_pmu_mappings = pmu_num;
|
ph->env.nr_pmu_mappings = pmu_num;
|
||||||
strbuf_init(&sb, 128);
|
if (strbuf_init(&sb, 128) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
while (pmu_num) {
|
while (pmu_num) {
|
||||||
if (readn(fd, &type, sizeof(type)) != sizeof(type))
|
if (readn(fd, &type, sizeof(type)) != sizeof(type))
|
||||||
@ -1994,9 +2001,11 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
|
|||||||
if (!name)
|
if (!name)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
strbuf_addf(&sb, "%u:%s", type, name);
|
if (strbuf_addf(&sb, "%u:%s", type, name) < 0)
|
||||||
|
goto error;
|
||||||
/* include a NULL character at the end */
|
/* include a NULL character at the end */
|
||||||
strbuf_add(&sb, "", 1);
|
if (strbuf_add(&sb, "", 1) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (!strcmp(name, "msr"))
|
if (!strcmp(name, "msr"))
|
||||||
ph->env.msr_pmu_type = type;
|
ph->env.msr_pmu_type = type;
|
||||||
|
@ -27,16 +27,27 @@ static int levenshtein_compare(const void *p1, const void *p2)
|
|||||||
return l1 != l2 ? l1 - l2 : strcmp(s1, s2);
|
return l1 != l2 ? l1 - l2 : strcmp(s1, s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
|
static int add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i, nr = cmds->cnt + old->cnt;
|
||||||
|
void *tmp;
|
||||||
ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc);
|
|
||||||
|
|
||||||
|
if (nr > cmds->alloc) {
|
||||||
|
/* Choose bigger one to alloc */
|
||||||
|
if (alloc_nr(cmds->alloc) < nr)
|
||||||
|
cmds->alloc = nr;
|
||||||
|
else
|
||||||
|
cmds->alloc = alloc_nr(cmds->alloc);
|
||||||
|
tmp = realloc(cmds->names, cmds->alloc * sizeof(*cmds->names));
|
||||||
|
if (!tmp)
|
||||||
|
return -1;
|
||||||
|
cmds->names = tmp;
|
||||||
|
}
|
||||||
for (i = 0; i < old->cnt; i++)
|
for (i = 0; i < old->cnt; i++)
|
||||||
cmds->names[cmds->cnt++] = old->names[i];
|
cmds->names[cmds->cnt++] = old->names[i];
|
||||||
zfree(&old->names);
|
zfree(&old->names);
|
||||||
old->cnt = 0;
|
old->cnt = 0;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *help_unknown_cmd(const char *cmd)
|
const char *help_unknown_cmd(const char *cmd)
|
||||||
@ -52,8 +63,11 @@ const char *help_unknown_cmd(const char *cmd)
|
|||||||
|
|
||||||
load_command_list("perf-", &main_cmds, &other_cmds);
|
load_command_list("perf-", &main_cmds, &other_cmds);
|
||||||
|
|
||||||
add_cmd_list(&main_cmds, &aliases);
|
if (add_cmd_list(&main_cmds, &aliases) < 0 ||
|
||||||
add_cmd_list(&main_cmds, &other_cmds);
|
add_cmd_list(&main_cmds, &other_cmds) < 0) {
|
||||||
|
fprintf(stderr, "ERROR: Failed to allocate command list for unknown command.\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
qsort(main_cmds.names, main_cmds.cnt,
|
qsort(main_cmds.names, main_cmds.cnt,
|
||||||
sizeof(main_cmds.names), cmdname_compare);
|
sizeof(main_cmds.names), cmdname_compare);
|
||||||
uniq(&main_cmds);
|
uniq(&main_cmds);
|
||||||
@ -99,6 +113,6 @@ const char *help_unknown_cmd(const char *cmd)
|
|||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
|
fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
|
||||||
}
|
}
|
||||||
|
end:
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -643,20 +643,20 @@ static int pmu_resolve_param_term(struct parse_events_term *term,
|
|||||||
static char *pmu_formats_string(struct list_head *formats)
|
static char *pmu_formats_string(struct list_head *formats)
|
||||||
{
|
{
|
||||||
struct perf_pmu_format *format;
|
struct perf_pmu_format *format;
|
||||||
char *str;
|
char *str = NULL;
|
||||||
struct strbuf buf;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
|
|
||||||
if (!formats)
|
if (!formats)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
strbuf_init(&buf, 0);
|
|
||||||
/* sysfs exported terms */
|
/* sysfs exported terms */
|
||||||
list_for_each_entry(format, formats, list)
|
list_for_each_entry(format, formats, list)
|
||||||
strbuf_addf(&buf, i++ ? ",%s" : "%s",
|
if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0)
|
||||||
format->name);
|
goto error;
|
||||||
|
|
||||||
str = strbuf_detach(&buf, NULL);
|
str = strbuf_detach(&buf, NULL);
|
||||||
|
error:
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
|
@ -1677,28 +1677,37 @@ char *synthesize_perf_probe_arg(struct perf_probe_arg *pa)
|
|||||||
{
|
{
|
||||||
struct perf_probe_arg_field *field = pa->field;
|
struct perf_probe_arg_field *field = pa->field;
|
||||||
struct strbuf buf;
|
struct strbuf buf;
|
||||||
char *ret;
|
char *ret = NULL;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (strbuf_init(&buf, 64) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
strbuf_init(&buf, 64);
|
|
||||||
if (pa->name && pa->var)
|
if (pa->name && pa->var)
|
||||||
strbuf_addf(&buf, "%s=%s", pa->name, pa->var);
|
err = strbuf_addf(&buf, "%s=%s", pa->name, pa->var);
|
||||||
else
|
else
|
||||||
strbuf_addstr(&buf, pa->name ?: pa->var);
|
err = strbuf_addstr(&buf, pa->name ?: pa->var);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
while (field) {
|
while (field) {
|
||||||
if (field->name[0] == '[')
|
if (field->name[0] == '[')
|
||||||
strbuf_addstr(&buf, field->name);
|
err = strbuf_addstr(&buf, field->name);
|
||||||
else
|
else
|
||||||
strbuf_addf(&buf, "%s%s", field->ref ? "->" : ".",
|
err = strbuf_addf(&buf, "%s%s", field->ref ? "->" : ".",
|
||||||
field->name);
|
field->name);
|
||||||
field = field->next;
|
field = field->next;
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pa->type)
|
if (pa->type)
|
||||||
strbuf_addf(&buf, ":%s", pa->type);
|
if (strbuf_addf(&buf, ":%s", pa->type) < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
ret = strbuf_detach(&buf, NULL);
|
ret = strbuf_detach(&buf, NULL);
|
||||||
|
out:
|
||||||
|
strbuf_release(&buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1706,18 +1715,23 @@ char *synthesize_perf_probe_arg(struct perf_probe_arg *pa)
|
|||||||
static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
|
static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
|
||||||
{
|
{
|
||||||
struct strbuf buf;
|
struct strbuf buf;
|
||||||
char *tmp;
|
char *tmp, *ret = NULL;
|
||||||
int len;
|
int len, err = 0;
|
||||||
|
|
||||||
|
if (strbuf_init(&buf, 64) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
strbuf_init(&buf, 64);
|
|
||||||
if (pp->function) {
|
if (pp->function) {
|
||||||
strbuf_addstr(&buf, pp->function);
|
if (strbuf_addstr(&buf, pp->function) < 0)
|
||||||
|
goto out;
|
||||||
if (pp->offset)
|
if (pp->offset)
|
||||||
strbuf_addf(&buf, "+%lu", pp->offset);
|
err = strbuf_addf(&buf, "+%lu", pp->offset);
|
||||||
else if (pp->line)
|
else if (pp->line)
|
||||||
strbuf_addf(&buf, ":%d", pp->line);
|
err = strbuf_addf(&buf, ":%d", pp->line);
|
||||||
else if (pp->retprobe)
|
else if (pp->retprobe)
|
||||||
strbuf_addstr(&buf, "%return");
|
err = strbuf_addstr(&buf, "%return");
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
if (pp->file) {
|
if (pp->file) {
|
||||||
tmp = pp->file;
|
tmp = pp->file;
|
||||||
@ -1726,12 +1740,15 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
|
|||||||
tmp = strchr(pp->file + len - 30, '/');
|
tmp = strchr(pp->file + len - 30, '/');
|
||||||
tmp = tmp ? tmp + 1 : pp->file + len - 30;
|
tmp = tmp ? tmp + 1 : pp->file + len - 30;
|
||||||
}
|
}
|
||||||
strbuf_addf(&buf, "@%s", tmp);
|
err = strbuf_addf(&buf, "@%s", tmp);
|
||||||
if (!pp->function && pp->line)
|
if (!err && !pp->function && pp->line)
|
||||||
strbuf_addf(&buf, ":%d", pp->line);
|
err = strbuf_addf(&buf, ":%d", pp->line);
|
||||||
}
|
}
|
||||||
|
if (!err)
|
||||||
return strbuf_detach(&buf, NULL);
|
ret = strbuf_detach(&buf, NULL);
|
||||||
|
out:
|
||||||
|
strbuf_release(&buf);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -1762,28 +1779,30 @@ char *synthesize_perf_probe_command(struct perf_probe_event *pev)
|
|||||||
static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
|
static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
|
||||||
struct strbuf *buf, int depth)
|
struct strbuf *buf, int depth)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
if (ref->next) {
|
if (ref->next) {
|
||||||
depth = __synthesize_probe_trace_arg_ref(ref->next, buf,
|
depth = __synthesize_probe_trace_arg_ref(ref->next, buf,
|
||||||
depth + 1);
|
depth + 1);
|
||||||
if (depth < 0)
|
if (depth < 0)
|
||||||
goto out;
|
return depth;
|
||||||
}
|
}
|
||||||
strbuf_addf(buf, "%+ld(", ref->offset);
|
err = strbuf_addf(buf, "%+ld(", ref->offset);
|
||||||
out:
|
return (err < 0) ? err : depth;
|
||||||
return depth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
|
static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
|
||||||
struct strbuf *buf)
|
struct strbuf *buf)
|
||||||
{
|
{
|
||||||
struct probe_trace_arg_ref *ref = arg->ref;
|
struct probe_trace_arg_ref *ref = arg->ref;
|
||||||
int depth = 0;
|
int depth = 0, err;
|
||||||
|
|
||||||
/* Argument name or separator */
|
/* Argument name or separator */
|
||||||
if (arg->name)
|
if (arg->name)
|
||||||
strbuf_addf(buf, " %s=", arg->name);
|
err = strbuf_addf(buf, " %s=", arg->name);
|
||||||
else
|
else
|
||||||
strbuf_addch(buf, ' ');
|
err = strbuf_addch(buf, ' ');
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
/* Special case: @XXX */
|
/* Special case: @XXX */
|
||||||
if (arg->value[0] == '@' && arg->ref)
|
if (arg->value[0] == '@' && arg->ref)
|
||||||
@ -1798,18 +1817,19 @@ static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
|
|||||||
|
|
||||||
/* Print argument value */
|
/* Print argument value */
|
||||||
if (arg->value[0] == '@' && arg->ref)
|
if (arg->value[0] == '@' && arg->ref)
|
||||||
strbuf_addf(buf, "%s%+ld", arg->value, arg->ref->offset);
|
err = strbuf_addf(buf, "%s%+ld", arg->value, arg->ref->offset);
|
||||||
else
|
else
|
||||||
strbuf_addstr(buf, arg->value);
|
err = strbuf_addstr(buf, arg->value);
|
||||||
|
|
||||||
/* Closing */
|
/* Closing */
|
||||||
while (depth--)
|
while (!err && depth--)
|
||||||
strbuf_addch(buf, ')');
|
err = strbuf_addch(buf, ')');
|
||||||
/* Print argument type */
|
|
||||||
if (arg->type)
|
|
||||||
strbuf_addf(buf, ":%s", arg->type);
|
|
||||||
|
|
||||||
return 0;
|
/* Print argument type */
|
||||||
|
if (!err && arg->type)
|
||||||
|
err = strbuf_addf(buf, ":%s", arg->type);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *synthesize_probe_trace_command(struct probe_trace_event *tev)
|
char *synthesize_probe_trace_command(struct probe_trace_event *tev)
|
||||||
@ -1817,15 +1837,18 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
|
|||||||
struct probe_trace_point *tp = &tev->point;
|
struct probe_trace_point *tp = &tev->point;
|
||||||
struct strbuf buf;
|
struct strbuf buf;
|
||||||
char *ret = NULL;
|
char *ret = NULL;
|
||||||
int i;
|
int i, err;
|
||||||
|
|
||||||
/* Uprobes must have tp->module */
|
/* Uprobes must have tp->module */
|
||||||
if (tev->uprobes && !tp->module)
|
if (tev->uprobes && !tp->module)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
strbuf_init(&buf, 32);
|
if (strbuf_init(&buf, 32) < 0)
|
||||||
strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
|
return NULL;
|
||||||
tev->group, tev->event);
|
|
||||||
|
if (strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
|
||||||
|
tev->group, tev->event) < 0)
|
||||||
|
goto error;
|
||||||
/*
|
/*
|
||||||
* If tp->address == 0, then this point must be a
|
* If tp->address == 0, then this point must be a
|
||||||
* absolute address uprobe.
|
* absolute address uprobe.
|
||||||
@ -1839,14 +1862,16 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
|
|||||||
|
|
||||||
/* Use the tp->address for uprobes */
|
/* Use the tp->address for uprobes */
|
||||||
if (tev->uprobes)
|
if (tev->uprobes)
|
||||||
strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address);
|
err = strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address);
|
||||||
else if (!strncmp(tp->symbol, "0x", 2))
|
else if (!strncmp(tp->symbol, "0x", 2))
|
||||||
/* Absolute address. See try_to_find_absolute_address() */
|
/* Absolute address. See try_to_find_absolute_address() */
|
||||||
strbuf_addf(&buf, "%s%s0x%lx", tp->module ?: "",
|
err = strbuf_addf(&buf, "%s%s0x%lx", tp->module ?: "",
|
||||||
tp->module ? ":" : "", tp->address);
|
tp->module ? ":" : "", tp->address);
|
||||||
else
|
else
|
||||||
strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "",
|
err = strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "",
|
||||||
tp->module ? ":" : "", tp->symbol, tp->offset);
|
tp->module ? ":" : "", tp->symbol, tp->offset);
|
||||||
|
if (err)
|
||||||
|
goto error;
|
||||||
|
|
||||||
for (i = 0; i < tev->nargs; i++)
|
for (i = 0; i < tev->nargs; i++)
|
||||||
if (synthesize_probe_trace_arg(&tev->args[i], &buf) < 0)
|
if (synthesize_probe_trace_arg(&tev->args[i], &buf) < 0)
|
||||||
@ -1960,14 +1985,15 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
|
|||||||
if (tev->args[i].name)
|
if (tev->args[i].name)
|
||||||
pev->args[i].name = strdup(tev->args[i].name);
|
pev->args[i].name = strdup(tev->args[i].name);
|
||||||
else {
|
else {
|
||||||
strbuf_init(&buf, 32);
|
if ((ret = strbuf_init(&buf, 32)) < 0)
|
||||||
|
goto error;
|
||||||
ret = synthesize_probe_trace_arg(&tev->args[i], &buf);
|
ret = synthesize_probe_trace_arg(&tev->args[i], &buf);
|
||||||
pev->args[i].name = strbuf_detach(&buf, NULL);
|
pev->args[i].name = strbuf_detach(&buf, NULL);
|
||||||
}
|
}
|
||||||
if (pev->args[i].name == NULL && ret >= 0)
|
if (pev->args[i].name == NULL && ret >= 0)
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
}
|
}
|
||||||
|
error:
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
clear_perf_probe_event(pev);
|
clear_perf_probe_event(pev);
|
||||||
|
|
||||||
@ -2140,37 +2166,40 @@ static int perf_probe_event__sprintf(const char *group, const char *event,
|
|||||||
const char *module,
|
const char *module,
|
||||||
struct strbuf *result)
|
struct strbuf *result)
|
||||||
{
|
{
|
||||||
int i;
|
int i, ret;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
if (asprintf(&buf, "%s:%s", group, event) < 0)
|
if (asprintf(&buf, "%s:%s", group, event) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
strbuf_addf(result, " %-20s (on ", buf);
|
ret = strbuf_addf(result, " %-20s (on ", buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* Synthesize only event probe point */
|
/* Synthesize only event probe point */
|
||||||
buf = synthesize_perf_probe_point(&pev->point);
|
buf = synthesize_perf_probe_point(&pev->point);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
strbuf_addstr(result, buf);
|
ret = strbuf_addstr(result, buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
if (module)
|
if (!ret && module)
|
||||||
strbuf_addf(result, " in %s", module);
|
ret = strbuf_addf(result, " in %s", module);
|
||||||
|
|
||||||
if (pev->nargs > 0) {
|
if (!ret && pev->nargs > 0) {
|
||||||
strbuf_add(result, " with", 5);
|
ret = strbuf_add(result, " with", 5);
|
||||||
for (i = 0; i < pev->nargs; i++) {
|
for (i = 0; !ret && i < pev->nargs; i++) {
|
||||||
buf = synthesize_perf_probe_arg(&pev->args[i]);
|
buf = synthesize_perf_probe_arg(&pev->args[i]);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
strbuf_addf(result, " %s", buf);
|
ret = strbuf_addf(result, " %s", buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strbuf_addch(result, ')');
|
if (!ret)
|
||||||
|
ret = strbuf_addch(result, ')');
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show an event */
|
/* Show an event */
|
||||||
|
@ -1294,6 +1294,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
|
|||||||
{
|
{
|
||||||
struct available_var_finder *af = data;
|
struct available_var_finder *af = data;
|
||||||
struct variable_list *vl;
|
struct variable_list *vl;
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
int tag, ret;
|
int tag, ret;
|
||||||
|
|
||||||
vl = &af->vls[af->nvls - 1];
|
vl = &af->vls[af->nvls - 1];
|
||||||
@ -1307,25 +1308,26 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
|
|||||||
if (ret == 0 || ret == -ERANGE) {
|
if (ret == 0 || ret == -ERANGE) {
|
||||||
int ret2;
|
int ret2;
|
||||||
bool externs = !af->child;
|
bool externs = !af->child;
|
||||||
struct strbuf buf;
|
|
||||||
|
|
||||||
strbuf_init(&buf, 64);
|
if (strbuf_init(&buf, 64) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (probe_conf.show_location_range) {
|
if (probe_conf.show_location_range) {
|
||||||
if (!externs) {
|
if (!externs)
|
||||||
if (ret)
|
ret2 = strbuf_add(&buf,
|
||||||
strbuf_add(&buf, "[INV]\t", 6);
|
ret ? "[INV]\t" : "[VAL]\t", 6);
|
||||||
else
|
else
|
||||||
strbuf_add(&buf, "[VAL]\t", 6);
|
ret2 = strbuf_add(&buf, "[EXT]\t", 6);
|
||||||
} else
|
if (ret2)
|
||||||
strbuf_add(&buf, "[EXT]\t", 6);
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret2 = die_get_varname(die_mem, &buf);
|
ret2 = die_get_varname(die_mem, &buf);
|
||||||
|
|
||||||
if (!ret2 && probe_conf.show_location_range &&
|
if (!ret2 && probe_conf.show_location_range &&
|
||||||
!externs) {
|
!externs) {
|
||||||
strbuf_addch(&buf, '\t');
|
if (strbuf_addch(&buf, '\t') < 0)
|
||||||
|
goto error;
|
||||||
ret2 = die_get_var_range(&af->pf.sp_die,
|
ret2 = die_get_var_range(&af->pf.sp_die,
|
||||||
die_mem, &buf);
|
die_mem, &buf);
|
||||||
}
|
}
|
||||||
@ -1334,8 +1336,8 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
|
|||||||
if (ret2 == 0) {
|
if (ret2 == 0) {
|
||||||
strlist__add(vl->vars,
|
strlist__add(vl->vars,
|
||||||
strbuf_detach(&buf, NULL));
|
strbuf_detach(&buf, NULL));
|
||||||
} else
|
}
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1343,6 +1345,10 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
|
|||||||
return DIE_FIND_CB_CONTINUE;
|
return DIE_FIND_CB_CONTINUE;
|
||||||
else
|
else
|
||||||
return DIE_FIND_CB_SIBLING;
|
return DIE_FIND_CB_SIBLING;
|
||||||
|
error:
|
||||||
|
strbuf_release(&buf);
|
||||||
|
pr_debug("Error in strbuf\n");
|
||||||
|
return DIE_FIND_CB_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a found vars into available variables list */
|
/* Add a found vars into available variables list */
|
||||||
|
@ -17,38 +17,42 @@ static inline int need_bs_quote(char c)
|
|||||||
return (c == '\'' || c == '!');
|
return (c == '\'' || c == '!');
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sq_quote_buf(struct strbuf *dst, const char *src)
|
static int sq_quote_buf(struct strbuf *dst, const char *src)
|
||||||
{
|
{
|
||||||
char *to_free = NULL;
|
char *to_free = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (dst->buf == src)
|
if (dst->buf == src)
|
||||||
to_free = strbuf_detach(dst, NULL);
|
to_free = strbuf_detach(dst, NULL);
|
||||||
|
|
||||||
strbuf_addch(dst, '\'');
|
ret = strbuf_addch(dst, '\'');
|
||||||
while (*src) {
|
while (!ret && *src) {
|
||||||
size_t len = strcspn(src, "'!");
|
size_t len = strcspn(src, "'!");
|
||||||
strbuf_add(dst, src, len);
|
ret = strbuf_add(dst, src, len);
|
||||||
src += len;
|
src += len;
|
||||||
while (need_bs_quote(*src)) {
|
while (!ret && need_bs_quote(*src))
|
||||||
strbuf_addstr(dst, "'\\");
|
ret = strbuf_addf(dst, "'\\%c\'", *src++);
|
||||||
strbuf_addch(dst, *src++);
|
|
||||||
strbuf_addch(dst, '\'');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
strbuf_addch(dst, '\'');
|
if (!ret)
|
||||||
|
ret = strbuf_addch(dst, '\'');
|
||||||
free(to_free);
|
free(to_free);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
|
int sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
|
||||||
{
|
{
|
||||||
int i;
|
int i, ret;
|
||||||
|
|
||||||
/* Copy into destination buffer. */
|
/* Copy into destination buffer. */
|
||||||
strbuf_grow(dst, 255);
|
ret = strbuf_grow(dst, 255);
|
||||||
for (i = 0; argv[i]; ++i) {
|
for (i = 0; !ret && argv[i]; ++i) {
|
||||||
strbuf_addch(dst, ' ');
|
ret = strbuf_addch(dst, ' ');
|
||||||
sq_quote_buf(dst, argv[i]);
|
if (ret)
|
||||||
|
break;
|
||||||
|
ret = sq_quote_buf(dst, argv[i]);
|
||||||
if (maxlen && dst->len > maxlen)
|
if (maxlen && dst->len > maxlen)
|
||||||
die("Too many or long arguments");
|
die("Too many or long arguments");
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,6 @@
|
|||||||
* sq_quote() in a real application.
|
* sq_quote() in a real application.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen);
|
int sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen);
|
||||||
|
|
||||||
#endif /* __PERF_QUOTE_H */
|
#endif /* __PERF_QUOTE_H */
|
||||||
|
@ -1062,7 +1062,7 @@ static void set_table_handlers(struct tables *tables)
|
|||||||
tables->dbe.cpr = call_path_root__new();
|
tables->dbe.cpr = call_path_root__new();
|
||||||
|
|
||||||
if (!tables->dbe.cpr)
|
if (!tables->dbe.cpr)
|
||||||
Py_FatalError("failed to create calls processor");
|
Py_FatalError("failed to create call path root");
|
||||||
}
|
}
|
||||||
|
|
||||||
tables->db_export_mode = true;
|
tables->db_export_mode = true;
|
||||||
|
@ -307,6 +307,7 @@ int perf_stat_process_counter(struct perf_stat_config *config,
|
|||||||
struct perf_counts_values *aggr = &counter->counts->aggr;
|
struct perf_counts_values *aggr = &counter->counts->aggr;
|
||||||
struct perf_stat_evsel *ps = counter->priv;
|
struct perf_stat_evsel *ps = counter->priv;
|
||||||
u64 *count = counter->counts->aggr.values;
|
u64 *count = counter->counts->aggr.values;
|
||||||
|
u64 val;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
aggr->val = aggr->ena = aggr->run = 0;
|
aggr->val = aggr->ena = aggr->run = 0;
|
||||||
@ -346,7 +347,8 @@ int perf_stat_process_counter(struct perf_stat_config *config,
|
|||||||
/*
|
/*
|
||||||
* Save the full runtime - to allow normalization during printout:
|
* Save the full runtime - to allow normalization during printout:
|
||||||
*/
|
*/
|
||||||
perf_stat__update_shadow_stats(counter, count, 0);
|
val = counter->scale * *count;
|
||||||
|
perf_stat__update_shadow_stats(counter, &val, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "debug.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
|
||||||
@ -17,12 +18,13 @@ int prefixcmp(const char *str, const char *prefix)
|
|||||||
*/
|
*/
|
||||||
char strbuf_slopbuf[1];
|
char strbuf_slopbuf[1];
|
||||||
|
|
||||||
void strbuf_init(struct strbuf *sb, ssize_t hint)
|
int strbuf_init(struct strbuf *sb, ssize_t hint)
|
||||||
{
|
{
|
||||||
sb->alloc = sb->len = 0;
|
sb->alloc = sb->len = 0;
|
||||||
sb->buf = strbuf_slopbuf;
|
sb->buf = strbuf_slopbuf;
|
||||||
if (hint)
|
if (hint)
|
||||||
strbuf_grow(sb, hint);
|
return strbuf_grow(sb, hint);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void strbuf_release(struct strbuf *sb)
|
void strbuf_release(struct strbuf *sb)
|
||||||
@ -42,67 +44,104 @@ char *strbuf_detach(struct strbuf *sb, size_t *sz)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void strbuf_grow(struct strbuf *sb, size_t extra)
|
int strbuf_grow(struct strbuf *sb, size_t extra)
|
||||||
{
|
{
|
||||||
if (sb->len + extra + 1 <= sb->len)
|
char *buf;
|
||||||
die("you want to use way too much memory");
|
size_t nr = sb->len + extra + 1;
|
||||||
if (!sb->alloc)
|
|
||||||
sb->buf = NULL;
|
if (nr < sb->alloc)
|
||||||
ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
|
return 0;
|
||||||
|
|
||||||
|
if (nr <= sb->len)
|
||||||
|
return -E2BIG;
|
||||||
|
|
||||||
|
if (alloc_nr(sb->alloc) > nr)
|
||||||
|
nr = alloc_nr(sb->alloc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that sb->buf == strbuf_slopbuf if sb->alloc == 0, and it is
|
||||||
|
* a static variable. Thus we have to avoid passing it to realloc.
|
||||||
|
*/
|
||||||
|
buf = realloc(sb->alloc ? sb->buf : NULL, nr * sizeof(*buf));
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
sb->buf = buf;
|
||||||
|
sb->alloc = nr;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void strbuf_addch(struct strbuf *sb, int c)
|
int strbuf_addch(struct strbuf *sb, int c)
|
||||||
{
|
{
|
||||||
strbuf_grow(sb, 1);
|
int ret = strbuf_grow(sb, 1);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
sb->buf[sb->len++] = c;
|
sb->buf[sb->len++] = c;
|
||||||
sb->buf[sb->len] = '\0';
|
sb->buf[sb->len] = '\0';
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void strbuf_add(struct strbuf *sb, const void *data, size_t len)
|
int strbuf_add(struct strbuf *sb, const void *data, size_t len)
|
||||||
{
|
{
|
||||||
strbuf_grow(sb, len);
|
int ret = strbuf_grow(sb, len);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
memcpy(sb->buf + sb->len, data, len);
|
memcpy(sb->buf + sb->len, data, len);
|
||||||
strbuf_setlen(sb, sb->len + len);
|
return strbuf_setlen(sb, sb->len + len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
|
static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
int len;
|
int len, ret;
|
||||||
va_list ap_saved;
|
va_list ap_saved;
|
||||||
|
|
||||||
if (!strbuf_avail(sb))
|
if (!strbuf_avail(sb)) {
|
||||||
strbuf_grow(sb, 64);
|
ret = strbuf_grow(sb, 64);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
va_copy(ap_saved, ap);
|
va_copy(ap_saved, ap);
|
||||||
len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
|
len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
die("your vsnprintf is broken");
|
return len;
|
||||||
if (len > strbuf_avail(sb)) {
|
if (len > strbuf_avail(sb)) {
|
||||||
strbuf_grow(sb, len);
|
ret = strbuf_grow(sb, len);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
|
len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
|
||||||
va_end(ap_saved);
|
va_end(ap_saved);
|
||||||
if (len > strbuf_avail(sb)) {
|
if (len > strbuf_avail(sb)) {
|
||||||
die("this should not happen, your vsnprintf is broken");
|
pr_debug("this should not happen, your vsnprintf is broken");
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strbuf_setlen(sb, sb->len + len);
|
return strbuf_setlen(sb, sb->len + len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
|
int strbuf_addf(struct strbuf *sb, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
strbuf_addv(sb, fmt, ap);
|
ret = strbuf_addv(sb, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
|
ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
|
||||||
{
|
{
|
||||||
size_t oldlen = sb->len;
|
size_t oldlen = sb->len;
|
||||||
size_t oldalloc = sb->alloc;
|
size_t oldalloc = sb->alloc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = strbuf_grow(sb, hint ? hint : 8192);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
strbuf_grow(sb, hint ? hint : 8192);
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ssize_t cnt;
|
ssize_t cnt;
|
||||||
|
|
||||||
@ -112,12 +151,14 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
|
|||||||
strbuf_release(sb);
|
strbuf_release(sb);
|
||||||
else
|
else
|
||||||
strbuf_setlen(sb, oldlen);
|
strbuf_setlen(sb, oldlen);
|
||||||
return -1;
|
return cnt;
|
||||||
}
|
}
|
||||||
if (!cnt)
|
if (!cnt)
|
||||||
break;
|
break;
|
||||||
sb->len += cnt;
|
sb->len += cnt;
|
||||||
strbuf_grow(sb, 8192);
|
ret = strbuf_grow(sb, 8192);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sb->buf[sb->len] = '\0';
|
sb->buf[sb->len] = '\0';
|
||||||
|
@ -51,7 +51,7 @@ struct strbuf {
|
|||||||
#define STRBUF_INIT { 0, 0, strbuf_slopbuf }
|
#define STRBUF_INIT { 0, 0, strbuf_slopbuf }
|
||||||
|
|
||||||
/*----- strbuf life cycle -----*/
|
/*----- strbuf life cycle -----*/
|
||||||
void strbuf_init(struct strbuf *buf, ssize_t hint);
|
int strbuf_init(struct strbuf *buf, ssize_t hint);
|
||||||
void strbuf_release(struct strbuf *buf);
|
void strbuf_release(struct strbuf *buf);
|
||||||
char *strbuf_detach(struct strbuf *buf, size_t *);
|
char *strbuf_detach(struct strbuf *buf, size_t *);
|
||||||
|
|
||||||
@ -60,26 +60,31 @@ static inline ssize_t strbuf_avail(const struct strbuf *sb) {
|
|||||||
return sb->alloc ? sb->alloc - sb->len - 1 : 0;
|
return sb->alloc ? sb->alloc - sb->len - 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void strbuf_grow(struct strbuf *buf, size_t);
|
int strbuf_grow(struct strbuf *buf, size_t);
|
||||||
|
|
||||||
static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
|
static inline int strbuf_setlen(struct strbuf *sb, size_t len) {
|
||||||
if (!sb->alloc)
|
int ret;
|
||||||
strbuf_grow(sb, 0);
|
if (!sb->alloc) {
|
||||||
|
ret = strbuf_grow(sb, 0);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
assert(len < sb->alloc);
|
assert(len < sb->alloc);
|
||||||
sb->len = len;
|
sb->len = len;
|
||||||
sb->buf[len] = '\0';
|
sb->buf[len] = '\0';
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----- add data in your buffer -----*/
|
/*----- add data in your buffer -----*/
|
||||||
void strbuf_addch(struct strbuf *sb, int c);
|
int strbuf_addch(struct strbuf *sb, int c);
|
||||||
|
|
||||||
void strbuf_add(struct strbuf *buf, const void *, size_t);
|
int strbuf_add(struct strbuf *buf, const void *, size_t);
|
||||||
static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
|
static inline int strbuf_addstr(struct strbuf *sb, const char *s) {
|
||||||
strbuf_add(sb, s, strlen(s));
|
return strbuf_add(sb, s, strlen(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((format(printf,2,3)))
|
__attribute__((format(printf,2,3)))
|
||||||
void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
|
int strbuf_addf(struct strbuf *sb, const char *fmt, ...);
|
||||||
|
|
||||||
/* XXX: if read fails, any partial read is undone */
|
/* XXX: if read fails, any partial read is undone */
|
||||||
ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
|
ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
|
||||||
|
@ -301,7 +301,7 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
|
|||||||
|
|
||||||
if (ip < s->start)
|
if (ip < s->start)
|
||||||
n = n->rb_left;
|
n = n->rb_left;
|
||||||
else if (ip >= s->end)
|
else if (ip > s->end || (ip == s->end && ip != s->start))
|
||||||
n = n->rb_right;
|
n = n->rb_right;
|
||||||
else
|
else
|
||||||
return s;
|
return s;
|
||||||
|
@ -507,7 +507,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param)
|
|||||||
"needed for --call-graph fp\n");
|
"needed for --call-graph fp\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef HAVE_DWARF_UNWIND_SUPPORT
|
|
||||||
/* Dwarf style */
|
/* Dwarf style */
|
||||||
} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
|
} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
|
||||||
const unsigned long default_stack_dump_size = 8192;
|
const unsigned long default_stack_dump_size = 8192;
|
||||||
@ -523,7 +522,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param)
|
|||||||
ret = get_stack_size(tok, &size);
|
ret = get_stack_size(tok, &size);
|
||||||
param->dump_size = size;
|
param->dump_size = size;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_DWARF_UNWIND_SUPPORT */
|
|
||||||
} else if (!strncmp(name, "lbr", sizeof("lbr"))) {
|
} else if (!strncmp(name, "lbr", sizeof("lbr"))) {
|
||||||
if (!strtok_r(NULL, ",", &saveptr)) {
|
if (!strtok_r(NULL, ",", &saveptr)) {
|
||||||
param->record_mode = CALLCHAIN_LBR;
|
param->record_mode = CALLCHAIN_LBR;
|
||||||
|
@ -160,12 +160,6 @@ static inline char *gitstrchrnul(const char *s, int c)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Wrappers:
|
|
||||||
*/
|
|
||||||
void *xrealloc(void *ptr, size_t size) __attribute__((weak));
|
|
||||||
|
|
||||||
|
|
||||||
static inline void *zalloc(size_t size)
|
static inline void *zalloc(size_t size)
|
||||||
{
|
{
|
||||||
return calloc(1, size);
|
return calloc(1, size);
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Various trivial helper wrappers around standard functions
|
|
||||||
*/
|
|
||||||
#include "cache.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* There's no pack memory to release - but stay close to the Git
|
|
||||||
* version so wrap this away:
|
|
||||||
*/
|
|
||||||
static inline void release_pack_memory(size_t size __maybe_unused,
|
|
||||||
int flag __maybe_unused)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void *xrealloc(void *ptr, size_t size)
|
|
||||||
{
|
|
||||||
void *ret = realloc(ptr, size);
|
|
||||||
if (!ret && !size)
|
|
||||||
ret = realloc(ptr, 1);
|
|
||||||
if (!ret) {
|
|
||||||
release_pack_memory(size, -1);
|
|
||||||
ret = realloc(ptr, size);
|
|
||||||
if (!ret && !size)
|
|
||||||
ret = realloc(ptr, 1);
|
|
||||||
if (!ret)
|
|
||||||
die("Out of memory, realloc failed");
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user