1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2a43783aeSArnaldo Carvalho de Melo #include <errno.h>
3fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
45f86b80bSJiri Olsa #include <linux/list.h>
5cee3ab9cSJiri Olsa #include <linux/compiler.h>
654bf53b1SAlexander Yarygin #include <linux/string.h>
75f86b80bSJiri Olsa #include "ordered-events.h"
85f86b80bSJiri Olsa #include "session.h"
95f86b80bSJiri Olsa #include "asm/bug.h"
105f86b80bSJiri Olsa #include "debug.h"
118520a98dSArnaldo Carvalho de Melo #include "ui/progress.h"
125f86b80bSJiri Olsa
13cee3ab9cSJiri Olsa #define pr_N(n, fmt, ...) \
14cee3ab9cSJiri Olsa eprintf(n, debug_ordered_events, fmt, ##__VA_ARGS__)
15cee3ab9cSJiri Olsa
16cee3ab9cSJiri Olsa #define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
17cee3ab9cSJiri Olsa
queue_event(struct ordered_events * oe,struct ordered_event * new)185f86b80bSJiri Olsa static void queue_event(struct ordered_events *oe, struct ordered_event *new)
195f86b80bSJiri Olsa {
205f86b80bSJiri Olsa struct ordered_event *last = oe->last;
215f86b80bSJiri Olsa u64 timestamp = new->timestamp;
225f86b80bSJiri Olsa struct list_head *p;
235f86b80bSJiri Olsa
245f86b80bSJiri Olsa ++oe->nr_events;
255f86b80bSJiri Olsa oe->last = new;
265f86b80bSJiri Olsa
27cee3ab9cSJiri Olsa pr_oe_time2(timestamp, "queue_event nr_events %u\n", oe->nr_events);
28cee3ab9cSJiri Olsa
295f86b80bSJiri Olsa if (!last) {
305f86b80bSJiri Olsa list_add(&new->list, &oe->events);
315f86b80bSJiri Olsa oe->max_timestamp = timestamp;
325f86b80bSJiri Olsa return;
335f86b80bSJiri Olsa }
345f86b80bSJiri Olsa
355f86b80bSJiri Olsa /*
365f86b80bSJiri Olsa * last event might point to some random place in the list as it's
375f86b80bSJiri Olsa * the last queued event. We expect that the new event is close to
385f86b80bSJiri Olsa * this.
395f86b80bSJiri Olsa */
405f86b80bSJiri Olsa if (last->timestamp <= timestamp) {
415f86b80bSJiri Olsa while (last->timestamp <= timestamp) {
425f86b80bSJiri Olsa p = last->list.next;
435f86b80bSJiri Olsa if (p == &oe->events) {
445f86b80bSJiri Olsa list_add_tail(&new->list, &oe->events);
455f86b80bSJiri Olsa oe->max_timestamp = timestamp;
465f86b80bSJiri Olsa return;
475f86b80bSJiri Olsa }
485f86b80bSJiri Olsa last = list_entry(p, struct ordered_event, list);
495f86b80bSJiri Olsa }
505f86b80bSJiri Olsa list_add_tail(&new->list, &last->list);
515f86b80bSJiri Olsa } else {
525f86b80bSJiri Olsa while (last->timestamp > timestamp) {
535f86b80bSJiri Olsa p = last->list.prev;
545f86b80bSJiri Olsa if (p == &oe->events) {
555f86b80bSJiri Olsa list_add(&new->list, &oe->events);
565f86b80bSJiri Olsa return;
575f86b80bSJiri Olsa }
585f86b80bSJiri Olsa last = list_entry(p, struct ordered_event, list);
595f86b80bSJiri Olsa }
605f86b80bSJiri Olsa list_add(&new->list, &last->list);
615f86b80bSJiri Olsa }
625f86b80bSJiri Olsa }
635f86b80bSJiri Olsa
__dup_event(struct ordered_events * oe,union perf_event * event)6454bf53b1SAlexander Yarygin static union perf_event *__dup_event(struct ordered_events *oe,
6554bf53b1SAlexander Yarygin union perf_event *event)
6654bf53b1SAlexander Yarygin {
6754bf53b1SAlexander Yarygin union perf_event *new_event = NULL;
6854bf53b1SAlexander Yarygin
6954bf53b1SAlexander Yarygin if (oe->cur_alloc_size < oe->max_alloc_size) {
7054bf53b1SAlexander Yarygin new_event = memdup(event, event->header.size);
7154bf53b1SAlexander Yarygin if (new_event)
7254bf53b1SAlexander Yarygin oe->cur_alloc_size += event->header.size;
7354bf53b1SAlexander Yarygin }
7454bf53b1SAlexander Yarygin
7554bf53b1SAlexander Yarygin return new_event;
7654bf53b1SAlexander Yarygin }
7754bf53b1SAlexander Yarygin
dup_event(struct ordered_events * oe,union perf_event * event)7854bf53b1SAlexander Yarygin static union perf_event *dup_event(struct ordered_events *oe,
7954bf53b1SAlexander Yarygin union perf_event *event)
8054bf53b1SAlexander Yarygin {
8154bf53b1SAlexander Yarygin return oe->copy_on_queue ? __dup_event(oe, event) : event;
8254bf53b1SAlexander Yarygin }
8354bf53b1SAlexander Yarygin
__free_dup_event(struct ordered_events * oe,union perf_event * event)84d5ceb62bSJiri Olsa static void __free_dup_event(struct ordered_events *oe, union perf_event *event)
8554bf53b1SAlexander Yarygin {
86d5ceb62bSJiri Olsa if (event) {
8754bf53b1SAlexander Yarygin oe->cur_alloc_size -= event->header.size;
8854bf53b1SAlexander Yarygin free(event);
8954bf53b1SAlexander Yarygin }
9054bf53b1SAlexander Yarygin }
9154bf53b1SAlexander Yarygin
free_dup_event(struct ordered_events * oe,union perf_event * event)92d5ceb62bSJiri Olsa static void free_dup_event(struct ordered_events *oe, union perf_event *event)
93d5ceb62bSJiri Olsa {
94d5ceb62bSJiri Olsa if (oe->copy_on_queue)
95d5ceb62bSJiri Olsa __free_dup_event(oe, event);
96d5ceb62bSJiri Olsa }
97d5ceb62bSJiri Olsa
985f86b80bSJiri Olsa #define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event))
alloc_event(struct ordered_events * oe,union perf_event * event)9954bf53b1SAlexander Yarygin static struct ordered_event *alloc_event(struct ordered_events *oe,
10054bf53b1SAlexander Yarygin union perf_event *event)
1015f86b80bSJiri Olsa {
1025f86b80bSJiri Olsa struct list_head *cache = &oe->cache;
1035f86b80bSJiri Olsa struct ordered_event *new = NULL;
10454bf53b1SAlexander Yarygin union perf_event *new_event;
10553da12e0SJiri Olsa size_t size;
10654bf53b1SAlexander Yarygin
10754bf53b1SAlexander Yarygin new_event = dup_event(oe, event);
10854bf53b1SAlexander Yarygin if (!new_event)
10954bf53b1SAlexander Yarygin return NULL;
1105f86b80bSJiri Olsa
111d5ceb62bSJiri Olsa /*
112d5ceb62bSJiri Olsa * We maintain the following scheme of buffers for ordered
113d5ceb62bSJiri Olsa * event allocation:
114d5ceb62bSJiri Olsa *
115d5ceb62bSJiri Olsa * to_free list -> buffer1 (64K)
116d5ceb62bSJiri Olsa * buffer2 (64K)
117d5ceb62bSJiri Olsa * ...
118d5ceb62bSJiri Olsa *
119d5ceb62bSJiri Olsa * Each buffer keeps an array of ordered events objects:
120d5ceb62bSJiri Olsa * buffer -> event[0]
121d5ceb62bSJiri Olsa * event[1]
122d5ceb62bSJiri Olsa * ...
123d5ceb62bSJiri Olsa *
124d5ceb62bSJiri Olsa * Each allocated ordered event is linked to one of
125d5ceb62bSJiri Olsa * following lists:
126d5ceb62bSJiri Olsa * - time ordered list 'events'
127d5ceb62bSJiri Olsa * - list of currently removed events 'cache'
128d5ceb62bSJiri Olsa *
129d5ceb62bSJiri Olsa * Allocation of the ordered event uses the following order
130d5ceb62bSJiri Olsa * to get the memory:
131d5ceb62bSJiri Olsa * - use recently removed object from 'cache' list
132d5ceb62bSJiri Olsa * - use available object in current allocation buffer
133d5ceb62bSJiri Olsa * - allocate new buffer if the current buffer is full
134d5ceb62bSJiri Olsa *
135d5ceb62bSJiri Olsa * Removal of ordered event object moves it from events to
136d5ceb62bSJiri Olsa * the cache list.
137d5ceb62bSJiri Olsa */
13853da12e0SJiri Olsa size = sizeof(*oe->buffer) + MAX_SAMPLE_BUFFER * sizeof(*new);
13953da12e0SJiri Olsa
1405f86b80bSJiri Olsa if (!list_empty(cache)) {
1415f86b80bSJiri Olsa new = list_entry(cache->next, struct ordered_event, list);
142e56fbc9dSArnaldo Carvalho de Melo list_del_init(&new->list);
1435f86b80bSJiri Olsa } else if (oe->buffer) {
144d5ceb62bSJiri Olsa new = &oe->buffer->event[oe->buffer_idx];
1455f86b80bSJiri Olsa if (++oe->buffer_idx == MAX_SAMPLE_BUFFER)
1465f86b80bSJiri Olsa oe->buffer = NULL;
14753da12e0SJiri Olsa } else if ((oe->cur_alloc_size + size) < oe->max_alloc_size) {
1485f86b80bSJiri Olsa oe->buffer = malloc(size);
14954bf53b1SAlexander Yarygin if (!oe->buffer) {
15054bf53b1SAlexander Yarygin free_dup_event(oe, new_event);
1515f86b80bSJiri Olsa return NULL;
15254bf53b1SAlexander Yarygin }
1535f86b80bSJiri Olsa
154cee3ab9cSJiri Olsa pr("alloc size %" PRIu64 "B (+%zu), max %" PRIu64 "B\n",
155cee3ab9cSJiri Olsa oe->cur_alloc_size, size, oe->max_alloc_size);
156cee3ab9cSJiri Olsa
1575f86b80bSJiri Olsa oe->cur_alloc_size += size;
1585f86b80bSJiri Olsa list_add(&oe->buffer->list, &oe->to_free);
1595f86b80bSJiri Olsa
160d5ceb62bSJiri Olsa oe->buffer_idx = 1;
161d5ceb62bSJiri Olsa new = &oe->buffer->event[0];
162cee3ab9cSJiri Olsa } else {
163cee3ab9cSJiri Olsa pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size);
164d5ceb62bSJiri Olsa return NULL;
1655f86b80bSJiri Olsa }
1665f86b80bSJiri Olsa
16754bf53b1SAlexander Yarygin new->event = new_event;
1685f86b80bSJiri Olsa return new;
1695f86b80bSJiri Olsa }
1705f86b80bSJiri Olsa
1714a6b362fSArnaldo Carvalho de Melo static struct ordered_event *
ordered_events__new_event(struct ordered_events * oe,u64 timestamp,union perf_event * event)1724a6b362fSArnaldo Carvalho de Melo ordered_events__new_event(struct ordered_events *oe, u64 timestamp,
17354bf53b1SAlexander Yarygin union perf_event *event)
1745f86b80bSJiri Olsa {
1755f86b80bSJiri Olsa struct ordered_event *new;
1765f86b80bSJiri Olsa
17754bf53b1SAlexander Yarygin new = alloc_event(oe, event);
1785f86b80bSJiri Olsa if (new) {
1795f86b80bSJiri Olsa new->timestamp = timestamp;
1805f86b80bSJiri Olsa queue_event(oe, new);
1815f86b80bSJiri Olsa }
1825f86b80bSJiri Olsa
1835f86b80bSJiri Olsa return new;
1845f86b80bSJiri Olsa }
1855f86b80bSJiri Olsa
ordered_events__delete(struct ordered_events * oe,struct ordered_event * event)1865f86b80bSJiri Olsa void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event)
1875f86b80bSJiri Olsa {
188fa4e5c67SJiri Olsa list_move(&event->list, &oe->cache);
1895f86b80bSJiri Olsa oe->nr_events--;
19054bf53b1SAlexander Yarygin free_dup_event(oe, event->event);
1911e0d4f02SDavid Carrillo-Cisneros event->event = NULL;
1925f86b80bSJiri Olsa }
1935f86b80bSJiri Olsa
ordered_events__queue(struct ordered_events * oe,union perf_event * event,u64 timestamp,u64 file_offset,const char * file_path)1944a6b362fSArnaldo Carvalho de Melo int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
1952292083fSAlexey Bayduraev u64 timestamp, u64 file_offset, const char *file_path)
1964a6b362fSArnaldo Carvalho de Melo {
1974a6b362fSArnaldo Carvalho de Melo struct ordered_event *oevent;
1984a6b362fSArnaldo Carvalho de Melo
1994a6b362fSArnaldo Carvalho de Melo if (!timestamp || timestamp == ~0ULL)
2004a6b362fSArnaldo Carvalho de Melo return -ETIME;
2014a6b362fSArnaldo Carvalho de Melo
2024a6b362fSArnaldo Carvalho de Melo if (timestamp < oe->last_flush) {
2034a6b362fSArnaldo Carvalho de Melo pr_oe_time(timestamp, "out of order event\n");
2044a6b362fSArnaldo Carvalho de Melo pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
2054a6b362fSArnaldo Carvalho de Melo oe->last_flush_type);
2064a6b362fSArnaldo Carvalho de Melo
2079870d780SArnaldo Carvalho de Melo oe->nr_unordered_events++;
2084a6b362fSArnaldo Carvalho de Melo }
2094a6b362fSArnaldo Carvalho de Melo
2104a6b362fSArnaldo Carvalho de Melo oevent = ordered_events__new_event(oe, timestamp, event);
2114a6b362fSArnaldo Carvalho de Melo if (!oevent) {
2124a6b362fSArnaldo Carvalho de Melo ordered_events__flush(oe, OE_FLUSH__HALF);
2134a6b362fSArnaldo Carvalho de Melo oevent = ordered_events__new_event(oe, timestamp, event);
2144a6b362fSArnaldo Carvalho de Melo }
2154a6b362fSArnaldo Carvalho de Melo
2164a6b362fSArnaldo Carvalho de Melo if (!oevent)
2174a6b362fSArnaldo Carvalho de Melo return -ENOMEM;
2184a6b362fSArnaldo Carvalho de Melo
2194a6b362fSArnaldo Carvalho de Melo oevent->file_offset = file_offset;
2202292083fSAlexey Bayduraev oevent->file_path = file_path;
2214a6b362fSArnaldo Carvalho de Melo return 0;
2224a6b362fSArnaldo Carvalho de Melo }
2234a6b362fSArnaldo Carvalho de Melo
do_flush(struct ordered_events * oe,bool show_progress)22468ca5d07SJiri Olsa static int do_flush(struct ordered_events *oe, bool show_progress)
2255f86b80bSJiri Olsa {
2265f86b80bSJiri Olsa struct list_head *head = &oe->events;
2275f86b80bSJiri Olsa struct ordered_event *tmp, *iter;
2285f86b80bSJiri Olsa u64 limit = oe->next_flush;
2295f86b80bSJiri Olsa u64 last_ts = oe->last ? oe->last->timestamp : 0ULL;
2305f86b80bSJiri Olsa struct ui_progress prog;
2315f86b80bSJiri Olsa int ret;
2325f86b80bSJiri Olsa
23328083681SArnaldo Carvalho de Melo if (!limit)
2345f86b80bSJiri Olsa return 0;
2355f86b80bSJiri Olsa
2365f86b80bSJiri Olsa if (show_progress)
2375f86b80bSJiri Olsa ui_progress__init(&prog, oe->nr_events, "Processing time ordered events...");
2385f86b80bSJiri Olsa
2395f86b80bSJiri Olsa list_for_each_entry_safe(iter, tmp, head, list) {
2405f86b80bSJiri Olsa if (session_done())
2415f86b80bSJiri Olsa return 0;
2425f86b80bSJiri Olsa
2435f86b80bSJiri Olsa if (iter->timestamp > limit)
2445f86b80bSJiri Olsa break;
2459870d780SArnaldo Carvalho de Melo ret = oe->deliver(oe, iter);
2465f86b80bSJiri Olsa if (ret)
2475f86b80bSJiri Olsa return ret;
2485f86b80bSJiri Olsa
2495f86b80bSJiri Olsa ordered_events__delete(oe, iter);
2505f86b80bSJiri Olsa oe->last_flush = iter->timestamp;
2515f86b80bSJiri Olsa
2525f86b80bSJiri Olsa if (show_progress)
2535f86b80bSJiri Olsa ui_progress__update(&prog, 1);
2545f86b80bSJiri Olsa }
2555f86b80bSJiri Olsa
2565f86b80bSJiri Olsa if (list_empty(head))
2575f86b80bSJiri Olsa oe->last = NULL;
2585f86b80bSJiri Olsa else if (last_ts <= limit)
2595f86b80bSJiri Olsa oe->last = list_entry(head->prev, struct ordered_event, list);
2605f86b80bSJiri Olsa
2615c9ce1e6SArnaldo Carvalho de Melo if (show_progress)
2625c9ce1e6SArnaldo Carvalho de Melo ui_progress__finish();
2635c9ce1e6SArnaldo Carvalho de Melo
2645f86b80bSJiri Olsa return 0;
2655f86b80bSJiri Olsa }
2665f86b80bSJiri Olsa
__ordered_events__flush(struct ordered_events * oe,enum oe_flush how,u64 timestamp)26768ca5d07SJiri Olsa static int __ordered_events__flush(struct ordered_events *oe, enum oe_flush how,
26868ca5d07SJiri Olsa u64 timestamp)
2695f86b80bSJiri Olsa {
270cee3ab9cSJiri Olsa static const char * const str[] = {
271b0a45203SJiri Olsa "NONE",
272cee3ab9cSJiri Olsa "FINAL",
273cee3ab9cSJiri Olsa "ROUND",
274cee3ab9cSJiri Olsa "HALF ",
2751e5b0cf8SChangbin Du "TOP ",
2761e5b0cf8SChangbin Du "TIME ",
277cee3ab9cSJiri Olsa };
2785f86b80bSJiri Olsa int err;
279b8494f1dSJiri Olsa bool show_progress = false;
2805f86b80bSJiri Olsa
28128083681SArnaldo Carvalho de Melo if (oe->nr_events == 0)
28228083681SArnaldo Carvalho de Melo return 0;
28328083681SArnaldo Carvalho de Melo
2845f86b80bSJiri Olsa switch (how) {
2855f86b80bSJiri Olsa case OE_FLUSH__FINAL:
286b8494f1dSJiri Olsa show_progress = true;
287*f7a858bfSLiam Howlett fallthrough;
28816c66bc1SJiri Olsa case OE_FLUSH__TOP:
28916c66bc1SJiri Olsa oe->next_flush = ULLONG_MAX;
2905f86b80bSJiri Olsa break;
2915f86b80bSJiri Olsa
2925f86b80bSJiri Olsa case OE_FLUSH__HALF:
2935f86b80bSJiri Olsa {
2945f86b80bSJiri Olsa struct ordered_event *first, *last;
2955f86b80bSJiri Olsa struct list_head *head = &oe->events;
2965f86b80bSJiri Olsa
2975f86b80bSJiri Olsa first = list_entry(head->next, struct ordered_event, list);
2985f86b80bSJiri Olsa last = oe->last;
2995f86b80bSJiri Olsa
3005f86b80bSJiri Olsa /* Warn if we are called before any event got allocated. */
3015f86b80bSJiri Olsa if (WARN_ONCE(!last || list_empty(head), "empty queue"))
3025f86b80bSJiri Olsa return 0;
3035f86b80bSJiri Olsa
3045f86b80bSJiri Olsa oe->next_flush = first->timestamp;
3055f86b80bSJiri Olsa oe->next_flush += (last->timestamp - first->timestamp) / 2;
3065f86b80bSJiri Olsa break;
3075f86b80bSJiri Olsa }
3085f86b80bSJiri Olsa
30968ca5d07SJiri Olsa case OE_FLUSH__TIME:
31068ca5d07SJiri Olsa oe->next_flush = timestamp;
31168ca5d07SJiri Olsa show_progress = false;
31268ca5d07SJiri Olsa break;
31368ca5d07SJiri Olsa
3145f86b80bSJiri Olsa case OE_FLUSH__ROUND:
315b0a45203SJiri Olsa case OE_FLUSH__NONE:
3165f86b80bSJiri Olsa default:
3175f86b80bSJiri Olsa break;
3188284bbeaSZou Wei }
3195f86b80bSJiri Olsa
320cee3ab9cSJiri Olsa pr_oe_time(oe->next_flush, "next_flush - ordered_events__flush PRE %s, nr_events %u\n",
321cee3ab9cSJiri Olsa str[how], oe->nr_events);
322cee3ab9cSJiri Olsa pr_oe_time(oe->max_timestamp, "max_timestamp\n");
323cee3ab9cSJiri Olsa
32468ca5d07SJiri Olsa err = do_flush(oe, show_progress);
3255f86b80bSJiri Olsa
3265f86b80bSJiri Olsa if (!err) {
3275f86b80bSJiri Olsa if (how == OE_FLUSH__ROUND)
3285f86b80bSJiri Olsa oe->next_flush = oe->max_timestamp;
329b0a45203SJiri Olsa
330b0a45203SJiri Olsa oe->last_flush_type = how;
3315f86b80bSJiri Olsa }
3325f86b80bSJiri Olsa
333cee3ab9cSJiri Olsa pr_oe_time(oe->next_flush, "next_flush - ordered_events__flush POST %s, nr_events %u\n",
334cee3ab9cSJiri Olsa str[how], oe->nr_events);
335cee3ab9cSJiri Olsa pr_oe_time(oe->last_flush, "last_flush\n");
336cee3ab9cSJiri Olsa
3375f86b80bSJiri Olsa return err;
3385f86b80bSJiri Olsa }
33936522f5cSJiri Olsa
ordered_events__flush(struct ordered_events * oe,enum oe_flush how)34068ca5d07SJiri Olsa int ordered_events__flush(struct ordered_events *oe, enum oe_flush how)
34168ca5d07SJiri Olsa {
34268ca5d07SJiri Olsa return __ordered_events__flush(oe, how, 0);
34368ca5d07SJiri Olsa }
34468ca5d07SJiri Olsa
ordered_events__flush_time(struct ordered_events * oe,u64 timestamp)34568ca5d07SJiri Olsa int ordered_events__flush_time(struct ordered_events *oe, u64 timestamp)
34668ca5d07SJiri Olsa {
34768ca5d07SJiri Olsa return __ordered_events__flush(oe, OE_FLUSH__TIME, timestamp);
34868ca5d07SJiri Olsa }
34968ca5d07SJiri Olsa
ordered_events__first_time(struct ordered_events * oe)35083356b3dSJiri Olsa u64 ordered_events__first_time(struct ordered_events *oe)
35183356b3dSJiri Olsa {
35283356b3dSJiri Olsa struct ordered_event *event;
35383356b3dSJiri Olsa
35483356b3dSJiri Olsa if (list_empty(&oe->events))
35583356b3dSJiri Olsa return 0;
35683356b3dSJiri Olsa
35783356b3dSJiri Olsa event = list_first_entry(&oe->events, struct ordered_event, list);
35883356b3dSJiri Olsa return event->timestamp;
35983356b3dSJiri Olsa }
36083356b3dSJiri Olsa
ordered_events__init(struct ordered_events * oe,ordered_events__deliver_t deliver,void * data)361a4a6668aSJiri Olsa void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver,
362a4a6668aSJiri Olsa void *data)
36336522f5cSJiri Olsa {
36436522f5cSJiri Olsa INIT_LIST_HEAD(&oe->events);
36536522f5cSJiri Olsa INIT_LIST_HEAD(&oe->cache);
36636522f5cSJiri Olsa INIT_LIST_HEAD(&oe->to_free);
36736522f5cSJiri Olsa oe->max_alloc_size = (u64) -1;
36836522f5cSJiri Olsa oe->cur_alloc_size = 0;
369d10eb1ebSArnaldo Carvalho de Melo oe->deliver = deliver;
370a4a6668aSJiri Olsa oe->data = data;
37136522f5cSJiri Olsa }
372adc56ed1SJiri Olsa
373d5ceb62bSJiri Olsa static void
ordered_events_buffer__free(struct ordered_events_buffer * buffer,unsigned int max,struct ordered_events * oe)374d5ceb62bSJiri Olsa ordered_events_buffer__free(struct ordered_events_buffer *buffer,
375d5ceb62bSJiri Olsa unsigned int max, struct ordered_events *oe)
376d5ceb62bSJiri Olsa {
377d5ceb62bSJiri Olsa if (oe->copy_on_queue) {
378d5ceb62bSJiri Olsa unsigned int i;
379d5ceb62bSJiri Olsa
380d5ceb62bSJiri Olsa for (i = 0; i < max; i++)
381d5ceb62bSJiri Olsa __free_dup_event(oe, buffer->event[i].event);
382d5ceb62bSJiri Olsa }
383d5ceb62bSJiri Olsa
384d5ceb62bSJiri Olsa free(buffer);
385d5ceb62bSJiri Olsa }
386d5ceb62bSJiri Olsa
ordered_events__free(struct ordered_events * oe)387adc56ed1SJiri Olsa void ordered_events__free(struct ordered_events *oe)
388adc56ed1SJiri Olsa {
389d5ceb62bSJiri Olsa struct ordered_events_buffer *buffer, *tmp;
390adc56ed1SJiri Olsa
391d5ceb62bSJiri Olsa if (list_empty(&oe->to_free))
392d5ceb62bSJiri Olsa return;
393d5ceb62bSJiri Olsa
394d5ceb62bSJiri Olsa /*
395d5ceb62bSJiri Olsa * Current buffer might not have all the events allocated
396d5ceb62bSJiri Olsa * yet, we need to free only allocated ones ...
397d5ceb62bSJiri Olsa */
39899d86c8bSJiri Olsa if (oe->buffer) {
399e56fbc9dSArnaldo Carvalho de Melo list_del_init(&oe->buffer->list);
400d5ceb62bSJiri Olsa ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe);
40199d86c8bSJiri Olsa }
402d5ceb62bSJiri Olsa
403d5ceb62bSJiri Olsa /* ... and continue with the rest */
404d5ceb62bSJiri Olsa list_for_each_entry_safe(buffer, tmp, &oe->to_free, list) {
405e56fbc9dSArnaldo Carvalho de Melo list_del_init(&buffer->list);
406d5ceb62bSJiri Olsa ordered_events_buffer__free(buffer, MAX_SAMPLE_BUFFER, oe);
407adc56ed1SJiri Olsa }
408adc56ed1SJiri Olsa }
4094532f642SWang Nan
ordered_events__reinit(struct ordered_events * oe)4104532f642SWang Nan void ordered_events__reinit(struct ordered_events *oe)
4114532f642SWang Nan {
4124532f642SWang Nan ordered_events__deliver_t old_deliver = oe->deliver;
4134532f642SWang Nan
4144532f642SWang Nan ordered_events__free(oe);
4154532f642SWang Nan memset(oe, '\0', sizeof(*oe));
416a4a6668aSJiri Olsa ordered_events__init(oe, old_deliver, oe->data);
4174532f642SWang Nan }
418