]> git.saurik.com Git - apple/system_cmds.git/blobdiff - msa/EventRingBuffer.hpp
system_cmds-643.30.1.tar.gz
[apple/system_cmds.git] / msa / EventRingBuffer.hpp
diff --git a/msa/EventRingBuffer.hpp b/msa/EventRingBuffer.hpp
new file mode 100644 (file)
index 0000000..ebae7f2
--- /dev/null
@@ -0,0 +1,154 @@
+//
+//  EventRingBuffer.hpp
+//  msa
+//
+//  Created by James McIlree on 10/8/13.
+//  Copyright (c) 2014 Apple. All rights reserved.
+//
+
+#ifndef __msa__EventRingBuffer__
+#define __msa__EventRingBuffer__
+
+template <typename SIZE>
+class EventRingBuffer {
+    protected:
+       const Globals&                  _globals; // Used for printing the ringbuffer
+       std::vector<KDEvent<SIZE>>      _events;
+       std::size_t                     _head;
+       std::size_t                     _tail;
+
+    public:
+       EventRingBuffer(const Globals& globals, std::size_t size);
+
+       // Returns:
+       //
+       // events, capacity, number_read
+       std::tuple<KDEvent<SIZE>*, std::size_t, std::size_t> read();
+
+       void print() const;
+       void print_event_index(std::size_t index) const;
+       void print_all_events() const;
+       void print_last_events(std::size_t lastN) const;
+       void print_from_timestamp(uint64_t timestamp) const;
+};
+
+template <typename SIZE>
+EventRingBuffer<SIZE>::EventRingBuffer(const Globals& globals, std::size_t size) :
+       _globals(globals),
+       _events(size),
+       _head(0),
+       _tail(0)
+{
+       ASSERT(size, "Sanity");
+
+       // Force all pages into memory so the first bazillion
+       // trace entries aren't VM_FAULT...
+       bzero(_events.data(), _events.size() * sizeof(KDEvent<SIZE>));
+}
+
+template <typename SIZE>
+std::tuple<KDEvent<SIZE>*, std::size_t, std::size_t> EventRingBuffer<SIZE>::read() {
+       std::size_t modulo_index = _tail % _events.size();
+       std::size_t count, capacity = _events.size() - modulo_index;
+       KDEvent<SIZE>* events = &_events.data()[modulo_index];
+
+       if ((count = KDBG::read(events, capacity * sizeof(KDEvent<SIZE>)))) {
+               // Update head/tail as soon as we have added data.
+               _tail += count;
+               if (_tail - _head > _events.size()) {
+                       _head += count;
+               }
+       }
+
+       return std::make_tuple(events, count, capacity);
+}
+
+#if 0
+
+template <typename SIZE>
+void EventRingBuffer<SIZE>::print() const {
+       printf("%zu events in buffer [%zu -> %zu)\n", _tail - _head, _head, _tail);
+}
+
+template <typename SIZE>
+void EventRingBuffer<SIZE>::print_event_index(std::size_t index) const {
+       const KDEvent<SIZE>& event = _events[index % _events.size()];
+
+       const char* type = event.is_func_start() ?  "beg" : (event.is_func_end() ? "end" : "---");
+       auto trace_code_it = _globals.trace_codes().find(event.dbg_cooked());
+
+       if (trace_code_it == _globals.trace_codes().end()) {
+               printf("event[%ld] { timestamp=%llx, arg1=%llx, arg2=%llx, arg3=%llx, arg4=%llx, tid=%llx, %4s %x, cpu=%u }\n", index, event.timestamp().value(),
+                      (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());
+       } else {
+               printf("event[%ld] { timestamp=%llx, arg1=%llx, arg2=%llx, arg3=%llx, arg4=%llx, tid=%llx, %4s %s, cpu=%u }\n", index, event.timestamp().value(),
+                      (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());
+       }
+}
+
+template <typename SIZE>
+void EventRingBuffer<SIZE>::print_all_events() const {
+       std::size_t begin = _head;
+       while (begin < _tail) {
+               print_event_index(begin++);
+       }
+}
+
+template <typename SIZE>
+void EventRingBuffer<SIZE>::print_last_events(std::size_t lastN) const {
+       std::size_t length = std::min(lastN, _tail - _head);
+       std::size_t begin = _tail - length;
+       ASSERT(begin <= _tail, "Sanity");
+       while (begin < _tail) {
+               print_event_index(begin++);
+       }
+}
+
+template <typename SIZE>
+void EventRingBuffer<SIZE>::print_from_timestamp(uint64_t t) const {
+       std::size_t begin = _head;
+       while (begin < _tail) {
+               const KDEvent<SIZE>& event = _events[begin % _events.size()];
+               if (event.timestamp() >= t)
+                       break;
+               begin++;
+       }
+
+       while (begin < _tail) {
+               print_event_index(begin++);
+       }
+}
+
+void PrintEventRingBuffer() {
+       //      uint64_t        _timestamp;
+       //      uint64_t        _arg1;
+       //      uint64_t        _arg2;
+       //      uint64_t        _arg3;
+       //      uint64_t        _arg4;
+       //      uint64_t        _thread;
+       //      uint32_t        _debugid;
+       //      uint32_t        _cpuid;
+
+       const KDEvent<Kernel64>* events = (const KDEvent<Kernel64>*)g_rb;
+       for (std::size_t i=ring_buffer_head_index; i<ring_buffer_tail_index; i++) {
+               const KDEvent<Kernel64>& event = events[i % g_rb_size];
+               printf("event[%ld] { timestamp=%llx, ", i, event.timestamp().value());
+               printf("arg1=%llx, ", event.arg1());
+               printf("arg2=%llx, ", event.arg2());
+               printf("arg3=%llx, ", event.arg3());
+               printf("arg4=%llx, ", event.arg4());
+               printf("tid=%llx, ", event.tid());
+               const char* type = event.is_func_start() ?  "beg" : (event.is_func_end() ? "end" : "---");
+               auto trace_code_it = gglobals->trace_codes().find(event.dbg_cooked());
+               if (trace_code_it == gglobals->trace_codes().end()) {
+                       printf("%4s %x, ", type, event.dbg_cooked());
+               } else {
+                       printf("%4s %s, ", type, trace_code_it->second.c_str());
+               }
+               printf("cpu=%u }\n", event.cpu());
+       }
+       printf("%lu\n", ring_buffer_tail_index - ring_buffer_head_index);
+}
+#endif
+
+#endif /* defined(__staintracker__EventRingBuffer__) */