summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-kvm.c2
-rw-r--r--tools/perf/util/session.c29
-rw-r--r--tools/perf/util/session.h3
3 files changed, 30 insertions, 4 deletions
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 258a5274099d..7ccceadcd9f8 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -732,7 +732,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
return -1;
}
- err = perf_session_queue_event(kvm->session, event, &sample, 0);
+ err = perf_session_queue_event(kvm->session, event, &kvm->tool, &sample, 0);
/*
* FIXME: Here we can't consume the event, as perf_session_queue_event will
* point to it, and it'll get possibly overwritten by the kernel.
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 8d4538c91076..bd2483b6b446 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -14,6 +14,7 @@
#include "util.h"
#include "cpumap.h"
#include "perf_regs.h"
+#include "asm/bug.h"
static int perf_session__open(struct perf_session *session)
{
@@ -456,6 +457,7 @@ struct ordered_event {
enum oe_flush {
OE_FLUSH__FINAL,
OE_FLUSH__ROUND,
+ OE_FLUSH__HALF,
};
static void perf_session_free_sample_buffers(struct perf_session *session)
@@ -637,6 +639,23 @@ static int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
oe->next_flush = ULLONG_MAX;
break;
+ case OE_FLUSH__HALF:
+ {
+ struct ordered_event *first, *last;
+ struct list_head *head = &oe->events;
+
+ first = list_entry(head->next, struct ordered_event, list);
+ last = oe->last;
+
+ /* Warn if we are called before any event got allocated. */
+ if (WARN_ONCE(!last || list_empty(head), "empty queue"))
+ return 0;
+
+ oe->next_flush = first->timestamp;
+ oe->next_flush += (last->timestamp - first->timestamp) / 2;
+ break;
+ }
+
case OE_FLUSH__ROUND:
default:
break;
@@ -699,7 +718,8 @@ static int process_finished_round(struct perf_tool *tool,
}
int perf_session_queue_event(struct perf_session *s, union perf_event *event,
- struct perf_sample *sample, u64 file_offset)
+ struct perf_tool *tool, struct perf_sample *sample,
+ u64 file_offset)
{
struct ordered_events *oe = &s->ordered_events;
u64 timestamp = sample->time;
@@ -714,6 +734,11 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
}
new = ordered_events__new(oe, timestamp);
+ if (!new) {
+ ordered_events__flush(s, tool, OE_FLUSH__HALF);
+ new = ordered_events__new(oe, timestamp);
+ }
+
if (!new)
return -ENOMEM;
@@ -1121,7 +1146,7 @@ static s64 perf_session__process_event(struct perf_session *session,
return ret;
if (tool->ordered_events) {
- ret = perf_session_queue_event(session, event, &sample,
+ ret = perf_session_queue_event(session, event, tool, &sample,
file_offset);
if (ret != -ETIME)
return ret;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index e2fbaf2567e1..a09e3c8d825a 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -67,7 +67,8 @@ int perf_session__process_events(struct perf_session *session,
struct perf_tool *tool);
int perf_session_queue_event(struct perf_session *s, union perf_event *event,
- struct perf_sample *sample, u64 file_offset);
+ struct perf_tool *tool, struct perf_sample *sample,
+ u64 file_offset);
void perf_tool__fill_defaults(struct perf_tool *tool);