15f86b80bSJiri Olsa #include <linux/list.h> 25f86b80bSJiri Olsa #include "ordered-events.h" 35f86b80bSJiri Olsa #include "evlist.h" 45f86b80bSJiri Olsa #include "session.h" 55f86b80bSJiri Olsa #include "asm/bug.h" 65f86b80bSJiri Olsa #include "debug.h" 75f86b80bSJiri Olsa 85f86b80bSJiri Olsa static void queue_event(struct ordered_events *oe, struct ordered_event *new) 95f86b80bSJiri Olsa { 105f86b80bSJiri Olsa struct ordered_event *last = oe->last; 115f86b80bSJiri Olsa u64 timestamp = new->timestamp; 125f86b80bSJiri Olsa struct list_head *p; 135f86b80bSJiri Olsa 145f86b80bSJiri Olsa ++oe->nr_events; 155f86b80bSJiri Olsa oe->last = new; 165f86b80bSJiri Olsa 175f86b80bSJiri Olsa if (!last) { 185f86b80bSJiri Olsa list_add(&new->list, &oe->events); 195f86b80bSJiri Olsa oe->max_timestamp = timestamp; 205f86b80bSJiri Olsa return; 215f86b80bSJiri Olsa } 225f86b80bSJiri Olsa 235f86b80bSJiri Olsa /* 245f86b80bSJiri Olsa * last event might point to some random place in the list as it's 255f86b80bSJiri Olsa * the last queued event. We expect that the new event is close to 265f86b80bSJiri Olsa * this. 275f86b80bSJiri Olsa */ 285f86b80bSJiri Olsa if (last->timestamp <= timestamp) { 295f86b80bSJiri Olsa while (last->timestamp <= timestamp) { 305f86b80bSJiri Olsa p = last->list.next; 315f86b80bSJiri Olsa if (p == &oe->events) { 325f86b80bSJiri Olsa list_add_tail(&new->list, &oe->events); 335f86b80bSJiri Olsa oe->max_timestamp = timestamp; 345f86b80bSJiri Olsa return; 355f86b80bSJiri Olsa } 365f86b80bSJiri Olsa last = list_entry(p, struct ordered_event, list); 375f86b80bSJiri Olsa } 385f86b80bSJiri Olsa list_add_tail(&new->list, &last->list); 395f86b80bSJiri Olsa } else { 405f86b80bSJiri Olsa while (last->timestamp > timestamp) { 415f86b80bSJiri Olsa p = last->list.prev; 425f86b80bSJiri Olsa if (p == &oe->events) { 435f86b80bSJiri Olsa list_add(&new->list, &oe->events); 445f86b80bSJiri Olsa return; 455f86b80bSJiri Olsa } 465f86b80bSJiri Olsa last = list_entry(p, struct ordered_event, list); 475f86b80bSJiri Olsa } 485f86b80bSJiri Olsa list_add(&new->list, &last->list); 495f86b80bSJiri Olsa } 505f86b80bSJiri Olsa } 515f86b80bSJiri Olsa 525f86b80bSJiri Olsa #define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event)) 535f86b80bSJiri Olsa static struct ordered_event *alloc_event(struct ordered_events *oe) 545f86b80bSJiri Olsa { 555f86b80bSJiri Olsa struct list_head *cache = &oe->cache; 565f86b80bSJiri Olsa struct ordered_event *new = NULL; 575f86b80bSJiri Olsa 585f86b80bSJiri Olsa if (!list_empty(cache)) { 595f86b80bSJiri Olsa new = list_entry(cache->next, struct ordered_event, list); 605f86b80bSJiri Olsa list_del(&new->list); 615f86b80bSJiri Olsa } else if (oe->buffer) { 625f86b80bSJiri Olsa new = oe->buffer + oe->buffer_idx; 635f86b80bSJiri Olsa if (++oe->buffer_idx == MAX_SAMPLE_BUFFER) 645f86b80bSJiri Olsa oe->buffer = NULL; 655f86b80bSJiri Olsa } else if (oe->cur_alloc_size < oe->max_alloc_size) { 665f86b80bSJiri Olsa size_t size = MAX_SAMPLE_BUFFER * sizeof(*new); 675f86b80bSJiri Olsa 685f86b80bSJiri Olsa oe->buffer = malloc(size); 695f86b80bSJiri Olsa if (!oe->buffer) 705f86b80bSJiri Olsa return NULL; 715f86b80bSJiri Olsa 725f86b80bSJiri Olsa oe->cur_alloc_size += size; 735f86b80bSJiri Olsa list_add(&oe->buffer->list, &oe->to_free); 745f86b80bSJiri Olsa 755f86b80bSJiri Olsa /* First entry is abused to maintain the to_free list. */ 765f86b80bSJiri Olsa oe->buffer_idx = 2; 775f86b80bSJiri Olsa new = oe->buffer + 1; 785f86b80bSJiri Olsa } 795f86b80bSJiri Olsa 805f86b80bSJiri Olsa return new; 815f86b80bSJiri Olsa } 825f86b80bSJiri Olsa 835f86b80bSJiri Olsa struct ordered_event * 845f86b80bSJiri Olsa ordered_events__new(struct ordered_events *oe, u64 timestamp) 855f86b80bSJiri Olsa { 865f86b80bSJiri Olsa struct ordered_event *new; 875f86b80bSJiri Olsa 885f86b80bSJiri Olsa new = alloc_event(oe); 895f86b80bSJiri Olsa if (new) { 905f86b80bSJiri Olsa new->timestamp = timestamp; 915f86b80bSJiri Olsa queue_event(oe, new); 925f86b80bSJiri Olsa } 935f86b80bSJiri Olsa 945f86b80bSJiri Olsa return new; 955f86b80bSJiri Olsa } 965f86b80bSJiri Olsa 975f86b80bSJiri Olsa void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event) 985f86b80bSJiri Olsa { 99fa4e5c67SJiri Olsa list_move(&event->list, &oe->cache); 1005f86b80bSJiri Olsa oe->nr_events--; 1015f86b80bSJiri Olsa } 1025f86b80bSJiri Olsa 1035f86b80bSJiri Olsa static int __ordered_events__flush(struct perf_session *s, 1045f86b80bSJiri Olsa struct perf_tool *tool) 1055f86b80bSJiri Olsa { 1065f86b80bSJiri Olsa struct ordered_events *oe = &s->ordered_events; 1075f86b80bSJiri Olsa struct list_head *head = &oe->events; 1085f86b80bSJiri Olsa struct ordered_event *tmp, *iter; 1095f86b80bSJiri Olsa struct perf_sample sample; 1105f86b80bSJiri Olsa u64 limit = oe->next_flush; 1115f86b80bSJiri Olsa u64 last_ts = oe->last ? oe->last->timestamp : 0ULL; 1125f86b80bSJiri Olsa bool show_progress = limit == ULLONG_MAX; 1135f86b80bSJiri Olsa struct ui_progress prog; 1145f86b80bSJiri Olsa int ret; 1155f86b80bSJiri Olsa 1165f86b80bSJiri Olsa if (!tool->ordered_events || !limit) 1175f86b80bSJiri Olsa return 0; 1185f86b80bSJiri Olsa 1195f86b80bSJiri Olsa if (show_progress) 1205f86b80bSJiri Olsa ui_progress__init(&prog, oe->nr_events, "Processing time ordered events..."); 1215f86b80bSJiri Olsa 1225f86b80bSJiri Olsa list_for_each_entry_safe(iter, tmp, head, list) { 1235f86b80bSJiri Olsa if (session_done()) 1245f86b80bSJiri Olsa return 0; 1255f86b80bSJiri Olsa 1265f86b80bSJiri Olsa if (iter->timestamp > limit) 1275f86b80bSJiri Olsa break; 1285f86b80bSJiri Olsa 1295f86b80bSJiri Olsa ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample); 1305f86b80bSJiri Olsa if (ret) 1315f86b80bSJiri Olsa pr_err("Can't parse sample, err = %d\n", ret); 1325f86b80bSJiri Olsa else { 1335f86b80bSJiri Olsa ret = perf_session__deliver_event(s, iter->event, &sample, tool, 1345f86b80bSJiri Olsa iter->file_offset); 1355f86b80bSJiri Olsa if (ret) 1365f86b80bSJiri Olsa return ret; 1375f86b80bSJiri Olsa } 1385f86b80bSJiri Olsa 1395f86b80bSJiri Olsa ordered_events__delete(oe, iter); 1405f86b80bSJiri Olsa oe->last_flush = iter->timestamp; 1415f86b80bSJiri Olsa 1425f86b80bSJiri Olsa if (show_progress) 1435f86b80bSJiri Olsa ui_progress__update(&prog, 1); 1445f86b80bSJiri Olsa } 1455f86b80bSJiri Olsa 1465f86b80bSJiri Olsa if (list_empty(head)) 1475f86b80bSJiri Olsa oe->last = NULL; 1485f86b80bSJiri Olsa else if (last_ts <= limit) 1495f86b80bSJiri Olsa oe->last = list_entry(head->prev, struct ordered_event, list); 1505f86b80bSJiri Olsa 1515f86b80bSJiri Olsa return 0; 1525f86b80bSJiri Olsa } 1535f86b80bSJiri Olsa 1545f86b80bSJiri Olsa int ordered_events__flush(struct perf_session *s, struct perf_tool *tool, 1555f86b80bSJiri Olsa enum oe_flush how) 1565f86b80bSJiri Olsa { 1575f86b80bSJiri Olsa struct ordered_events *oe = &s->ordered_events; 1585f86b80bSJiri Olsa int err; 1595f86b80bSJiri Olsa 1605f86b80bSJiri Olsa switch (how) { 1615f86b80bSJiri Olsa case OE_FLUSH__FINAL: 1625f86b80bSJiri Olsa oe->next_flush = ULLONG_MAX; 1635f86b80bSJiri Olsa break; 1645f86b80bSJiri Olsa 1655f86b80bSJiri Olsa case OE_FLUSH__HALF: 1665f86b80bSJiri Olsa { 1675f86b80bSJiri Olsa struct ordered_event *first, *last; 1685f86b80bSJiri Olsa struct list_head *head = &oe->events; 1695f86b80bSJiri Olsa 1705f86b80bSJiri Olsa first = list_entry(head->next, struct ordered_event, list); 1715f86b80bSJiri Olsa last = oe->last; 1725f86b80bSJiri Olsa 1735f86b80bSJiri Olsa /* Warn if we are called before any event got allocated. */ 1745f86b80bSJiri Olsa if (WARN_ONCE(!last || list_empty(head), "empty queue")) 1755f86b80bSJiri Olsa return 0; 1765f86b80bSJiri Olsa 1775f86b80bSJiri Olsa oe->next_flush = first->timestamp; 1785f86b80bSJiri Olsa oe->next_flush += (last->timestamp - first->timestamp) / 2; 1795f86b80bSJiri Olsa break; 1805f86b80bSJiri Olsa } 1815f86b80bSJiri Olsa 1825f86b80bSJiri Olsa case OE_FLUSH__ROUND: 1835f86b80bSJiri Olsa default: 1845f86b80bSJiri Olsa break; 1855f86b80bSJiri Olsa }; 1865f86b80bSJiri Olsa 1875f86b80bSJiri Olsa err = __ordered_events__flush(s, tool); 1885f86b80bSJiri Olsa 1895f86b80bSJiri Olsa if (!err) { 1905f86b80bSJiri Olsa if (how == OE_FLUSH__ROUND) 1915f86b80bSJiri Olsa oe->next_flush = oe->max_timestamp; 1925f86b80bSJiri Olsa } 1935f86b80bSJiri Olsa 1945f86b80bSJiri Olsa return err; 1955f86b80bSJiri Olsa } 196