diff options
Diffstat (limited to 'tools/perf/util/ordered-events.c')
-rw-r--r-- | tools/perf/util/ordered-events.c | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c index 706ce1a66169..fd4be94125fb 100644 --- a/tools/perf/util/ordered-events.c +++ b/tools/perf/util/ordered-events.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include <linux/list.h> | 1 | #include <linux/list.h> |
2 | #include <linux/compiler.h> | 2 | #include <linux/compiler.h> |
3 | #include <linux/string.h> | ||
3 | #include "ordered-events.h" | 4 | #include "ordered-events.h" |
4 | #include "evlist.h" | 5 | #include "evlist.h" |
5 | #include "session.h" | 6 | #include "session.h" |
@@ -57,11 +58,45 @@ static void queue_event(struct ordered_events *oe, struct ordered_event *new) | |||
57 | } | 58 | } |
58 | } | 59 | } |
59 | 60 | ||
61 | static union perf_event *__dup_event(struct ordered_events *oe, | ||
62 | union perf_event *event) | ||
63 | { | ||
64 | union perf_event *new_event = NULL; | ||
65 | |||
66 | if (oe->cur_alloc_size < oe->max_alloc_size) { | ||
67 | new_event = memdup(event, event->header.size); | ||
68 | if (new_event) | ||
69 | oe->cur_alloc_size += event->header.size; | ||
70 | } | ||
71 | |||
72 | return new_event; | ||
73 | } | ||
74 | |||
75 | static union perf_event *dup_event(struct ordered_events *oe, | ||
76 | union perf_event *event) | ||
77 | { | ||
78 | return oe->copy_on_queue ? __dup_event(oe, event) : event; | ||
79 | } | ||
80 | |||
81 | static void free_dup_event(struct ordered_events *oe, union perf_event *event) | ||
82 | { | ||
83 | if (oe->copy_on_queue) { | ||
84 | oe->cur_alloc_size -= event->header.size; | ||
85 | free(event); | ||
86 | } | ||
87 | } | ||
88 | |||
60 | #define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event)) | 89 | #define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event)) |
61 | static struct ordered_event *alloc_event(struct ordered_events *oe) | 90 | static struct ordered_event *alloc_event(struct ordered_events *oe, |
91 | union perf_event *event) | ||
62 | { | 92 | { |
63 | struct list_head *cache = &oe->cache; | 93 | struct list_head *cache = &oe->cache; |
64 | struct ordered_event *new = NULL; | 94 | struct ordered_event *new = NULL; |
95 | union perf_event *new_event; | ||
96 | |||
97 | new_event = dup_event(oe, event); | ||
98 | if (!new_event) | ||
99 | return NULL; | ||
65 | 100 | ||
66 | if (!list_empty(cache)) { | 101 | if (!list_empty(cache)) { |
67 | new = list_entry(cache->next, struct ordered_event, list); | 102 | new = list_entry(cache->next, struct ordered_event, list); |
@@ -74,8 +109,10 @@ static struct ordered_event *alloc_event(struct ordered_events *oe) | |||
74 | size_t size = MAX_SAMPLE_BUFFER * sizeof(*new); | 109 | size_t size = MAX_SAMPLE_BUFFER * sizeof(*new); |
75 | 110 | ||
76 | oe->buffer = malloc(size); | 111 | oe->buffer = malloc(size); |
77 | if (!oe->buffer) | 112 | if (!oe->buffer) { |
113 | free_dup_event(oe, new_event); | ||
78 | return NULL; | 114 | return NULL; |
115 | } | ||
79 | 116 | ||
80 | pr("alloc size %" PRIu64 "B (+%zu), max %" PRIu64 "B\n", | 117 | pr("alloc size %" PRIu64 "B (+%zu), max %" PRIu64 "B\n", |
81 | oe->cur_alloc_size, size, oe->max_alloc_size); | 118 | oe->cur_alloc_size, size, oe->max_alloc_size); |
@@ -90,15 +127,17 @@ static struct ordered_event *alloc_event(struct ordered_events *oe) | |||
90 | pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size); | 127 | pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size); |
91 | } | 128 | } |
92 | 129 | ||
130 | new->event = new_event; | ||
93 | return new; | 131 | return new; |
94 | } | 132 | } |
95 | 133 | ||
96 | struct ordered_event * | 134 | struct ordered_event * |
97 | ordered_events__new(struct ordered_events *oe, u64 timestamp) | 135 | ordered_events__new(struct ordered_events *oe, u64 timestamp, |
136 | union perf_event *event) | ||
98 | { | 137 | { |
99 | struct ordered_event *new; | 138 | struct ordered_event *new; |
100 | 139 | ||
101 | new = alloc_event(oe); | 140 | new = alloc_event(oe, event); |
102 | if (new) { | 141 | if (new) { |
103 | new->timestamp = timestamp; | 142 | new->timestamp = timestamp; |
104 | queue_event(oe, new); | 143 | queue_event(oe, new); |
@@ -111,6 +150,7 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve | |||
111 | { | 150 | { |
112 | list_move(&event->list, &oe->cache); | 151 | list_move(&event->list, &oe->cache); |
113 | oe->nr_events--; | 152 | oe->nr_events--; |
153 | free_dup_event(oe, event->event); | ||
114 | } | 154 | } |
115 | 155 | ||
116 | static int __ordered_events__flush(struct perf_session *s, | 156 | static int __ordered_events__flush(struct perf_session *s, |
@@ -240,6 +280,7 @@ void ordered_events__free(struct ordered_events *oe) | |||
240 | 280 | ||
241 | event = list_entry(oe->to_free.next, struct ordered_event, list); | 281 | event = list_entry(oe->to_free.next, struct ordered_event, list); |
242 | list_del(&event->list); | 282 | list_del(&event->list); |
283 | free_dup_event(oe, event->event); | ||
243 | free(event); | 284 | free(event); |
244 | } | 285 | } |
245 | } | 286 | } |