Merge changes I8675ec52,I2d8fd5b6

* changes:
  Sort wakeups and add send latency.
  Make raw senders able to send flatbuffers
diff --git a/WORKSPACE b/WORKSPACE
index e3e87ca..400fb87 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -365,9 +365,9 @@
     path = "third_party/ceres",
 )
 
-# Downloaded from http://devsite.ctr-electronics.com/maven/release/com/ctre/phoenix/api-cpp/5.14.1/.
+# Downloaded from http://devsite.ctr-electronics.com/maven/release/com/ctre/frcbeta/phoenix/api-cpp/5.17.1/.
 http_archive(
-    name = "ctre_phoenix_api_cpp_headers_2019",
+    name = "ctre_phoenix_api_cpp_headers",
     build_file_content = """
 cc_library(
     name = 'api-cpp',
@@ -375,15 +375,15 @@
     hdrs = glob(['ctre/phoenix/**/*.h']),
 )
 """,
-    sha256 = "f11f83ea6854229a1c4381d5e6a3917be6a062eb266ad14e4c4c9067ec3cd446",
+    sha256 = "b75761d13e367ece7a114237fc68670ed3b2f39daa4d4ff2a67f9e254d2ed39b",
     urls = [
-        "http://www.frc971.org/Build-Dependencies/api-cpp-5.14.1-headers.zip",
+        "http://www.frc971.org/Build-Dependencies/api-cpp-5.17.1-headers.zip",
     ],
 )
 
-# Downloaded from http://devsite.ctr-electronics.com/maven/release/com/ctre/phoenix/api-cpp/5.14.1/.
+# Downloaded from http://devsite.ctr-electronics.com/maven/release/com/ctre/frcbeta/phoenix/api-cpp/5.17.1/.
 http_archive(
-    name = "ctre_phoenix_api_cpp_athena_2019",
+    name = "ctre_phoenix_api_cpp_athena",
     build_file_content = """
 cc_library(
     name = 'api-cpp',
@@ -391,19 +391,52 @@
     srcs = ['linux/athena/static/libCTRE_Phoenix.a'],
     restricted_to = ['@//tools:roborio'],
     deps = [
-    '@ctre_phoenix_core_headers_2019//:core',
+      '@ctre_phoenix_core_headers//:core',
     ],
 )
 """,
-    sha256 = "0a976b86e887a75f0565fd7069db25e06ff0b76d2eebc294f23d81636b165381",
+    sha256 = "5678a1c6bf2af859bc5783040908b571dd1da63c6b1b5196610aa0cfa35ff9c3",
     urls = [
-        "http://www.frc971.org/Build-Dependencies/api-cpp-5.14.1-linuxathenastatic.zip",
+        "http://www.frc971.org/Build-Dependencies/api-cpp-5.17.1-linuxathenastatic.zip",
     ],
 )
 
-# Downloaded from http://devsite.ctr-electronics.com/maven/release/com/ctre/phoenix/cci/5.14.1/.
+# Downloaded from http://devsite.ctr-electronics.com/maven/release/com/ctre/frcbeta/phoenix/diagnostics/5.17.1/.
 http_archive(
-    name = "ctre_phoenix_cci_headers_2019",
+    name = "ctre_phoenix_diagnostics_headers",
+    build_file_content = """
+cc_library(
+    name = 'diagnostics',
+    visibility = ['//visibility:public'],
+    hdrs = glob(['ctre/phoenix/**/*.h']),
+)
+""",
+    sha256 = "c922f635df06ad7b2d8b2b3e72ce166a2238a9b28b7040a2963ed15fb61ec102",
+    urls = [
+        "http://www.frc971.org/Build-Dependencies/diagnostics-5.17.1-headers.zip",
+    ],
+)
+
+# Downloaded from http://devsite.ctr-electronics.com/maven/release/com/ctre/frcbeta/phoenix/diagnostics/5.17.1/.
+http_archive(
+    name = "ctre_phoenix_diagnostics_athena",
+    build_file_content = """
+cc_library(
+    name = 'diagnostics',
+    visibility = ['//visibility:public'],
+    srcs = ['linux/athena/static/libCTRE_PhoenixDiagnostics.a'],
+    restricted_to = ['@//tools:roborio'],
+)
+""",
+    sha256 = "d59c3dd4d841d769ba509b0ce993355745eb6ca1c86a660b476bf5d9c2532a9e",
+    urls = [
+        "http://www.frc971.org/Build-Dependencies/diagnostics-5.17.1-linuxathenastatic.zip",
+    ],
+)
+
+# Downloaded from http://devsite.ctr-electronics.com/maven/release/com/ctre/frcbeta/phoenix/cci/5.17.1/.
+http_archive(
+    name = "ctre_phoenix_cci_headers",
     build_file_content = """
 cc_library(
     name = 'cci',
@@ -411,15 +444,15 @@
     hdrs = glob(['ctre/phoenix/**/*.h']),
 )
 """,
-    sha256 = "0ce3d1cc916d9ebfcd19a5622736193cbac4f799205df155480943895ac78e45",
+    sha256 = "d43f6db7aa5165123e222568bdae794a182622d5a71181def355c7c08733dc7f",
     urls = [
-        "http://www.frc971.org/Build-Dependencies/cci-5.14.1-headers.zip",
+        "http://www.frc971.org/Build-Dependencies/cci-5.17.1-headers.zip",
     ],
 )
 
-# Downloaded from http://devsite.ctr-electronics.com/maven/release/com/ctre/phoenix/cci/5.14.1/.
+# Downloaded from http://devsite.ctr-electronics.com/maven/release/com/ctre/frcbeta/phoenix/cci/5.17.1/.
 http_archive(
-    name = "ctre_phoenix_cci_athena_2019",
+    name = "ctre_phoenix_cci_athena",
     build_file_content = """
 cc_library(
     name = 'cci',
@@ -428,15 +461,15 @@
     restricted_to = ['@//tools:roborio'],
 )
 """,
-    sha256 = "00b7e4abb1190924e9b31761951494264beebf4eefb64901000034dafaf2e8bc",
+    sha256 = "8dcf5a2b55747f8dc23556d61f1f6a7d5419e7c3336de97afa30dc89e07c6861",
     urls = [
-        "http://www.frc971.org/Build-Dependencies/cci-5.14.1-linuxathenastatic.zip",
+        "http://www.frc971.org/Build-Dependencies/cci-5.17.1-linuxathenastatic.zip",
     ],
 )
 
-# Downloaded from http://devsite.ctr-electronics.com/maven/release/com/ctre/phoenix/core/5.14.1/.
+# Downloaded from http://devsite.ctr-electronics.com/maven/release/com/ctre/frcbeta/phoenix/core/5.17.1/.
 http_archive(
-    name = "ctre_phoenix_core_headers_2019",
+    name = "ctre_phoenix_core_headers",
     build_file_content = """
 cc_library(
     name = 'core',
@@ -444,9 +477,9 @@
     hdrs = glob(['ctre/phoenix/**/*.h']),
 )
 """,
-    sha256 = "b74bf1bd5428cd6d7f7c3cf293b5bf8c009126eb2271d68ed070756427de5f7a",
+    sha256 = "552589ce2aebea1c6112babe3dd7476611eab1d8a0e48f777bd5c421f76857df",
     urls = [
-        "http://www.frc971.org/Build-Dependencies/core-5.14.1-headers.zip",
+        "http://www.frc971.org/Build-Dependencies/core-5.17.1-headers.zip",
     ],
 )
 
diff --git a/aos/BUILD b/aos/BUILD
index 7882244..ee0aa05 100644
--- a/aos/BUILD
+++ b/aos/BUILD
@@ -4,6 +4,7 @@
 filegroup(
     name = "prime_binaries",
     srcs = [
+        "//aos:aos_dump",
         "//aos:core",
         "//aos/logging:log_displayer",
         "//aos/logging:log_streamer",
@@ -28,7 +29,7 @@
         "//aos:core",
         "//aos/logging:log_streamer.stripped",
         "//aos/logging:log_displayer.stripped",
-        "//aos:log_fbs_shmem.stripped",
+        "//aos:aos_dump.stripped",
         "//aos/starter",
     ],
     visibility = ["//visibility:public"],
@@ -487,9 +488,9 @@
 )
 
 cc_binary(
-    name = "log_fbs_shmem",
+    name = "aos_dump",
     srcs = [
-        "log_fbs_shmem.cc",
+        "aos_dump.cc",
     ],
     visibility = ["//visibility:public"],
     deps = [
diff --git a/aos/log_fbs_shmem.cc b/aos/aos_dump.cc
similarity index 100%
rename from aos/log_fbs_shmem.cc
rename to aos/aos_dump.cc
diff --git a/aos/events/logging/logger.cc b/aos/events/logging/logger.cc
index e2da491..9968b80 100644
--- a/aos/events/logging/logger.cc
+++ b/aos/events/logging/logger.cc
@@ -1,6 +1,7 @@
 #include "aos/events/logging/logger.h"
 
 #include <fcntl.h>
+#include <limits.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/uio.h>
@@ -44,7 +45,10 @@
   queued_size_ += buffer.size();
   queue_.emplace_back(std::move(buffer));
 
-  if (queued_size_ > static_cast<size_t>(FLAGS_flush_size)) {
+  // Flush if we are at the max number of iovs per writev, or have written
+  // enough data.  Otherwise writev will fail with an invalid argument.
+  if (queued_size_ > static_cast<size_t>(FLAGS_flush_size) ||
+      queue_.size() == IOV_MAX) {
     Flush();
   }
 }
diff --git a/aos/events/logging/logger_test.cc b/aos/events/logging/logger_test.cc
index 1137e66..c627101 100644
--- a/aos/events/logging/logger_test.cc
+++ b/aos/events/logging/logger_test.cc
@@ -106,6 +106,47 @@
   reader.Deregister();
 }
 
+// Tests that a large number of messages per second doesn't overwhelm writev.
+TEST_F(LoggerTest, ManyMessages) {
+  const ::std::string tmpdir(getenv("TEST_TMPDIR"));
+  const ::std::string logfile = tmpdir + "/logfile.bfbs";
+  // Remove the log file.
+  unlink(logfile.c_str());
+
+  LOG(INFO) << "Logging data to " << logfile;
+
+  {
+    DetachedBufferWriter writer(logfile);
+    std::unique_ptr<EventLoop> logger_event_loop =
+        event_loop_factory_.MakeEventLoop("logger");
+
+    std::unique_ptr<EventLoop> ping_spammer_event_loop =
+        event_loop_factory_.MakeEventLoop("ping_spammer");
+    aos::Sender<examples::Ping> ping_sender =
+        ping_spammer_event_loop->MakeSender<examples::Ping>("/test");
+
+    aos::TimerHandler *timer_handler =
+        ping_spammer_event_loop->AddTimer([&ping_sender]() {
+          aos::Sender<examples::Ping>::Builder builder =
+              ping_sender.MakeBuilder();
+          examples::Ping::Builder ping_builder =
+              builder.MakeBuilder<examples::Ping>();
+          CHECK(builder.Send(ping_builder.Finish()));
+        });
+
+    // 100 ms / 0.05 ms -> 2000 messages.  Should be enough to crash it.
+    ping_spammer_event_loop->OnRun([&ping_spammer_event_loop, timer_handler]() {
+      timer_handler->Setup(ping_spammer_event_loop->monotonic_now(),
+                           chrono::microseconds(50));
+    });
+
+    Logger logger(&writer, logger_event_loop.get(),
+                  std::chrono::milliseconds(100));
+
+    event_loop_factory_.RunFor(chrono::milliseconds(1000));
+  }
+}
+
 }  // namespace testing
 }  // namespace logger
 }  // namespace aos
diff --git a/aos/ipc_lib/queue_racer.cc b/aos/ipc_lib/queue_racer.cc
index f3b9d5c..350350c 100644
--- a/aos/ipc_lib/queue_racer.cc
+++ b/aos/ipc_lib/queue_racer.cc
@@ -46,8 +46,7 @@
   // Event used to start all the threads processing at once.
   Event run;
 
-  ::std::atomic<bool> poll_index;
-  poll_index = true;
+  ::std::atomic<bool> poll_index{true};
 
   // List of threads.
   ::std::vector<ThreadState> threads(num_threads_);
@@ -87,10 +86,11 @@
       const uint64_t started_writes = started_writes_.load();
 
       const uint32_t latest_queue_index_uint32_t =
-          queue.LatestQueueIndex().index();
+          latest_queue_index_queue_index.index();
       uint64_t latest_queue_index = latest_queue_index_uint32_t;
 
-      if (latest_queue_index_queue_index != LocklessQueue::empty_queue_index()) {
+      if (latest_queue_index_queue_index !=
+          LocklessQueue::empty_queue_index()) {
         // If we got smaller, we wrapped.
         if (latest_queue_index_uint32_t < last_queue_index) {
           ++wrap_count;
@@ -112,10 +112,12 @@
         EXPECT_EQ(finished_writes, 0);
       } else {
         if (finished_writes == 0) {
-          // Plausible to be at the beginning.
+          // Plausible to be at the beginning, in which case we don't have
+          // anything to check.
           if (latest_queue_index_queue_index !=
               LocklessQueue::empty_queue_index()) {
-            // Otherwise, we have started.  The queue is always allowed to
+            // Otherwise, we have started.  The queue can't have any more
+            // entries than this.
             EXPECT_GE(started_writes, latest_queue_index + 1);
           }
         } else {
@@ -150,7 +152,9 @@
           run.Wait();
 
           // Gogogo!
-          for (uint64_t i = 0; i < num_messages_ * static_cast<uint64_t>(1 + write_wrap_count); ++i) {
+          for (uint64_t i = 0;
+               i < num_messages_ * static_cast<uint64_t>(1 + write_wrap_count);
+               ++i) {
             char data[sizeof(ThreadPlusCount)];
             ThreadPlusCount tpc;
             tpc.thread = thread_index;
diff --git a/aos/logging/BUILD b/aos/logging/BUILD
index d56cf8e..1aaa2db 100644
--- a/aos/logging/BUILD
+++ b/aos/logging/BUILD
@@ -143,7 +143,7 @@
         ":sizes",
         "//aos:die",
         "//aos:macros",
-        "//aos:once",
+        "@com_google_absl//absl/base",
         "//aos/ipc_lib:queue",
         "//aos/mutex",
         "//aos/time",
diff --git a/aos/logging/implementations.cc b/aos/logging/implementations.cc
index 2220e4e..5b324b1 100644
--- a/aos/logging/implementations.cc
+++ b/aos/logging/implementations.cc
@@ -10,7 +10,7 @@
 #include "aos/logging/printf_formats.h"
 #include "aos/time/time.h"
 #include "aos/ipc_lib/queue.h"
-#include "aos/once.h"
+#include "absl/base/call_once.h"
 
 namespace aos {
 namespace logging {
@@ -67,15 +67,13 @@
   internal::Context::Delete();
 }
 
-void *DoInit() {
+void DoInit() {
   SetGlobalImplementation(root_implementation = new RootLogImplementation());
 
   if (pthread_atfork(NULL /*prepare*/, NULL /*parent*/,
                      NewContext /*child*/) != 0) {
     AOS_LOG(FATAL, "pthread_atfork(NULL, NULL, %p) failed\n", NewContext);
   }
-
-  return NULL;
 }
 
 }  // namespace
@@ -163,8 +161,8 @@
 }
 
 void Init() {
-  static Once<void> once(DoInit);
-  once.Get();
+  static absl::once_flag once;
+  absl::call_once(once, DoInit);
 }
 
 void Load() {
diff --git a/debian/ni-libraries.BUILD b/debian/ni-libraries.BUILD
index 8c10587..9661248 100644
--- a/debian/ni-libraries.BUILD
+++ b/debian/ni-libraries.BUILD
@@ -16,6 +16,7 @@
     includes = [
         "src/include",
     ],
+    linkopts = ["-ldl"],
     linkstatic = True,
     restricted_to = ["@//tools:roborio"],
     visibility = ["//visibility:public"],
diff --git a/debian/slycot.BUILD b/debian/slycot.BUILD
index 41e7be2..393de22 100644
--- a/debian/slycot.BUILD
+++ b/debian/slycot.BUILD
@@ -141,6 +141,7 @@
         "clang": [
         ],
         "gcc": [
+            "-Wno-unused-but-set-variable",
             "-Wno-discarded-qualifiers",
         ],
     }),
diff --git a/frc971/control_loops/drivetrain/drivetrain.cc b/frc971/control_loops/drivetrain/drivetrain.cc
index 78cb378..42f0935 100644
--- a/frc971/control_loops/drivetrain/drivetrain.cc
+++ b/frc971/control_loops/drivetrain/drivetrain.cc
@@ -54,6 +54,7 @@
       right_high_requested_(dt_config_.default_high_gear) {
   ::aos::controls::HPolytope<0>::Init();
   down_U_.setZero();
+  event_loop->SetRuntimeRealtimePriority(30);
 }
 
 int DrivetrainLoop::ControllerIndexFromGears() {
diff --git a/frc971/wpilib/ahal/RobotBase.h b/frc971/wpilib/ahal/RobotBase.h
index df91525..24e2898 100644
--- a/frc971/wpilib/ahal/RobotBase.h
+++ b/frc971/wpilib/ahal/RobotBase.h
@@ -33,7 +33,8 @@
   }
 #else
 #define START_ROBOT_CLASS(_ClassName_)                                       \
-  int main() {                                                               \
+  int main(int argc, char *argv[]) {                                         \
+    ::aos::InitGoogle(&argc, &argv);                                         \
     if (!HAL_Initialize(500, 0)) {                                           \
       std::cerr << "FATAL ERROR: HAL could not be initialized" << std::endl; \
       return -1;                                                             \
diff --git a/third_party/BUILD b/third_party/BUILD
index d67d4b4..6bb5f9c 100644
--- a/third_party/BUILD
+++ b/third_party/BUILD
@@ -18,9 +18,11 @@
     restricted_to = ["//tools:roborio"],
     visibility = ["//visibility:public"],
     deps = [
-        "@ctre_phoenix_api_cpp_athena_2019//:api-cpp",
-        "@ctre_phoenix_api_cpp_headers_2019//:api-cpp",
-        "@ctre_phoenix_cci_athena_2019//:cci",
-        "@ctre_phoenix_cci_headers_2019//:cci",
+        "@ctre_phoenix_api_cpp_athena//:api-cpp",
+        "@ctre_phoenix_api_cpp_headers//:api-cpp",
+        "@ctre_phoenix_cci_athena//:cci",
+        "@ctre_phoenix_cci_headers//:cci",
+        "@ctre_phoenix_diagnostics_athena//:diagnostics",
+        "@ctre_phoenix_diagnostics_headers//:diagnostics",
     ],
 )
diff --git a/y2019/control_loops/superstructure/superstructure.cc b/y2019/control_loops/superstructure/superstructure.cc
index 91e1704..4246397 100644
--- a/y2019/control_loops/superstructure/superstructure.cc
+++ b/y2019/control_loops/superstructure/superstructure.cc
@@ -25,7 +25,9 @@
       elevator_(constants::GetValues().elevator.subsystem_params),
       wrist_(constants::GetValues().wrist.subsystem_params),
       intake_(constants::GetValues().intake),
-      stilts_(constants::GetValues().stilts.subsystem_params) {}
+      stilts_(constants::GetValues().stilts.subsystem_params) {
+  event_loop->SetRuntimeRealtimePriority(30);
+}
 
 void Superstructure::RunIteration(const Goal *unsafe_goal,
                                   const Position *position,