summaryrefslogtreecommitdiffstats
path: root/tools/perf/util/ordered-events.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-10-16 07:15:45 +0200
committerIngo Molnar <mingo@kernel.org>2014-10-16 07:15:45 +0200
commit71c62b24fe88e4d3f5470207426e94345ca94c83 (patch)
tree2e2abafb2a325803af41de4f50a399c06c270c7a /tools/perf/util/ordered-events.c
parentec4212d88a77eb6caec10777ddd629b702a5ebbd (diff)
parent673d659f5c5918b7ddbafebf1f129c9eb82973b4 (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: * Add a visual cue for toggle zeroing of samples in 'perf top' (Taeung Song) * Fix for double free in 'perf stat' when using some specific invalid command line combo (Yasser Shalabi) Infrastructure changes: * Add option to copy events when queuing for sorting across cpu buffers and enable it for 'perf kvm stat live', to avoid having events left in the queue pointing to the ring buffer be rewritten in high volume sessions. (Alexander Yarygin, improving work done by David Ahern): * Document sysfs events/ interfaces (Cody P Schafer) * Add support to new style format of kernel PMU event. (Kan Liang) * Fix typos in perf/Documentation (Masanari Iida) * Improve callchains when using libunwind (Namhyung Kim) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util/ordered-events.c')
-rw-r--r--tools/perf/util/ordered-events.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index 706ce1a6616..fd4be94125f 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -1,5 +1,6 @@
#include <linux/list.h>
#include <linux/compiler.h>
+#include <linux/string.h>
#include "ordered-events.h"
#include "evlist.h"
#include "session.h"
@@ -57,11 +58,45 @@ static void queue_event(struct ordered_events *oe, struct ordered_event *new)
}
}
+static union perf_event *__dup_event(struct ordered_events *oe,
+ union perf_event *event)
+{
+ union perf_event *new_event = NULL;
+
+ if (oe->cur_alloc_size < oe->max_alloc_size) {
+ new_event = memdup(event, event->header.size);
+ if (new_event)
+ oe->cur_alloc_size += event->header.size;
+ }
+
+ return new_event;
+}
+
+static union perf_event *dup_event(struct ordered_events *oe,
+ union perf_event *event)
+{
+ return oe->copy_on_queue ? __dup_event(oe, event) : event;
+}
+
+static void free_dup_event(struct ordered_events *oe, union perf_event *event)
+{
+ if (oe->copy_on_queue) {
+ oe->cur_alloc_size -= event->header.size;
+ free(event);
+ }
+}
+
#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event))
-static struct ordered_event *alloc_event(struct ordered_events *oe)
+static struct ordered_event *alloc_event(struct ordered_events *oe,
+ union perf_event *event)
{
struct list_head *cache = &oe->cache;
struct ordered_event *new = NULL;
+ union perf_event *new_event;
+
+ new_event = dup_event(oe, event);
+ if (!new_event)
+ return NULL;
if (!list_empty(cache)) {
new = list_entry(cache->next, struct ordered_event, list);
@@ -74,8 +109,10 @@ static struct ordered_event *alloc_event(struct ordered_events *oe)
size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
oe->buffer = malloc(size);
- if (!oe->buffer)
+ if (!oe->buffer) {
+ free_dup_event(oe, new_event);
return NULL;
+ }
pr("alloc size %" PRIu64 "B (+%zu), max %" PRIu64 "B\n",
oe->cur_alloc_size, size, oe->max_alloc_size);
@@ -90,15 +127,17 @@ static struct ordered_event *alloc_event(struct ordered_events *oe)
pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size);
}
+ new->event = new_event;
return new;
}
struct ordered_event *
-ordered_events__new(struct ordered_events *oe, u64 timestamp)
+ordered_events__new(struct ordered_events *oe, u64 timestamp,
+ union perf_event *event)
{
struct ordered_event *new;
- new = alloc_event(oe);
+ new = alloc_event(oe, event);
if (new) {
new->timestamp = timestamp;
queue_event(oe, new);
@@ -111,6 +150,7 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
{
list_move(&event->list, &oe->cache);
oe->nr_events--;
+ free_dup_event(oe, event->event);
}
static int __ordered_events__flush(struct perf_session *s,
@@ -240,6 +280,7 @@ void ordered_events__free(struct ordered_events *oe)
event = list_entry(oe->to_free.next, struct ordered_event, list);
list_del(&event->list);
+ free_dup_event(oe, event->event);
free(event);
}
}