]> git.saurik.com Git - apple/system_cmds.git/blame - msa/EventRingBuffer.hpp
system_cmds-643.30.1.tar.gz
[apple/system_cmds.git] / msa / EventRingBuffer.hpp
CommitLineData
bd6521f0
A
1//
2// EventRingBuffer.hpp
3// msa
4//
5// Created by James McIlree on 10/8/13.
6// Copyright (c) 2014 Apple. All rights reserved.
7//
8
9#ifndef __msa__EventRingBuffer__
10#define __msa__EventRingBuffer__
11
12template <typename SIZE>
13class EventRingBuffer {
14 protected:
15 const Globals& _globals; // Used for printing the ringbuffer
16 std::vector<KDEvent<SIZE>> _events;
17 std::size_t _head;
18 std::size_t _tail;
19
20 public:
21 EventRingBuffer(const Globals& globals, std::size_t size);
22
23 // Returns:
24 //
25 // events, capacity, number_read
26 std::tuple<KDEvent<SIZE>*, std::size_t, std::size_t> read();
27
28 void print() const;
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;
33};
34
35template <typename SIZE>
36EventRingBuffer<SIZE>::EventRingBuffer(const Globals& globals, std::size_t size) :
37 _globals(globals),
38 _events(size),
39 _head(0),
40 _tail(0)
41{
42 ASSERT(size, "Sanity");
43
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>));
47}
48
49template <typename SIZE>
50std::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];
54
55 if ((count = KDBG::read(events, capacity * sizeof(KDEvent<SIZE>)))) {
56 // Update head/tail as soon as we have added data.
57 _tail += count;
58 if (_tail - _head > _events.size()) {
59 _head += count;
60 }
61 }
62
63 return std::make_tuple(events, count, capacity);
64}
65
66#if 0
67
68template <typename SIZE>
69void EventRingBuffer<SIZE>::print() const {
70 printf("%zu events in buffer [%zu -> %zu)\n", _tail - _head, _head, _tail);
71}
72
73template <typename SIZE>
74void EventRingBuffer<SIZE>::print_event_index(std::size_t index) const {
75 const KDEvent<SIZE>& event = _events[index % _events.size()];
76
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());
79
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());
83 } else {
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());
86 }
87}
88
89template <typename SIZE>
90void EventRingBuffer<SIZE>::print_all_events() const {
91 std::size_t begin = _head;
92 while (begin < _tail) {
93 print_event_index(begin++);
94 }
95}
96
97template <typename SIZE>
98void 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++);
104 }
105}
106
107template <typename SIZE>
108void 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)
113 break;
114 begin++;
115 }
116
117 while (begin < _tail) {
118 print_event_index(begin++);
119 }
120}
121
122void PrintEventRingBuffer() {
123 // uint64_t _timestamp;
124 // uint64_t _arg1;
125 // uint64_t _arg2;
126 // uint64_t _arg3;
127 // uint64_t _arg4;
128 // uint64_t _thread;
129 // uint32_t _debugid;
130 // uint32_t _cpuid;
131
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());
145 } else {
146 printf("%4s %s, ", type, trace_code_it->second.c_str());
147 }
148 printf("cpu=%u }\n", event.cpu());
149 }
150 printf("%lu\n", ring_buffer_tail_index - ring_buffer_head_index);
151}
152#endif
153
154#endif /* defined(__staintracker__EventRingBuffer__) */