added more multithreaded tests that are useful with tsan

Also made various small cleanups while writing and checking these tests.
diff --git a/aos/common/util/run_command_test.cc b/aos/common/util/run_command_test.cc
index b440e47..daff3c5 100644
--- a/aos/common/util/run_command_test.cc
+++ b/aos/common/util/run_command_test.cc
@@ -2,6 +2,8 @@
 
 #include "gtest/gtest.h"
 
+#include "aos/common/util/thread.h"
+
 namespace aos {
 namespace util {
 namespace testing {
@@ -34,6 +36,26 @@
   EXPECT_EQ(SIGQUIT, WTERMSIG(result));
 }
 
+TEST(RunCommandTest, MultipleThreads) {
+  int result1, result2;
+  util::FunctionThread t1([&result1](util::Thread *) {
+    result1 = RunCommand("true");
+  });
+  util::FunctionThread t2([&result2](util::Thread *) {
+    result2 = RunCommand("true");
+  });
+  t1.Start();
+  t2.Start();
+  t1.WaitUntilDone();
+  t2.WaitUntilDone();
+  ASSERT_NE(-1, result1);
+  ASSERT_NE(-1, result2);
+  ASSERT_TRUE(WIFEXITED(result1));
+  ASSERT_TRUE(WIFEXITED(result2));
+  EXPECT_EQ(0, WEXITSTATUS(result1));
+  EXPECT_EQ(0, WEXITSTATUS(result2));
+}
+
 }  // namespace testing
 }  // namespace util
 }  // namespace aos
diff --git a/aos/common/util/thread.cc b/aos/common/util/thread.cc
index fab62eb..dbb638e 100644
--- a/aos/common/util/thread.cc
+++ b/aos/common/util/thread.cc
@@ -1,7 +1,8 @@
 #include "aos/common/util/thread.h"
 
 #include <pthread.h>
-#include <assert.h>
+
+#include "aos/common/logging/logging.h"
 
 namespace aos {
 namespace util {
@@ -10,24 +11,30 @@
 
 Thread::~Thread() {
   if (started_ && !joined_) {
-    assert(false);
+    CHECK(false);
   }
 }
 
 void Thread::Start() {
-  assert(!started_);
+  CHECK(!started_);
   started_ = true;
-  assert(pthread_create(&thread_, NULL, &Thread::StaticRun, this) == 0);
+  CHECK(pthread_create(&thread_, NULL, &Thread::StaticRun, this) == 0);
 }
 
 void Thread::Join() {
-  assert(!joined_ && started_);
+  CHECK(!joined_ && started_);
   joined_ = true;
   {
     MutexLocker locker(&should_terminate_mutex_);
     should_terminate_ = true;
   }
-  assert(pthread_join(thread_, NULL) == 0);
+  CHECK(pthread_join(thread_, NULL) == 0);
+}
+
+void Thread::WaitUntilDone() {
+  CHECK(!joined_ && started_);
+  joined_ = true;
+  CHECK(pthread_join(thread_, NULL) == 0);
 }
 
 void *Thread::StaticRun(void *self) {
diff --git a/aos/common/util/thread.h b/aos/common/util/thread.h
index ab6f09c..97123d5 100644
--- a/aos/common/util/thread.h
+++ b/aos/common/util/thread.h
@@ -1,7 +1,10 @@
 #ifndef AOS_COMMON_UTIL_THREAD_H_
 #define AOS_COMMON_UTIL_THREAD_H_
 
+#include <functional>
+
 #include "aos/common/mutex.h"
+#include "aos/common/macros.h"
 
 namespace aos {
 namespace util {
@@ -20,6 +23,9 @@
   // Asks the code to stop and then waits until it has done so.
   void Join();
 
+  // Waits until the code has stopped. Does not ask it to do so.
+  void WaitUntilDone();
+
  protected:
   // Subclasses need to call this periodically if they are going to loop to
   // check whether they have been asked to stop.
@@ -42,6 +48,21 @@
   bool joined_;
   bool should_terminate_;
   Mutex should_terminate_mutex_;
+
+  DISALLOW_COPY_AND_ASSIGN(Thread);
+};
+
+class FunctionThread : public Thread {
+ public:
+  FunctionThread(::std::function<void(FunctionThread *)> function)
+      : function_(function) {}
+
+ private:
+  virtual void Run() override {
+    function_(this);
+  }
+
+  const ::std::function<void(FunctionThread *)> function_;
 };
 
 }  // namespace util
diff --git a/aos/common/util/util.gyp b/aos/common/util/util.gyp
index 7c0adf3..fb29d7f 100644
--- a/aos/common/util/util.gyp
+++ b/aos/common/util/util.gyp
@@ -20,6 +20,7 @@
         'run_command',
         '<(EXTERNALS):gtest',
         '<(AOS)/build/aos.gyp:logging',
+        'thread',
       ],
     },
     {