5 // Created by James McIlree on 10/8/13.
6 // Copyright (c) 2014 Apple. All rights reserved.
9 #ifndef __msa__EventRingBuffer__
10 #define __msa__EventRingBuffer__
12 template <typename SIZE>
13 class EventRingBuffer {
15 const Globals& _globals; // Used for printing the ringbuffer
16 std::vector<KDEvent<SIZE>> _events;
21 EventRingBuffer(const Globals& globals, std::size_t size);
25 // events, capacity, number_read
26 std::tuple<KDEvent<SIZE>*, std::size_t, std::size_t> read();
29 void print_event_index(std::size_t index) const;
30 void print_all_events() const;
31 void print_last_events(std::size_t lastN) const;
32 void print_from_timestamp(uint64_t timestamp) const;
35 template <typename SIZE>
36 EventRingBuffer<SIZE>::EventRingBuffer(const Globals& globals, std::size_t size) :
42 ASSERT(size, "Sanity");
44 // Force all pages into memory so the first bazillion
45 // trace entries aren't VM_FAULT...
46 bzero(_events.data(), _events.size() * sizeof(KDEvent<SIZE>));
49 template <typename SIZE>
50 std::tuple<KDEvent<SIZE>*, std::size_t, std::size_t> EventRingBuffer<SIZE>::read() {
51 std::size_t modulo_index = _tail % _events.size();
52 std::size_t count, capacity = _events.size() - modulo_index;
53 KDEvent<SIZE>* events = &_events.data()[modulo_index];
55 if ((count = KDBG::read(events, capacity * sizeof(KDEvent<SIZE>)))) {
56 // Update head/tail as soon as we have added data.
58 if (_tail - _head > _events.size()) {
63 return std::make_tuple(events, count, capacity);
68 template <typename SIZE>
69 void EventRingBuffer<SIZE>::print() const {
70 printf("%zu events in buffer [%zu -> %zu)\n", _tail - _head, _head, _tail);
73 template <typename SIZE>
74 void EventRingBuffer<SIZE>::print_event_index(std::size_t index) const {
75 const KDEvent<SIZE>& event = _events[index % _events.size()];
77 const char* type = event.is_func_start() ? "beg" : (event.is_func_end() ? "end" : "---");
78 auto trace_code_it = _globals.trace_codes().find(event.dbg_cooked());
80 if (trace_code_it == _globals.trace_codes().end()) {
81 printf("event[%ld] { timestamp=%llx, arg1=%llx, arg2=%llx, arg3=%llx, arg4=%llx, tid=%llx, %4s %x, cpu=%u }\n", index, event.timestamp().value(),
82 (uint64_t)event.arg1(), (uint64_t)event.arg2(), (uint64_t)event.arg3(), (uint64_t)event.arg4(), (uint64_t)event.tid(), type, event.dbg_cooked(), event.cpu());
84 printf("event[%ld] { timestamp=%llx, arg1=%llx, arg2=%llx, arg3=%llx, arg4=%llx, tid=%llx, %4s %s, cpu=%u }\n", index, event.timestamp().value(),
85 (uint64_t)event.arg1(), (uint64_t)event.arg2(), (uint64_t)event.arg3(), (uint64_t)event.arg4(), (uint64_t)event.tid(), type, trace_code_it->second.c_str(), event.cpu());
89 template <typename SIZE>
90 void EventRingBuffer<SIZE>::print_all_events() const {
91 std::size_t begin = _head;
92 while (begin < _tail) {
93 print_event_index(begin++);
97 template <typename SIZE>
98 void EventRingBuffer<SIZE>::print_last_events(std::size_t lastN) const {
99 std::size_t length = std::min(lastN, _tail - _head);
100 std::size_t begin = _tail - length;
101 ASSERT(begin <= _tail, "Sanity");
102 while (begin < _tail) {
103 print_event_index(begin++);
107 template <typename SIZE>
108 void EventRingBuffer<SIZE>::print_from_timestamp(uint64_t t) const {
109 std::size_t begin = _head;
110 while (begin < _tail) {
111 const KDEvent<SIZE>& event = _events[begin % _events.size()];
112 if (event.timestamp() >= t)
117 while (begin < _tail) {
118 print_event_index(begin++);
122 void PrintEventRingBuffer() {
123 // uint64_t _timestamp;
129 // uint32_t _debugid;
132 const KDEvent<Kernel64>* events = (const KDEvent<Kernel64>*)g_rb;
133 for (std::size_t i=ring_buffer_head_index; i<ring_buffer_tail_index; i++) {
134 const KDEvent<Kernel64>& event = events[i % g_rb_size];
135 printf("event[%ld] { timestamp=%llx, ", i, event.timestamp().value());
136 printf("arg1=%llx, ", event.arg1());
137 printf("arg2=%llx, ", event.arg2());
138 printf("arg3=%llx, ", event.arg3());
139 printf("arg4=%llx, ", event.arg4());
140 printf("tid=%llx, ", event.tid());
141 const char* type = event.is_func_start() ? "beg" : (event.is_func_end() ? "end" : "---");
142 auto trace_code_it = gglobals->trace_codes().find(event.dbg_cooked());
143 if (trace_code_it == gglobals->trace_codes().end()) {
144 printf("%4s %x, ", type, event.dbg_cooked());
146 printf("%4s %s, ", type, trace_code_it->second.c_str());
148 printf("cpu=%u }\n", event.cpu());
150 printf("%lu\n", ring_buffer_tail_index - ring_buffer_head_index);
154 #endif /* defined(__staintracker__EventRingBuffer__) */