blob: 259d59c3a93852e3d33d13d8396a5aa146870adc [file] [log] [blame]
Austin Schuh99004602024-03-16 11:59:24 -07001#include <unistd.h>
2
3#include <iostream>
4
5#include "gflags/gflags.h"
6
7#include "aos/aos_cli_utils.h"
8#include "aos/configuration.h"
9#include "aos/ftrace.h"
10#include "aos/init.h"
11#include "aos/json_to_flatbuffer.h"
12#include "aos/realtime.h"
13
14DEFINE_int32(priority, -1, "If set, the RT priority to run at.");
15DEFINE_double(max_jitter, 0.01,
16 "The max time in milliseconds between messages before marking it "
17 "as too late.");
18DEFINE_bool(print_jitter, true,
19 "If true, print jitter events. These will impact RT performance.");
20DECLARE_bool(enable_ftrace);
21
22namespace aos {
23
24class State {
25 public:
26 State(Ftrace *ftrace, aos::EventLoop *event_loop, const Channel *channel)
27 : ftrace_(ftrace),
28 channel_(channel),
29 channel_name_(aos::configuration::StrippedChannelToString(channel_)) {
30 LOG(INFO) << "Watching for jitter on " << channel_name_;
31 event_loop->MakeRawWatcher(
32 channel_, [this](const aos::Context &context, const void *message) {
33 HandleMessage(context, message);
34 });
35 }
36
37 void HandleMessage(const aos::Context &context, const void * /*message*/) {
38 if (last_time_ != aos::monotonic_clock::min_time) {
39 if (context.monotonic_event_time >
40 last_time_ + std::chrono::duration_cast<std::chrono::nanoseconds>(
41 std::chrono::duration<double>(FLAGS_max_jitter))) {
42 if (FLAGS_enable_ftrace) {
43 ftrace_->FormatMessage(
44 "Got high latency event on %s -> %.9f between messages",
45 channel_name_.c_str(),
46 std::chrono::duration<double>(context.monotonic_event_time -
47 last_time_)
48 .count());
49 ftrace_->TurnOffOrDie();
50 }
51
52 if (FLAGS_print_jitter) {
53 // Printing isn't realtime, but if someone wants to run as RT, they
54 // should know this. Bypass the warning.
55 ScopedNotRealtime nrt;
56
57 LOG(INFO) << "Got a high latency event on "
58 << aos::configuration::StrippedChannelToString(channel_)
59 << " -> " << std::fixed << std::setprecision(9)
60 << std::chrono::duration<double>(
61 context.monotonic_event_time - last_time_)
62 .count()
63 << " between messages.";
64 }
65 }
66 }
67
68 last_time_ = context.monotonic_event_time;
69 }
70
71 private:
72 Ftrace *ftrace_;
73 const Channel *channel_;
74
75 std::string channel_name_;
76
77 aos::monotonic_clock::time_point last_time_ = aos::monotonic_clock::min_time;
78};
79
80} // namespace aos
81
82int main(int argc, char **argv) {
83 aos::InitGoogle(&argc, &argv);
84
85 aos::CliUtilInfo cli_info;
86 if (cli_info.Initialize(
87 &argc, &argv,
88 [&cli_info](const aos::Channel *channel) {
89 return aos::configuration::ChannelIsReadableOnNode(
90 channel, cli_info.event_loop->node());
91 },
92 "channel is readeable on node", true)) {
93 return 0;
94 }
95
96 aos::Ftrace ftrace;
97
98 std::vector<std::unique_ptr<aos::State>> states;
99
100 for (const aos::Channel *channel : cli_info.found_channels) {
101 states.emplace_back(std::make_unique<aos::State>(
102 &ftrace, &(cli_info.event_loop.value()), channel));
103 }
104
105 if (FLAGS_priority > 0) {
106 cli_info.event_loop->SetRuntimeRealtimePriority(FLAGS_priority);
107 }
108
109 cli_info.event_loop->Run();
110
111 return 0;
112}