made sure everything's thread safe

Pretty much everything already was, but I tweaked a few things to make
sure they stay that way and added various comments about that fact. Also
cleaned up a few things along the way and removed SafeMessageBuilder
because it wasn't.
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..89fa70a
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,7 @@
+This is the README.txt file for git. If you are looking at this file and you got it through SVN, somebody messed up and it should be fixed.
+
+This is team 971's code. We only keep code in this git repository. For details about how we use git, see doc/gitsetup.txt.
+
+You can get to this code in a web browser through <https://robotics.mvla.net/git971> (useful for ie sending links). You have to use your SVN credentials to log in there.
+
+aos/README.txt has some more details about what's where.
diff --git a/aos/README.txt b/aos/README.txt
index da70440..7bf0144 100644
--- a/aos/README.txt
+++ b/aos/README.txt
@@ -29,6 +29,7 @@
 	type of implementation, objects referred to by interrupt service routines activated by the signal function
 	would require explicit specification of volatile storage, as well as other implementation-defined
 	restrictions.
-Everything that has to do different things when compiled for the crio or linux uses #ifdef __VXWORKS__ etc.
-The crio "queue" implementation uses 1 global instance and no synchronization, so it should only be used in code that gets called by the crio-side control loop infrastructure.
+
 The C++ namespace aos is used for all of the aos code. The crio and linux_code namespaces are for APIs that only make sense on one platform or the other.
+
+Almost everything in aos/ is thread-safe. Files with a main() might not be, and some pieces of code explicitly say at their declaration that they aren't. Also, code which shares non-const pointers (including this) is not generally thread-safe. Other than those exceptions, everything is assumed to be thread-safe so the comments don't say so explicitly.
diff --git a/aos/build/aos.gyp b/aos/build/aos.gyp
index 3aaaf10..96cfc1b 100644
--- a/aos/build/aos.gyp
+++ b/aos/build/aos.gyp
@@ -7,9 +7,9 @@
 {
   'targets': [
     # A target for things used by the logging implementation (except die) to
-    # depend on that allows linking successfully with logging calls  but has no
-    # way to get initialized and so is basically useless unless something else
-    # links in the rest of the logging stuff.
+    # depend on that allows linking successfully with logging calls. However,
+    # executables containing targets that depend on this still need a dependency
+    # on logging somewhere or else they won't link.
     {
       'target_name': 'logging_interface',
       'type': 'static_library',
diff --git a/aos/build/queues/output/message_dec.rb b/aos/build/queues/output/message_dec.rb
index 40a2570..903a872 100644
--- a/aos/build/queues/output/message_dec.rb
+++ b/aos/build/queues/output/message_dec.rb
@@ -199,47 +199,27 @@
 		create_Print(type_class,cpp_tree)
 		create_GetType(type_class, cpp_tree)
 		create_DoGetType(type_class, cpp_tree)
-    create_DefaultConstructor(type_class, cpp_tree)
-    create_InOrderConstructor(type_class, cpp_tree)
+                create_DefaultConstructor(type_class, cpp_tree)
+                create_InOrderConstructor(type_class, cpp_tree)
 
 		b_namespace = cpp_tree.get(b_loc = self.class.builder_loc(@loc))
 
-		safetemplate = Types::TemplateClass.new(b_namespace,"SafeMessageBuilder")
-		ifdef_statement = Types::PreprocessorIf.new(b_namespace,"!defined(__VXWORKS__) && !defined(__TEST_VXWORKS__)")
-		ifdef_statement.add_member(safetemplate)
-		b_namespace.add(ifdef_statement)
 		template = b_namespace.add_template("MessageBuilder")
-		safetemplate.spec_args << t = @loc.to_cpp_id(@name)
 		template.spec_args << t = @loc.to_cpp_id(@name)
-		safemsg_ptr_t = "SafeScopedMessagePtr< #{t}>"
 		msg_ptr_t = "ScopedMessagePtr< #{t}>"
-		safemsg_bld_t = "SafeMessageBuilder< #{t}>"
 		msg_bld_t = "MessageBuilder< #{t}>"
-		safetemplate.add_member(:private,"#{safemsg_ptr_t} msg_ptr_")
 		template.add_member(:private,"#{msg_ptr_t} msg_ptr_")
 		template.add_member(:private,"#{msg_bld_t}(const #{msg_bld_t}&)")
 		template.add_member(:private,"void operator=(const #{msg_bld_t}&)")
-		safetemplate.add_member(:private,"friend class ::aos::Queue< #{t}>")
 		template.add_member(:private,"friend class ::aos::Queue< #{t}>")
 
 		cons = CPP::Constructor.new(template)
-		unsafe_cons = CPP::Constructor.new(template)
-		cons_ifdef_statement = CPP::PreprocessorIf.new(cons, unsafe_cons)
-		cons_ifdef_statement.name = "!defined(__VXWORKS__) && !defined(__TEST_VXWORKS__)"
-		template.add_member(:private,cons_ifdef_statement)
+		template.add_member(:private,cons)
 		cons.args << "RawQueue *queue"
 		cons.args << "#{t} *msg"
-		unsafe_cons.args << "#{t} *msg"
 		cons.add_cons("msg_ptr_","queue","msg")
-		unsafe_cons.add_cons("msg_ptr_","msg")
-		cons = safetemplate.add_member(:private,CPP::Constructor.new(safetemplate))
-		cons.args << "RawQueue *queue"
-		cons.add_cons("msg_ptr_","queue")
-		safetemplate.public
 		template.public
-		DefineMembers(cpp_tree, safetemplate, safemsg_bld_t)
 		DefineMembers(cpp_tree, template, msg_bld_t)
-
 	end
 	def DefineMembers(cpp_tree, template, msg_bld_t) 
 		send = template.def_func("bool","Send")
diff --git a/aos/build/queues/output/queue_dec.rb b/aos/build/queues/output/queue_dec.rb
index db4e1af..031c033 100644
--- a/aos/build/queues/output/queue_dec.rb
+++ b/aos/build/queues/output/queue_dec.rb
@@ -10,9 +10,6 @@
 		type = cpp_tree.get(@type)
 		return @type.loc.to_cpp_id(type.name)
 	end
-	def full_ptr_name(cpp_tree)
-		return "::aos::SafeScopedMessagePtr< #{full_message_name(cpp_tree)}>"
-	end
 	def full_builder_name(cpp_tree)
 		return "::aos::MessageBuilder< #{full_message_name(cpp_tree)}>"
 	end
diff --git a/aos/common/controls/polytope.h b/aos/common/controls/polytope.h
index 6afe04b..e37346e 100644
--- a/aos/common/controls/polytope.h
+++ b/aos/common/controls/polytope.h
@@ -19,6 +19,10 @@
         k_(k) {
   }
 
+  // This is an initialization function shared across all instantiations of this
+  // template.
+  // This must be called at least once before calling any of the methods. It is
+  // not thread-safe.
   static void Init() {
     dd_set_global_constants();
   }
diff --git a/aos/common/die.cc b/aos/common/die.cc
index e1b3b07..69b2aef 100644
--- a/aos/common/die.cc
+++ b/aos/common/die.cc
@@ -10,6 +10,7 @@
 #include <stdint.h>
 
 #include <string>
+#include <atomic>
 
 namespace aos {
 
@@ -45,7 +46,7 @@
 #endif
 }
 
-bool test_mode = false;
+::std::atomic_bool test_mode(false);
 
 }  // namespace
 
@@ -57,7 +58,7 @@
   fputs("aos fatal: ERROR!! details following\n", stderr);
   va_copy(args1, args_in);
   vfprintf(stderr, format, args1);
-  if (!test_mode) {
+  if (!test_mode.load()) {
     fputs("aos fatal: ERROR!! see stderr for details\n", stdout);
 
     const std::string filename = GetFilename();
@@ -78,7 +79,7 @@
 }
 
 void SetDieTestMode(bool new_test_mode) {
-  test_mode = new_test_mode;
+  test_mode.store(new_test_mode);
 }
 
 }  // namespace aos
diff --git a/aos/common/logging/logging_impl.cc b/aos/common/logging/logging_impl.cc
index f520b35..969c0ee 100644
--- a/aos/common/logging/logging_impl.cc
+++ b/aos/common/logging/logging_impl.cc
@@ -38,7 +38,7 @@
   Context *context = Context::Get();
 
   context->implementation = implementation;
-  global_top_implementation = implementation;
+  global_top_implementation.store(implementation);
 }
 
 void NewContext() {
diff --git a/aos/common/logging/logging_impl.h b/aos/common/logging/logging_impl.h
index a55e768..f24ce6a 100644
--- a/aos/common/logging/logging_impl.h
+++ b/aos/common/logging/logging_impl.h
@@ -11,6 +11,7 @@
 
 #include <string>
 #include <functional>
+#include <atomic>
 
 #include "aos/common/logging/logging.h"
 #include "aos/common/type_traits.h"
@@ -30,7 +31,8 @@
 //
 // It is implemented in logging_impl.cc and logging_interface.cc. They are
 // separate so that code used by logging_impl.cc can link in
-// logging_interface.cc to use logging.
+// logging_interface.cc to use logging without creating a circular dependency.
+// However, any executables with such code still need logging_impl.cc linked in.
 
 namespace aos {
 namespace logging {
@@ -250,10 +252,13 @@
 // goes.
 namespace internal {
 
-extern LogImplementation *global_top_implementation;
+extern ::std::atomic<LogImplementation *> global_top_implementation;
 
 // An separate instance of this class is accessible from each task/thread.
 // NOTE: It will get deleted in the child of a fork.
+//
+// Get() and Delete() are implemented in the platform-specific interface.cc
+// file.
 struct Context {
   Context();
 
@@ -267,6 +272,8 @@
   // Deletes the Context object for this task/thread so that the next Get() is
   // called it will create a new one.
   // It is valid to call this when Get() has never been called.
+  // This also gets called after a fork(2) in the new process, where it should
+  // still work to clean up any state.
   static void Delete();
 
   // Which one to log to right now.
diff --git a/aos/common/logging/logging_interface.cc b/aos/common/logging/logging_interface.cc
index 8c45afd..e4c6fcd 100644
--- a/aos/common/logging/logging_interface.cc
+++ b/aos/common/logging/logging_interface.cc
@@ -15,10 +15,10 @@
 namespace logging {
 namespace internal {
 
-LogImplementation *global_top_implementation(NULL);
+::std::atomic<LogImplementation *> global_top_implementation(NULL);
 
 Context::Context()
-    : implementation(global_top_implementation),
+    : implementation(global_top_implementation.load()),
       sequence(0) {
   cork_data.Reset();
 }
diff --git a/aos/common/macros.h b/aos/common/macros.h
index 21482f6..e8558b2 100644
--- a/aos/common/macros.h
+++ b/aos/common/macros.h
@@ -8,6 +8,7 @@
 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
   TypeName(const TypeName&) = delete;      \
   void operator=(const TypeName&) = delete
+
 // A macro to wrap arguments to macros that contain commas.
 // Useful for DISALLOW_COPY_AND_ASSIGNing templated types with multiple template
 // arguments.
diff --git a/aos/common/mutex.h b/aos/common/mutex.h
index a22df4e..ff953e4 100644
--- a/aos/common/mutex.h
+++ b/aos/common/mutex.h
@@ -30,7 +30,7 @@
   // Locks the mutex. If it fails, it calls LOG(FATAL).
   void Lock();
   // Unlocks the mutex. Fails like Lock.
-  // Multiple unlocking might be considered failure.
+  // Multiple unlocking is undefined.
   void Unlock();
   // Locks the mutex unless it is already locked.
   // Returns whether it succeeded or not.
@@ -55,7 +55,6 @@
 // A class that locks a Mutex when constructed and unlocks it when destructed.
 // Designed to be used as a local variable so that
 // the mutex will be unlocked when the scope is exited.
-// Should it fail for some reason, it dies with LOG(FATAL).
 class MutexLocker {
  public:
   explicit MutexLocker(Mutex *mutex) : mutex_(mutex) {
diff --git a/aos/common/queue.h b/aos/common/queue.h
index 33dc377..da2a180 100644
--- a/aos/common/queue.h
+++ b/aos/common/queue.h
@@ -3,17 +3,9 @@
 
 #include <assert.h>
 
-#if defined(__VXWORKS__) || defined(__TEST_VXWORKS__)
-#define USE_UNSAFE
-#else
-#undef USE_UNSAFE
-#endif
-
 #include "aos/common/time.h"
 #include "aos/common/macros.h"
-#ifndef USE_UNSAFE
 #include "aos/linux_code/ipc_lib/queue.h"
-#endif  // USE_UNSAFE
 #include "aos/common/time.h"
 
 namespace aos {
@@ -53,15 +45,11 @@
 template <class T> class Queue;
 template <class T> class MessageBuilder;
 template <class T> class ScopedMessagePtr;
-#ifndef USE_UNSAFE
-template <class T> class SafeMessageBuilder;
-template <class T> class SafeScopedMessagePtr;
-#endif  // USE_UNSAFE
 
 // A ScopedMessagePtr<> manages a queue message pointer.
 // It frees it properly when the ScopedMessagePtr<> goes out of scope or gets
 // sent.  By design, there is no way to get the ScopedMessagePtr to release the
-// message pointer.
+// message pointer to external code.
 template <class T>
 class ScopedMessagePtr {
  public:
@@ -116,7 +104,6 @@
     reset();
   }
 
-#ifndef SWIG
   // Implements a move constructor.  This only takes rvalue references
   // because we want to allow someone to say
   // ScopedMessagePtr<X> ptr = queue.MakeMessage();
@@ -126,14 +113,9 @@
   // clear out the source so there aren't 2 pointers to the message lying
   // around.
   ScopedMessagePtr(ScopedMessagePtr<T> &&ptr)
-    :
-#ifndef USE_UNSAFE
-    queue_(ptr.queue_),
-#endif  // USE_UNSAFE
-      msg_(ptr.msg_) {
+      : queue_(ptr.queue_), msg_(ptr.msg_) {
     ptr.msg_ = NULL;
   }
-#endif  // SWIG
 
  private:
   // Provide access to set_queue and the constructor for init.
@@ -141,27 +123,20 @@
   // Provide access to the copy constructor for MakeWithBuilder.
   friend class aos::MessageBuilder<T>;
 
-#ifndef USE_UNSAFE
-  // Only Queue should be able to build a queue.
+  // Only Queue should be able to build a message.
   ScopedMessagePtr(RawQueue *queue, T *msg)
       : queue_(queue), msg_(msg) {}
-#else
-  ScopedMessagePtr(T *msg)
-      : msg_(msg) {}
-#endif  // USE_UNSAFE
 
   // Sets the pointer to msg, freeing the old value if it was there.
   // This is private because nobody should be able to get a pointer to a message
   // that needs to be scoped without using the queue.
   void reset(T *msg = NULL);
 
-#ifndef USE_UNSAFE
   // Sets the queue that owns this message.
   void set_queue(RawQueue *queue) { queue_ = queue; }
 
   // The queue that the message is a part of.
   RawQueue *queue_;
-#endif  // USE_UNSAFE
   // The message or NULL.
   T *msg_;
 
@@ -171,8 +146,6 @@
 
 // Specializations for the Builders will be automatically generated in the .q.h
 // header files with all of the handy builder methods.
-// This builder uses an actual shm message pointer, which is more efficient and
-// more dangerous than the linux only SafeMessageBuilder.
 template <class T>
 class MessageBuilder {
  public:
@@ -182,21 +155,14 @@
 
 // TODO(aschuh): Base class
 // T must be a Message with the same format as the messages generated by
-// the q files.
+// the .q files.
 template <class T>
 class Queue {
  public:
   typedef T Message;
 
   Queue(const char *queue_name)
-      : queue_name_(queue_name),
-#ifdef USE_UNSAFE
-        queue_msg_(&msg_)
-#else
-        queue_(NULL),
-        queue_msg_(NULL, NULL)
-#endif  // USE_UNSAFE
-  {
+      : queue_name_(queue_name), queue_(NULL), queue_msg_(NULL, NULL) {
     static_assert(shm_ok<T>::value,
                   "The provided message type can't be put in shmem.");
   }
@@ -215,6 +181,9 @@
   // Returns true if there was a new message available and we successfully
   // fetched it.
   bool FetchNext();
+
+  // Fetches the next message from the queue, waiting if necessary until there
+  // is one.
   void FetchNextBlocking();
 
   // Fetches the last message from the queue.
@@ -227,16 +196,17 @@
   void FetchAnother();
 
   // Returns the age of the message.
-  const time::Time Age() { return time::Time::Now() - queue_msg_->sent_time; }
+  const time::Time Age() const { return time::Time::Now() - queue_msg_->sent_time; }
 
   // Returns true if the latest value in the queue is newer than age mseconds.
-  bool IsNewerThanMS(int age) {
+  // DEPRECATED(brians): Use IsNewerThan(const time::Time&) instead.
+  bool IsNewerThanMS(int age) const {
     // TODO(aschuh): Log very verbosely if something is _ever_ stale.
-    if (get() != NULL) {
-      return Age() < time::Time::InMS(age);
-    } else {
-      return false;
-    }
+    return IsNewerThan(time::Time::InMS(age));
+  }
+
+  bool IsNewerThan(const time::Time &age) const {
+    return get() != nullptr && Age() < age;
   }
 
   // Returns a pointer to the current message.
@@ -259,40 +229,26 @@
     return msg;
   }
 
-#ifndef USE_UNSAFE
-  // Returns a scoped_ptr containing a message.
-  // GCC will optimize away the copy constructor, so this is safe.
-  SafeScopedMessagePtr<T> SafeMakeMessage();
-
-  // Returns a message builder that contains a pre-allocated message.
-  aos::SafeMessageBuilder<T> SafeMakeWithBuilder();
-#endif  // USE_UNSAFE
-
-#ifndef SWIG
   // Returns a scoped_ptr containing a message.
   // GCC will optimize away the copy constructor, so this is safe.
   ScopedMessagePtr<T> MakeMessage();
 
   // Returns a message builder that contains a pre-allocated message.
   aos::MessageBuilder<T> MakeWithBuilder();
-#endif  // SWIG
 
   const char *name() const { return queue_name_; }
 
  private:
   const char *queue_name_;
 
-#ifdef USE_UNSAFE
-  // The unsafe queue only has 1 entry and no safety, so 1 message is fine.
-  T msg_;
-#else
   T *MakeRawMessage();
+
   // Pointer to the queue that this object fetches from.
   RawQueue *queue_;
   int index_ = 0;
-#endif
   // Scoped pointer holding the latest message or NULL.
   ScopedMessagePtr<const T> queue_msg_;
+
   DISALLOW_COPY_AND_ASSIGN(Queue<T>);
 };
 
@@ -315,11 +271,6 @@
 
 }  // namespace aos
 
-#ifdef USE_UNSAFE
-#include "aos/crio/queue-tmpl.h"
-#else
 #include "aos/linux_code/queue-tmpl.h"
-#endif
-#undef USE_UNSAFE
 
 #endif  // AOS_COMMON_QUEUE_H_
diff --git a/aos/common/queue_test.cc b/aos/common/queue_test.cc
index dfd18a2..36522f9 100644
--- a/aos/common/queue_test.cc
+++ b/aos/common/queue_test.cc
@@ -68,30 +68,6 @@
   EXPECT_EQ(0x971, my_test_queue->test_int);
 }
 
-// Tests that we can send a message with the message pointer and get it back.
-TEST_F(QueueTest, SendMessageBlockingSafe) {
-  SafeScopedMessagePtr<TestingMessage> msg = my_test_queue.SafeMakeMessage();
-  msg->test_bool = true;
-  msg->test_int = 0x971;
-  ASSERT_TRUE(msg.SendBlocking());
-
-  ASSERT_TRUE(my_test_queue.FetchLatest());
-  EXPECT_TRUE(my_test_queue->test_bool);
-  EXPECT_EQ(0x971, my_test_queue->test_int);
-}
-
-// Tests that we can send a message with the message pointer and get it back.
-TEST_F(QueueTest, SendMessageSafe) {
-  SafeScopedMessagePtr<TestingMessage> msg = my_test_queue.SafeMakeMessage();
-  msg->test_bool = true;
-  msg->test_int = 0x971;
-  msg.Send();
-
-  ASSERT_TRUE(my_test_queue.FetchLatest());
-  EXPECT_TRUE(my_test_queue->test_bool);
-  EXPECT_EQ(0x971, my_test_queue->test_int);
-}
-
 // Tests that we can send a message with the builder and get it back.
 TEST_F(QueueTest, SendWithBuilder) {
   my_test_queue.MakeWithBuilder().test_bool(true).test_int(0x971).Send();
diff --git a/aos/common/time.h b/aos/common/time.h
index 846366c..0440d91 100644
--- a/aos/common/time.h
+++ b/aos/common/time.h
@@ -205,8 +205,7 @@
   }
 
   // Enables returning the mock time value for Now instead of checking the
-  // system clock.  This should only be used when testing things depending on
-  // time, or many things may/will break.
+  // system clock.
   static void EnableMockTime(const Time &now = Now());
   // Calls SetMockTime with the current actual time.
   static void UpdateMockTime();
diff --git a/aos/linux_code/configuration.cc b/aos/linux_code/configuration.cc
index 55fff84..e4d5d80 100644
--- a/aos/linux_code/configuration.cc
+++ b/aos/linux_code/configuration.cc
@@ -44,6 +44,7 @@
   unique_c_ptr<ifaddrs, freeifaddrs> addrs_deleter(addrs);
 
   for (; addrs != nullptr; addrs = addrs->ifa_next) {
+    // ifa_addr tends to be nullptr on CAN interfaces.
     if (addrs->ifa_addr != nullptr && addrs->ifa_addr->sa_family == AF_INET) {
       if (strcmp(kLinuxNetInterface, addrs->ifa_name) == 0) {
         static const in_addr r =
diff --git a/aos/linux_code/core.cc b/aos/linux_code/core.cc
index 5b580ef..189df1d 100644
--- a/aos/linux_code/core.cc
+++ b/aos/linux_code/core.cc
@@ -13,7 +13,7 @@
 // Initializes shared memory. This is the only file that will create the shared
 // memory file if it doesn't already exist (and set everything up).
 //
-// Will also create the file given as a first argument.
+// Will also touch the file given as a first argument.
 
 int main(int argc, char **argv) {
   aos::InitCreate();
diff --git a/aos/linux_code/init.cc b/aos/linux_code/init.cc
index 05004a2..d8864fe 100644
--- a/aos/linux_code/init.cc
+++ b/aos/linux_code/init.cc
@@ -44,7 +44,7 @@
   WriteCoreDumps();
 }
 
-int LockAllMemory() {
+void LockAllMemory() {
   InitStart();
   if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
     PDie("%s-init: mlockall failed", program_invocation_short_name);
@@ -55,8 +55,6 @@
   uint8_t data[4096 * 8];
   // Not 0 because linux might optimize that to a 0-filled page.
   memset(data, 1, sizeof(data));
-
-  return 0;
 }
 
 // Do the initialization code that is necessary for both realtime and
@@ -76,11 +74,14 @@
 void Init(int relative_priority) {
   if (getenv(kNoRealtimeEnvironmentVariable) == NULL) {  // if nobody set it
     LockAllMemory();
+
     // Only let rt processes run for 3 seconds straight.
     SetSoftRLimit(RLIMIT_RTTIME, 3000000, true);
+
     // Allow rt processes up to priority 40.
     SetSoftRLimit(RLIMIT_RTPRIO, 40, false);
-    // Set our process to priority 40.
+
+    // Set our process to the appropriate priority.
     struct sched_param param;
     param.sched_priority = 30 + relative_priority;
     if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
diff --git a/aos/linux_code/init.h b/aos/linux_code/init.h
index c2b2635..538684e 100644
--- a/aos/linux_code/init.h
+++ b/aos/linux_code/init.h
@@ -3,6 +3,10 @@
 
 namespace aos {
 
+// In order to use shared memory, one of the Init* functions must be called in
+// exactly 1 thread per process. It is OK to keep going without calling one of
+// them again after fork(2)ing.
+
 // Does the non-realtime parts of the initialization process.
 void InitNRT();
 // Initializes everything, including the realtime stuff.
@@ -17,7 +21,8 @@
 void Cleanup();
 
 // Sets up this process to write core dump files.
-// This is called by Init*.
+// This is called by Init*, but it's here for other files that want this
+// behavior without calling Init*.
 void WriteCoreDumps();
 
 }  // namespace aos
diff --git a/aos/linux_code/ipc_lib/shared_mem.c b/aos/linux_code/ipc_lib/shared_mem.c
index a132233..e0be160 100644
--- a/aos/linux_code/ipc_lib/shared_mem.c
+++ b/aos/linux_code/ipc_lib/shared_mem.c
@@ -8,6 +8,7 @@
 #include <sys/types.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <assert.h>
 
 #include "aos/linux_code/ipc_lib/core_lib.h"
 #include "aos/common/logging/logging.h"
@@ -39,6 +40,7 @@
 
 // TODO(brians): madvise(2) it to put this shm in core dumps.
 void aos_core_create_shared_mem(enum aos_core_create to_create) {
+  assert(global_core == NULL);
   static struct aos_core global_core_data;
   global_core = &global_core_data;
 
diff --git a/aos/linux_code/ipc_lib/shared_mem.h b/aos/linux_code/ipc_lib/shared_mem.h
index 6968df7..33cb607 100644
--- a/aos/linux_code/ipc_lib/shared_mem.h
+++ b/aos/linux_code/ipc_lib/shared_mem.h
@@ -47,6 +47,7 @@
   reference
 };
 struct aos_core {
+  // Non-0 if we "own" shared_mem and should shm_unlink(3) it when we're done.
   int owner;
   void *shared_mem;
   // How large the chunk of shared memory is.
diff --git a/aos/linux_code/logging/linux_interface.cc b/aos/linux_code/logging/linux_interface.cc
index 9889c07..cbc114e 100644
--- a/aos/linux_code/logging/linux_interface.cc
+++ b/aos/linux_code/logging/linux_interface.cc
@@ -42,7 +42,7 @@
 }  // namespace
 
 Context *Context::Get() {
-  if (my_context == NULL) {
+  if (__builtin_expect(my_context == NULL, 0)) {
     my_context = new Context();
     my_context->name = GetMyName();
     if (my_context->name.size() + 1 > sizeof(LogMessage::name)) {
diff --git a/aos/linux_code/queue-tmpl.h b/aos/linux_code/queue-tmpl.h
index 64121f3..522bf6b 100644
--- a/aos/linux_code/queue-tmpl.h
+++ b/aos/linux_code/queue-tmpl.h
@@ -28,138 +28,6 @@
   msg_ = msg;
 }
 
-// A SafeScopedMessagePtr<> manages a message pointer.
-// It frees it properly when the ScopedMessagePtr<> goes out of scope or gets
-// sent.  By design, there is no way to get the ScopedMessagePtr to release the
-// message pointer.  When the message gets sent, it allocates a queue message,
-// copies the data into it, and then sends it.  Copies copy the message.
-template <class T>
-class SafeScopedMessagePtr {
- public:
-  // Returns a pointer to the message.
-  // This stays valid until Send or the destructor have been called.
-  T *get() { return msg_; }
-
-  T &operator*() {
-    T *msg = get();
-    assert(msg != NULL);
-    return *msg;
-  }
-
-  T *operator->() {
-    T *msg = get();
-    assert(msg != NULL);
-    return msg;
-  }
-
-  operator bool() {
-    return msg_ != NULL;
-  }
-
-  const T *get() const { return msg_; }
-
-  const T &operator*() const {
-    const T *msg = get();
-    assert(msg != NULL);
-    return *msg;
-  }
-
-  const T *operator->() const {
-    const T *msg = get();
-    assert(msg != NULL);
-    return msg;
-  }
-
-  // Sends the message and removes our reference to it.
-  // If the queue is full, over-rides the oldest message in it with our new
-  // message.
-  // Returns true on success, and false otherwise.
-  // The message will be freed.
-  bool Send() {
-    assert(msg_ != NULL);
-    assert(queue_ != NULL);
-    msg_->SetTimeToNow();
-    T *shm_msg = static_cast<T *>(queue_->GetMessage());
-    if (shm_msg == NULL) {
-      return false;
-    }
-    *shm_msg = *msg_;
-    bool return_value = queue_->WriteMessage(shm_msg, RawQueue::kOverride);
-    reset();
-    return return_value;
-  }
-
-  // Sends the message and removes our reference to it.
-  // If the queue is full, blocks until it is no longer full.
-  // Returns true on success, and false otherwise.
-  // Frees the message.
-  bool SendBlocking() {
-    assert(msg_ != NULL);
-    assert(queue_ != NULL);
-    msg_->SetTimeToNow();
-    T *shm_msg = static_cast<T *>(queue_->GetMessage());
-    if (shm_msg == NULL) {
-      return false;
-    }
-    *shm_msg = *msg_;
-    bool return_value = queue_->WriteMessage(shm_msg, RawQueue::kBlock);
-    reset();
-    return return_value;
-  }
-
-  // Frees the contained message.
-  ~SafeScopedMessagePtr() {
-    reset();
-  }
-
-  // Implements a move constructor to take the message pointer from the
-  // temporary object to save work.
-  SafeScopedMessagePtr(SafeScopedMessagePtr<T> &&ptr)
-    : queue_(ptr.queue_),
-      msg_(ptr.msg_) {
-    ptr.msg_ = NULL;
-  }
-
-  // Copy constructor actually copies the data.
-  SafeScopedMessagePtr(const SafeScopedMessagePtr<T> &ptr)
-      : queue_(ptr.queue_),
-        msg_(NULL) {
-    reset(new T(*ptr.get()));
-  }
-  // Equal operator copies the data.
-  void operator=(const SafeScopedMessagePtr<T> &ptr) {
-    queue_ = ptr.queue_;
-    reset(new T(*ptr.get()));
-  }
-
- private:
-  // Provide access to private constructor.
-  friend class aos::Queue<typename std::remove_const<T>::type>;
-  friend class aos::SafeMessageBuilder<T>;
-
-  // Only Queue should be able to build a message pointer.
-  SafeScopedMessagePtr(RawQueue *queue)
-      : queue_(queue), msg_(new T()) {}
-
-  // Sets the pointer to msg, freeing the old value if it was there.
-  // This is private because nobody should be able to get a pointer to a message
-  // that needs to be scoped without using the queue.
-  void reset(T *msg = NULL) {
-    if (msg_) {
-      delete msg_;
-    }
-    msg_ = msg;
-  }
-
-  // Sets the queue that owns this message.
-  void set_queue(RawQueue *queue) { queue_ = queue; }
-
-  // The queue that the message is a part of.
-  RawQueue *queue_;
-  // The message or NULL.
-  T *msg_;
-};
-
 template <class T>
 void Queue<T>::Init() {
   if (queue_ == NULL) {
@@ -223,14 +91,6 @@
 }
 
 template <class T>
-SafeScopedMessagePtr<T> Queue<T>::SafeMakeMessage() {
-  Init();
-  SafeScopedMessagePtr<T> safe_msg(queue_);
-  safe_msg->Zero();
-  return safe_msg;
-}
-
-template <class T>
 ScopedMessagePtr<T> Queue<T>::MakeMessage() {
   Init();
   return ScopedMessagePtr<T>(queue_, MakeRawMessage());
@@ -249,21 +109,4 @@
   return aos::MessageBuilder<T>(queue_, MakeRawMessage());
 }
 
-
-// This builder uses the safe message pointer so that it can be safely copied
-// in places where it could be leaked.
-template <class T>
-class SafeMessageBuilder {
- public:
-  typedef T Message;
-  bool Send();
-};
-
-template <class T>
-aos::SafeMessageBuilder<T> Queue<T>::SafeMakeWithBuilder() {
-  Init();
-  return aos::SafeMessageBuilder<T>(queue_);
-}
-
-
 }  // namespace aos
diff --git a/aos/prime/input/joystick_input.cc b/aos/prime/input/joystick_input.cc
index 6a6606e..7e2f0cd 100644
--- a/aos/prime/input/joystick_input.cc
+++ b/aos/prime/input/joystick_input.cc
@@ -70,7 +70,8 @@
           }
         }
       }
-
+    }
+    {
       using driver_station::ControlBit;
       if (data.PosEdge(ControlBit::kFmsAttached)) {
         LOG(INFO, "PosEdge(kFmsAttached)\n");
diff --git a/aos/prime/output/motor_output.cc b/aos/prime/output/motor_output.cc
index c02a11b..b6d59e2 100644
--- a/aos/prime/output/motor_output.cc
+++ b/aos/prime/output/motor_output.cc
@@ -51,6 +51,10 @@
     time::PhasedLoopXMS(5, 1000);
     ::aos::time::Time::UpdateMockTime();
 
+    no_robot_state_.Print();
+    fake_robot_state_.Print();
+    sending_failed_.Print();
+
     values_.digital_module = -1;
     // 0 means output disabled.
     memset(&values_.pwm_outputs, 0x00, sizeof(values_.pwm_outputs));
@@ -63,8 +67,12 @@
     RunIteration();
 
     ::aos::robot_state.FetchLatest();
-    if (!::aos::robot_state.get() || ::aos::robot_state->fake) {
-      LOG(DEBUG, "fake robot state -> not outputting\n");
+    if (!::aos::robot_state.get()) {
+      LOG_INTERVAL(no_robot_state_);
+      continue;
+    }
+    if (::aos::robot_state->fake) {
+      LOG_INTERVAL(fake_robot_state_);
       continue;
     }
 
@@ -75,7 +83,7 @@
       continue;
     }
     if (socket_.Send(buffer, size) != size) {
-      LOG(WARNING, "sending outputs failed\n");
+      LOG_INTERVAL(sending_failed_);
       continue;
     } else {
       LOG(DEBUG, "sent outputs\n");
diff --git a/aos/prime/output/motor_output.h b/aos/prime/output/motor_output.h
index 8c613e9..7d856bc 100644
--- a/aos/prime/output/motor_output.h
+++ b/aos/prime/output/motor_output.h
@@ -10,12 +10,13 @@
 #include "aos/common/network/send_socket.h"
 #include "aos/common/byteorder.h"
 #include "aos/common/type_traits.h"
+#include "aos/common/util/log_interval.h"
 
 namespace aos {
 
 // A class for sending output values to a cRIO.
 // values_ gets completely reset each time through, so RunIteration() needs to
-// set everything each time.
+// set everything each time (except solenoids).
 class MotorOutput {
  public:
   MotorOutput();
@@ -51,7 +52,7 @@
   void SetSolenoid(uint8_t channel, bool set);
   void SetPWMOutput(uint8_t channel, double value,
                     const MotorControllerBounds &bounds);
-  void SetRawPWMOutput(uint8_t cahnnel, uint8_t value);
+  void SetRawPWMOutput(uint8_t channel, uint8_t value);
   void DisablePWMOutput(uint8_t channel);
   void SetDigitalOutput(uint8_t channel, bool value);
 
@@ -65,6 +66,16 @@
   virtual void RunIteration() = 0;
 
   network::SendSocket socket_;
+
+  util::SimpleLogInterval no_robot_state_ =
+      util::SimpleLogInterval(::aos::time::Time::InSeconds(0.5), INFO,
+                        "no robot state -> not outputting");
+  util::SimpleLogInterval fake_robot_state_ =
+      util::SimpleLogInterval(::aos::time::Time::InSeconds(0.5), DEBUG,
+                        "fake robot state -> not outputting");
+  util::SimpleLogInterval sending_failed_ =
+      util::SimpleLogInterval(::aos::time::Time::InSeconds(0.1), WARNING,
+                        "sending outputs failed");
 };
 
 }  // namespace aos
diff --git a/aos/prime/output/output.gyp b/aos/prime/output/output.gyp
index 20fe699..1fadff0 100644
--- a/aos/prime/output/output.gyp
+++ b/aos/prime/output/output.gyp
@@ -12,10 +12,12 @@
         '<(EXTERNALS):WPILib-NetworkRobotValues',
         '<(AOS)/build/aos.gyp:logging',
         '<(AOS)/common/messages/messages.gyp:robot_state',
+        '<(AOS)/common/util/util.gyp:log_interval',
       ],
       'export_dependent_settings': [
         '<(AOS)/common/network/network.gyp:socket',
         '<(EXTERNALS):WPILib-NetworkRobotValues',
+        '<(AOS)/common/util/util.gyp:log_interval',
       ],
     },
     {