Make simulated_event_loop run with --die_on_malloc

We can't yet turn it on globally since some mallocs have snuck back in.
Gotta beat them back out first.

Change-Id: Ib0fc90746002240b5afca6b36eff2f4b29bbfbb0
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/aos/events/event_loop.h b/aos/events/event_loop.h
index 8c16f3a..3ecd93f 100644
--- a/aos/events/event_loop.h
+++ b/aos/events/event_loop.h
@@ -477,9 +477,9 @@
  protected:
   TimerHandler(EventLoop *event_loop, std::function<void()> fn);
 
-  monotonic_clock::time_point Call(
-      std::function<monotonic_clock::time_point()> get_time,
-      monotonic_clock::time_point event_time);
+  template <typename T>
+  monotonic_clock::time_point Call(T get_time,
+                                   monotonic_clock::time_point event_time);
 
  private:
   friend class EventLoop;
diff --git a/aos/events/event_loop_param_test.cc b/aos/events/event_loop_param_test.cc
index f9e673c..2d7decc 100644
--- a/aos/events/event_loop_param_test.cc
+++ b/aos/events/event_loop_param_test.cc
@@ -1151,6 +1151,7 @@
   std::vector<monotonic_clock::time_point> iteration_list;
 
   auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
+    ScopedNotRealtime nrt;
     iteration_list.push_back(loop->context().monotonic_event_time);
   });
 
@@ -1181,6 +1182,7 @@
   ::std::vector<::aos::monotonic_clock::time_point> iteration_list;
 
   auto test_timer = loop->AddTimer([&iteration_list, &loop]() {
+    ScopedNotRealtime nrt;
     iteration_list.push_back(loop->context().monotonic_event_time);
   });
 
@@ -2417,6 +2419,28 @@
 }
 
 // Tests that a realtime event loop timer is marked realtime.
+TEST_P(AbstractEventLoopTest, RealtimeSend) {
+  auto loop1 = MakePrimary();
+
+  loop1->SetRuntimeRealtimePriority(1);
+
+  auto sender = loop1->MakeSender<TestMessage>("/test2");
+
+  loop1->OnRun([&]() {
+    CheckRealtime();
+
+    aos::Sender<TestMessage>::Builder msg = sender.MakeBuilder();
+    TestMessage::Builder builder = msg.MakeBuilder<TestMessage>();
+    builder.add_value(200);
+    msg.CheckOk(msg.Send(builder.Finish()));
+
+    this->Exit();
+  });
+
+  Run();
+}
+
+// Tests that a realtime event loop timer is marked realtime.
 TEST_P(AbstractEventLoopTest, RealtimeEventLoopTimer) {
   auto loop1 = MakePrimary();
 
diff --git a/aos/events/event_loop_tmpl.h b/aos/events/event_loop_tmpl.h
index b3c36cc..d206bc1 100644
--- a/aos/events/event_loop_tmpl.h
+++ b/aos/events/event_loop_tmpl.h
@@ -201,9 +201,9 @@
   return err;
 }
 
+template <typename T>
 inline monotonic_clock::time_point TimerHandler::Call(
-    std::function<monotonic_clock::time_point()> get_time,
-    monotonic_clock::time_point event_time) {
+    T get_time, monotonic_clock::time_point event_time) {
   const monotonic_clock::time_point monotonic_start_time = get_time();
 
   event_loop_->SetTimerContext(event_time);
diff --git a/aos/events/ping_lib.h b/aos/events/ping_lib.h
index 75d06e7..0b83d52 100644
--- a/aos/events/ping_lib.h
+++ b/aos/events/ping_lib.h
@@ -32,7 +32,7 @@
   // Last pong value received so we can detect missed pongs.
   int last_pong_value_ = 0;
 
-  bool quiet_ = false;
+  bool quiet_ = true;
 };
 
 }  // namespace aos
diff --git a/aos/events/pong_lib.cc b/aos/events/pong_lib.cc
index 77bd8d9..b274e58 100644
--- a/aos/events/pong_lib.cc
+++ b/aos/events/pong_lib.cc
@@ -11,7 +11,7 @@
     : event_loop_(event_loop),
       sender_(event_loop_->MakeSender<examples::Pong>("/test")) {
   event_loop_->MakeWatcher("/test", [this](const examples::Ping &ping) {
-    if (last_value_ == ping.value()) {
+    if (last_value_ == ping.value() && (!quiet_ || VLOG_IS_ON(1))) {
       LOG(WARNING) << "Duplicate ping value at " << last_value_
                    << " time difference " << ping.send_time() - last_send_time_;
     }
diff --git a/aos/events/pong_lib.h b/aos/events/pong_lib.h
index 7dc20d5..8b6641a 100644
--- a/aos/events/pong_lib.h
+++ b/aos/events/pong_lib.h
@@ -12,11 +12,15 @@
  public:
   Pong(EventLoop *event_loop);
 
+  void set_quiet(bool quiet) { quiet_ = quiet; }
+
  private:
   EventLoop *event_loop_;
   aos::Sender<examples::Pong> sender_;
   int32_t last_value_ = 0;
   int32_t last_send_time_ = 0;
+
+  bool quiet_ = true;
 };
 
 }  // namespace aos
diff --git a/aos/events/simulated_event_loop.cc b/aos/events/simulated_event_loop.cc
index e6bc28d..6bf3ec1 100644
--- a/aos/events/simulated_event_loop.cc
+++ b/aos/events/simulated_event_loop.cc
@@ -15,6 +15,10 @@
 #include "aos/realtime.h"
 #include "aos/util/phased_loop.h"
 
+// TODO(austin): If someone runs a SimulatedEventLoop on a RT thread with
+// die_on_malloc set, it won't die.  Really, we need to go RT, or fall back to
+// the base thread's original RT state to be actually accurate.
+
 namespace aos {
 
 class SimulatedEventLoop;
@@ -349,6 +353,10 @@
 
   void *data() override {
     if (!message_) {
+      // This API is safe to use in a RT context on a RT system.  So annotate it
+      // accordingly.
+      ScopedNotRealtime nrt;
+
       auto [span, mutable_span] =
           MakeSharedSpan(simulated_channel_->max_size());
       message_ = SimulatedMessage::Make(simulated_channel_, span);
@@ -1032,15 +1040,16 @@
     size_t length, monotonic_clock::time_point monotonic_remote_time,
     realtime_clock::time_point realtime_remote_time,
     uint32_t remote_queue_index, const UUID &source_boot_uuid) {
+  // The allocations in here are due to infrastructure and don't count in the
+  // no mallocs in RT code.
+  ScopedNotRealtime nrt;
+
   VLOG(1) << simulated_event_loop_->distributed_now() << " "
           << NodeName(simulated_event_loop_->node())
           << simulated_event_loop_->monotonic_now() << " "
           << simulated_event_loop_->name() << " Send "
           << configuration::StrippedChannelToString(channel());
 
-  // The allocations in here are due to infrastructure and don't count in the
-  // no mallocs in RT code.
-  ScopedNotRealtime nrt;
   CHECK_LE(length, size()) << ": Attempting to send too big a message.";
   message_->context.monotonic_event_time =
       simulated_event_loop_->monotonic_now();
@@ -1166,7 +1175,10 @@
     prev_logger.Swap(simulated_event_loop_->log_impl_);
   }
   if (token_ != scheduler_->InvalidToken()) {
-    scheduler_->Deschedule(token_);
+    {
+      ScopedNotRealtime nrt;
+      scheduler_->Deschedule(token_);
+    }
     token_ = scheduler_->InvalidToken();
   }
   if (repeat_offset_ != monotonic_clock::zero()) {
@@ -1186,7 +1198,10 @@
 void SimulatedTimerHandler::Disable() {
   simulated_event_loop_->RemoveEvent(&event_);
   if (token_ != scheduler_->InvalidToken()) {
-    scheduler_->Deschedule(token_);
+    {
+      ScopedNotRealtime nrt;
+      scheduler_->Deschedule(token_);
+    }
     token_ = scheduler_->InvalidToken();
   }
 }