copying branch over from other 2013 repo
diff --git a/aos/atom_code/atom_code.gyp b/aos/atom_code/atom_code.gyp
new file mode 100644
index 0000000..8253588
--- /dev/null
+++ b/aos/atom_code/atom_code.gyp
@@ -0,0 +1,16 @@
+{
+  'targets': [
+    {
+      'target_name': 'init',
+      'type': 'static_library',
+      'sources': [
+        '<(AOS)/atom_code/init.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/atom_code/ipc_lib/ipc_lib.gyp:ipc_lib',
+        '<(AOS)/common/common.gyp:die',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+    },
+  ],
+}
diff --git a/aos/atom_code/camera/Buffers.cpp b/aos/atom_code/camera/Buffers.cpp
index 22b7337..f580f89 100644
--- a/aos/atom_code/camera/Buffers.cpp
+++ b/aos/atom_code/camera/Buffers.cpp
@@ -1,8 +1,10 @@
-#include "Buffers.h"
-#include "V4L2.h"
+#include "aos/atom_code/camera/Buffers.h"
 
 #include <sys/mman.h>
 
+#include "aos/atom_code/camera/V4L2.h"
+#include "aos/common/logging/logging.h"
+
 namespace aos {
 namespace camera {
 
diff --git a/aos/atom_code/camera/Buffers.h b/aos/atom_code/camera/Buffers.h
index 7f1206d..b72cd3e 100644
--- a/aos/atom_code/camera/Buffers.h
+++ b/aos/atom_code/camera/Buffers.h
@@ -6,7 +6,7 @@
 
 #include <string>
 
-#include "aos/aos_core.h"
+#include "aos/atom_code/ipc_lib/queue.h"
 #include "aos/common/type_traits.h"
 
 namespace aos {
diff --git a/aos/atom_code/camera/camera.gyp b/aos/atom_code/camera/camera.gyp
index e94a6ac..b8e8dd3 100644
--- a/aos/atom_code/camera/camera.gyp
+++ b/aos/atom_code/camera/camera.gyp
@@ -43,13 +43,28 @@
       'hard_dependency': 1,
     },
     {
+      'target_name': 'buffers',
+      'type': 'static_library',
+      'sources': [
+        'Buffers.cpp',
+      ],
+      'dependencies': [
+        '<(AOS)/atom_code/ipc_lib/ipc_lib.gyp:ipc_lib',
+        '<(AOS)/build/aos.gyp:logging',
+      ],
+      'export_dependent_settings': [
+        '<(AOS)/atom_code/ipc_lib/ipc_lib.gyp:ipc_lib',
+      ],
+    },
+    {
       'target_name': 'CameraHTTPStreamer',
       'type': 'executable',
       'sources': [
         'HTTPStreamer.cpp',
       ],
       'dependencies': [
-        '<(AOS)/build/aos.gyp:libaos',
+        'buffers',
+        '<(AOS)/atom_code/atom_code.gyp:init',
       ],
     },
     {
@@ -59,7 +74,8 @@
         'Reader.cpp',
       ],
       'dependencies': [
-        '<(AOS)/build/aos.gyp:libaos',
+        'buffers',
+        '<(AOS)/atom_code/atom_code.gyp:init',
       ],
     },
   ],
diff --git a/aos/atom_code/camera/jni.cpp b/aos/atom_code/camera/jni.cpp
index 7b7eafa..ad5177a 100644
--- a/aos/atom_code/camera/jni.cpp
+++ b/aos/atom_code/camera/jni.cpp
@@ -3,6 +3,8 @@
 #include "jni/aos_Natives.h"
 #include "aos/atom_code/camera/Buffers.h"
 #include "aos/externals/libjpeg/include/jpeglib.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/atom_code/init.h"
 
 using aos::camera::Buffers;
 
@@ -248,8 +250,8 @@
   } else {
     level = DEBUG;
   }
-  // can't use Get/ReleaseStringCritical because log_do might block waiting to
-  // put its message into the queue
+  // Can't use Get/ReleaseStringCritical because log_do might block waiting to
+  // put its message into the queue.
   const char *const message_chars = env->GetStringUTFChars(message, NULL);
   if (message_chars == NULL) return;
   log_do(level, "%s\n", message_chars);
diff --git a/aos/atom_code/core/BinaryLogReader.cpp b/aos/atom_code/core/BinaryLogReader.cpp
index b673c26..7027d21 100644
--- a/aos/atom_code/core/BinaryLogReader.cpp
+++ b/aos/atom_code/core/BinaryLogReader.cpp
@@ -11,16 +11,20 @@
 
 #include <map>
 
-#include "aos/aos_core.h"
+#include "aos/atom_code/logging/atom_logging.h"
 #include "aos/atom_code/core/LogFileCommon.h"
 #include "aos/common/Configuration.h"
+#include "aos/atom_code/init.h"
 
-static const char *const kCRIOName = "CRIO";
+namespace aos {
+namespace logging {
+namespace atom {
+namespace {
 
-int main() {
-  aos::InitNRT();
+int binary_log_reader_main() {
+  InitNRT();
 
-  const char *folder = aos::configuration::GetLoggingDirectory();
+  const char *folder = configuration::GetLoggingDirectory();
   if (access(folder, R_OK | W_OK) == -1) {
     LOG(FATAL, "folder '%s' does not exist. please create it\n", folder);
   }
@@ -28,19 +32,24 @@
 
   const time_t t = time(NULL);
   char *tmp;
-  if (asprintf(&tmp, "%s/aos_log-%jd", folder, static_cast<uintmax_t>(t)) == -1) {
-    fprintf(stderr, "BinaryLogReader: couldn't create final name because of %d (%s)."
+  if (asprintf(&tmp, "%s/aos_log-%jd", folder, static_cast<uintmax_t>(t)) ==
+      -1) {
+    fprintf(stderr,
+            "BinaryLogReader: couldn't create final name because of %d (%s)."
             " exiting\n", errno, strerror(errno));
     return EXIT_FAILURE;
   }
   char *tmp2;
   if (asprintf(&tmp2, "%s/aos_log-current", folder) == -1) {
-    fprintf(stderr, "BinaryLogReader: couldn't create symlink name because of %d (%s)."
+    fprintf(stderr,
+            "BinaryLogReader: couldn't create symlink name because of %d (%s)."
             " not creating current symlink\n", errno, strerror(errno));
   } else {
     if (unlink(tmp2) == -1 && (errno != EROFS && errno != ENOENT)) {
-      fprintf(stderr, "BinaryLogReader: warning: unlink('%s') failed because of %d (%s)\n",
-          tmp2, errno, strerror(errno));
+      fprintf(stderr,
+              "BinaryLogReader: warning: unlink('%s') failed"
+              " because of %d (%s)\n",
+              tmp2, errno, strerror(errno));
     }
     if (symlink(tmp, tmp2) == -1) {
       fprintf(stderr, "BinaryLogReader: warning: symlink('%s', '%s') failed"
@@ -52,11 +61,12 @@
                 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
   free(tmp);
   if (fd == -1) {
-    fprintf(stderr, "BinaryLogReader: couldn't open file '%s' because of %d (%s)."
+    fprintf(stderr,
+            "BinaryLogReader: couldn't open file '%s' because of %d (%s)."
             " exiting\n", tmp, errno, strerror(errno));
     return EXIT_FAILURE;
   }
-  aos::LogFileAccessor writer(fd, true);
+  LogFileAccessor writer(fd, true);
 
   struct timespec timespec;
   time_t last_sec = 0;
@@ -68,47 +78,39 @@
       writer.Sync();
     }
 
-    const log_message *const msg = log_read_next();
+    const LogMessage *const msg = ReadNext();
     if (msg == NULL) continue;
-    const log_crio_message *const crio_msg = reinterpret_cast<const log_crio_message *>(
-        msg);
 
-    size_t name_size, message_size;
-    if (msg->source == -1) {
-      name_size = strlen(kCRIOName);
-      message_size = strlen(crio_msg->message);
-    } else {
-      name_size = strlen(msg->name);
-      message_size = strlen(msg->message);
-    }
-    // add on size for terminating '\0'
-    name_size += 1;
-    message_size += 1;
+    // add 1 for terminating '\0'
+    size_t name_size = strlen(msg->name) + 1;
+    size_t message_size = strlen(msg->message) + 1;
 
-    aos::LogFileMessageHeader *const output = writer.GetWritePosition(
-        sizeof(aos::LogFileMessageHeader) + name_size + message_size);
+    LogFileMessageHeader *const output = writer.GetWritePosition(
+        sizeof(LogFileMessageHeader) + name_size + message_size);
     char *output_strings = reinterpret_cast<char *>(output) + sizeof(*output);
     output->name_size = name_size;
     output->message_size = message_size;
     output->source = msg->source;
-    if (msg->source == -1) {
-      output->level = crio_msg->level;
-      // TODO(brians) figure out what time to put in
-      output->sequence = crio_msg->sequence;
-      memcpy(output_strings, kCRIOName, name_size);
-      memcpy(output_strings + name_size, crio_msg->message, message_size);
-    } else {
-      output->level = msg->level;
-      output->time_sec = msg->time.tv_sec;
-      output->time_nsec = msg->time.tv_nsec;
-      output->sequence = msg->sequence;
-      memcpy(output_strings, msg->name, name_size);
-      memcpy(output_strings + name_size, msg->message, message_size);
-    }
+    output->level = msg->level;
+    output->time_sec = msg->seconds;
+    output->time_nsec = msg->nseconds;
+    output->sequence = msg->sequence;
+    memcpy(output_strings, msg->name, name_size);
+    memcpy(output_strings + name_size, msg->message, message_size);
     condition_set(&output->marker);
 
-    log_free_message(msg);
+    logging::atom::Free(msg);
   }
 
-  aos::Cleanup();
+  Cleanup();
+  return 0;
+}
+
+}  // namespace
+}  // namespace atom
+}  // namespace logging
+}  // namespace aos
+
+int main() {
+  return aos::logging::atom::binary_log_reader_main();
 }
diff --git a/aos/atom_code/core/CRIOLogReader.cpp b/aos/atom_code/core/CRIOLogReader.cpp
index f32e21d..2aa216c 100644
--- a/aos/atom_code/core/CRIOLogReader.cpp
+++ b/aos/atom_code/core/CRIOLogReader.cpp
@@ -8,44 +8,55 @@
 #include <fcntl.h>
 #include <arpa/inet.h>
 #include <errno.h>
+#include <string.h>
 
 #include <map>
 
-#include "aos/aos_core.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/atom_code/logging/atom_logging.h"
 #include "aos/common/Configuration.h"
 #include "aos/common/byteorder.h"
+#include "aos/atom_code/init.h"
+
+namespace aos {
+namespace logging {
+namespace atom {
+namespace {
 
 struct log_buffer {
-  log_crio_message msg;
+  LogMessage *msg;
   size_t used;
 
-  log_buffer() {
+  log_buffer() : msg(NULL) {
     Clear();
   }
   void Clear() {
+    logging::atom::Free(msg);
+    msg = logging::atom::Get();
     used = 0;
   }
-  // returns whether msg is now complete
+
+  // Returns whether msg is now complete.
   bool ReceiveFrom(int sock) {
-    const ssize_t ret = recv(sock, reinterpret_cast<uint8_t *>(&msg) + used,
-                             sizeof(msg) - used, 0);
+    const ssize_t ret = recv(sock, reinterpret_cast<uint8_t *>(msg) + used,
+                             sizeof(*msg) - used, 0);
     if (ret == -1) {
       LOG(ERROR, "recv(%d, %p, %d) failed because of %d: %s\n",
-          sock, reinterpret_cast<uint8_t *>(&msg) + used, sizeof(msg) - used,
+          sock, reinterpret_cast<uint8_t *>(msg) + used, sizeof(*msg) - used,
           errno, strerror(errno));
       return false;
     } else {
       used += ret;
-      if (used > sizeof(msg)) {
-        LOG(WARNING, "used(%zd) is > sizeof(msg)(%zd)\n", used, sizeof(msg));
+      if (used > sizeof(*msg)) {
+        LOG(WARNING, "used(%zd) is > sizeof(*msg)(%zd)\n", used, sizeof(*msg));
       }
-      return used >= sizeof(msg);
+      return used >= sizeof(*msg);
     }
   }
 };
 
-int main() {
-  aos::InitNRT();
+int crio_log_reader_main() {
+  InitNRT();
 
   const int sock = socket(AF_INET, SOCK_STREAM, 0);
   if (sock == -1) {
@@ -59,11 +70,11 @@
   } bind_sockaddr;
   memset(&bind_sockaddr, 0, sizeof(bind_sockaddr));
   bind_sockaddr.in.sin_family = AF_INET;
-  bind_sockaddr.in.sin_port = htons(static_cast<uint16_t>(aos::NetworkPort::kLogs));
+  bind_sockaddr.in.sin_port = htons(static_cast<uint16_t>(NetworkPort::kLogs));
   bind_sockaddr.in.sin_addr.s_addr = htonl(INADDR_ANY);
   if (bind(sock, &bind_sockaddr.addr, sizeof(bind_sockaddr.addr)) == -1) {
-    LOG(ERROR, "bind(%d, %p) failed because of %d: %s\n", sock, &bind_sockaddr.addr,
-        errno, strerror(errno));
+    LOG(ERROR, "bind(%d, %p) failed because of %d: %s\n", sock,
+        &bind_sockaddr.addr, errno, strerror(errno));
     return EXIT_FAILURE;
   }
   if (listen(sock, 10) == -1) {
@@ -109,21 +120,35 @@
             "because of %d: %s\n",
             sock, SOCK_NONBLOCK, errno, strerror(errno));
       } else {
-        socks[new_sock]; // creates using value's default constructor
+        socks[new_sock];  // creates using value's default constructor
       }
     }
 
     for (auto it = socks.begin(); it != socks.end(); ++it) {
       if (FD_ISSET(it->first, &read_fds)) {
         if (it->second.ReceiveFrom(it->first)) {
-          it->second.msg.identifier = -1;
-          it->second.msg.time = aos::ntoh(it->second.msg.time);
-          log_crio_message_send(it->second.msg);
+          it->second.msg->source = ntoh(it->second.msg->source);
+          it->second.msg->sequence = ntoh(it->second.msg->sequence);
+          it->second.msg->level = ntoh(it->second.msg->level);
+          it->second.msg->seconds = ntoh(it->second.msg->seconds);
+          it->second.msg->nseconds = ntoh(it->second.msg->nseconds);
+
+          logging::atom::Write(it->second.msg);
+          it->second.msg = NULL;
           it->second.Clear();
         }
       }
     }
   }
 
-  aos::Cleanup();
+  Cleanup();
+}
+
+}  // namespace
+}  // namespace atom
+}  // namespace logging
+}  // namespace aos
+
+int main() {
+  return aos::logging::atom::crio_log_reader_main();
 }
diff --git a/aos/atom_code/core/LogDisplayer.cpp b/aos/atom_code/core/LogDisplayer.cpp
index 9dee08f..d8d9f94 100644
--- a/aos/atom_code/core/LogDisplayer.cpp
+++ b/aos/atom_code/core/LogDisplayer.cpp
@@ -9,6 +9,7 @@
 
 #include "aos/atom_code/core/LogFileCommon.h"
 #include "aos/aos_core.h"
+#include "aos/common/logging/logging_impl.h"
 
 namespace {
 
@@ -81,7 +82,7 @@
         filter_name = optarg;
         break;
       case 'l':
-        filter_level = str_log(optarg);
+        filter_level = aos::logging::str_log(optarg);
         if (filter_level == LOG_UNKNOWN) {
           fprintf(stderr, "LogDisplayer: unknown log level '%s'\n", optarg);
           exit(EXIT_FAILURE);
@@ -121,7 +122,7 @@
   }
 
   fprintf(stderr, "displaying down to level %s from file '%s'\n",
-          log_str(filter_level), filename);
+          aos::logging::log_str(filter_level), filename);
   if (optind < argc) {
     fprintf(stderr, "non-option ARGV-elements: ");
     while (optind < argc) {
@@ -135,23 +136,33 @@
             filename, strerror(errno));
     exit(EXIT_FAILURE);
   }
-  aos::LogFileAccessor accessor(fd, false);
+  aos::logging::LogFileAccessor accessor(fd, false);
   if (!start_at_beginning) {
     accessor.MoveToEnd();
   }
-  const aos::LogFileMessageHeader *msg;
+  const aos::logging::LogFileMessageHeader *msg;
+  aos::logging::LogMessage log_message;
   do {
     msg = accessor.ReadNextMessage(follow);
     if (msg == NULL) continue;
-    if (log_gt_important(filter_level, msg->level)) continue;
+    if (aos::logging::log_gt_important(filter_level, msg->level)) continue;
     if (filter_name != NULL &&
         strcmp(filter_name, reinterpret_cast<const char *>(msg) + sizeof(*msg)) != 0) {
       continue;
     }
-    printf("%s(%"PRId32")(%03"PRId8"): %s at %010"PRIu64"s%09"PRIu64"ns: %s",
-           reinterpret_cast<const char *>(msg) + sizeof(*msg), msg->source,
-           msg->sequence, log_str(msg->level), msg->time_sec, msg->time_nsec,
-           reinterpret_cast<const char *>(msg) + sizeof(*msg) + msg->name_size);
+
+    log_message.source = msg->source;
+    log_message.sequence = msg->sequence;
+    log_message.level = msg->level;
+    log_message.seconds = msg->time_sec;
+    log_message.nseconds = msg->time_nsec;
+    strncpy(log_message.name,
+            reinterpret_cast<const char *>(msg) + sizeof(*msg),
+            sizeof(log_message.name));
+    strncpy(log_message.message,
+            reinterpret_cast<const char *>(msg) + sizeof(*msg) +
+            msg->name_size,
+            sizeof(log_message.message));
+    aos::logging::internal::PrintMessage(stdout, log_message);
   } while (msg != NULL);
 }
-
diff --git a/aos/atom_code/core/LogFileCommon.h b/aos/atom_code/core/LogFileCommon.h
index 235c55b..afb86b0 100644
--- a/aos/atom_code/core/LogFileCommon.h
+++ b/aos/atom_code/core/LogFileCommon.h
@@ -11,18 +11,22 @@
 
 #include <algorithm>
 
-#include "aos/aos_core.h"
+#include "aos/common/logging/logging_impl.h"
 
 namespace aos {
+namespace logging {
 
 // File format: {
 //   LogFileMessageHeader header;
-//   char *name; // of the process that wrote the message
+//   char *name;  // of the process that wrote the message
 //   char *message;
 // } not crossing kPageSize boundaries into the file.
 //
-// Field sizes designed to fit the various values from log_message even on
+// Field sizes designed to fit the various values from LogMessage even on
 // other machines (hopefully) because they're baked into the files.
+//
+// A lot of the fields don't have comments because they're the same as the
+// identically named fields in LogMessage.
 struct __attribute__((aligned)) LogFileMessageHeader {
   // gets condition_set once this one has been written
   // for readers keeping up with a live writer
@@ -36,18 +40,17 @@
   log_level level;
   static_assert(sizeof(level) == 1, "log_level changed size!");
 
-  uint64_t time_sec;
-  static_assert(sizeof(time_sec) >= sizeof(log_message::time.tv_sec), "tv_sec won't fit");
-  uint64_t time_nsec;
-  static_assert(sizeof(time_nsec) >= sizeof(log_message::time.tv_nsec),
+  uint32_t time_sec;
+  static_assert(sizeof(time_sec) >= sizeof(LogMessage::seconds),
+                "tv_sec won't fit");
+  uint32_t time_nsec;
+  static_assert(sizeof(time_nsec) >= sizeof(LogMessage::nseconds),
                 "tv_nsec won't fit");
 
-  int32_t source; // pid or -1 for crio
-  static_assert(sizeof(source) >= sizeof(log_message::source), "PIDs won't fit");
-  uint8_t sequence;
-  static_assert(sizeof(sequence) == sizeof(log_crio_message::sequence),
-                "something changed");
-  static_assert(sizeof(sequence) == sizeof(log_message::sequence),
+  int32_t source;
+  static_assert(sizeof(source) >= sizeof(LogMessage::source), "PIDs won't fit");
+  uint16_t sequence;
+  static_assert(sizeof(sequence) == sizeof(LogMessage::sequence),
                 "something changed");
 
   // both including the terminating '\0'
@@ -129,7 +132,7 @@
         sizeof(mutex) > kPageSize) {
       char *const temp = current_;
       MapNextPage();
-      if (condition_set_value(reinterpret_cast<mutex *>(&temp[position_]), 2) != 0) {
+      if (condition_set_value(reinterpret_cast<mutex *>(&temp[position_]), 2) == -1) {
         fprintf(stderr, "LogFileCommon: condition_set_value(%p, 2) failed with %d: %s."
                 " readers will hang\n", &temp[position_], errno, strerror(errno));
       }
@@ -186,7 +189,7 @@
   }
 };
 
-};
+}  // namespace logging
+}  // namespace aos
 
 #endif
-
diff --git a/aos/atom_code/core/LogStreamer.cpp b/aos/atom_code/core/LogStreamer.cpp
index ceec18d..ffecac8 100644
--- a/aos/atom_code/core/LogStreamer.cpp
+++ b/aos/atom_code/core/LogStreamer.cpp
@@ -10,35 +10,43 @@
 #include <fcntl.h>
 #include <inttypes.h>
 
-#include "aos/aos_core.h"
+#include "aos/atom_code/logging/atom_logging.h"
 #include "aos/atom_code/core/LogFileCommon.h"
+#include "aos/atom_code/init.h"
+#include "aos/atom_code/ipc_lib/queue.h"
+#include "aos/common/logging/logging_impl.h"
 
-static const char *const kCRIOName = "CRIO";
+namespace aos {
+namespace logging {
+namespace atom {
+namespace {
 
-int main() {
-  aos::InitNRT();
+int log_streamer_main() {
+  InitNRT();
 
   const time_t t = time(NULL);
-  printf("starting at %jd----------------------------------\n", static_cast<uintmax_t>(t));
+  printf("starting at %jd----------------------------------\n",
+         static_cast<uintmax_t>(t));
 
   int index = 0;
   while (true) {
-    const log_message *const msg = log_read_next2(BLOCK, &index);
+    const LogMessage *const msg = ReadNext(BLOCK, &index);
     if (msg == NULL) continue;
-    const log_crio_message *const crio_msg = reinterpret_cast<const log_crio_message *>(
-        msg);
 
-    if (msg->source == -1) {
-      printf("CRIO(%03"PRId8"): %s at %f: %s", crio_msg->sequence,
-             log_str(crio_msg->level), crio_msg->time, crio_msg->message);
-    } else {
-      printf("%s(%"PRId32")(%03"PRId8"): %s at %010jus%09luns: %s",
-             msg->name, msg->source, msg->sequence, log_str(msg->level),
-             static_cast<uintmax_t>(msg->time.tv_sec), msg->time.tv_nsec, msg->message);
-    }
+    internal::PrintMessage(stdout, *msg);
 
-    log_free_message(msg);
+    logging::atom::Free(msg);
   }
 
-  aos::Cleanup();
+  Cleanup();
+  return 0;
+}
+
+}  // namespace
+}  // namespace atom
+}  // namespace logging
+}  // namespace aos
+
+int main() {
+  return aos::logging::atom::log_streamer_main();
 }
diff --git a/aos/atom_code/core/core.cc b/aos/atom_code/core/core.cc
index b34169b..4179a0a 100644
--- a/aos/atom_code/core/core.cc
+++ b/aos/atom_code/core/core.cc
@@ -3,10 +3,10 @@
 // Purposes: All shared memory gets allocated here.
 //
 
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include "aos/aos_core.h"
+#include <sys/select.h>
+#include <stdlib.h>
+
+#include "aos/atom_code/init.h"
 
 int main() {
   aos::InitCreate();
diff --git a/aos/atom_code/core/core.gyp b/aos/atom_code/core/core.gyp
index 04d3cc8..4e13e51 100644
--- a/aos/atom_code/core/core.gyp
+++ b/aos/atom_code/core/core.gyp
@@ -7,7 +7,7 @@
         'core.cc',
       ],
       'dependencies': [
-        '<(AOS)/build/aos.gyp:libaos',
+        '<(AOS)/atom_code/atom_code.gyp:init',
       ],
     },
     {
@@ -17,7 +17,9 @@
         'BinaryLogReader.cpp',
       ],
       'dependencies': [
-        '<(AOS)/build/aos.gyp:libaos',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/atom_code/atom_code.gyp:init',
+        '<(AOS)/common/common.gyp:common',
       ],
     },
     {
@@ -27,7 +29,8 @@
         'LogStreamer.cpp',
       ],
       'dependencies': [
-        '<(AOS)/build/aos.gyp:libaos',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/atom_code/atom_code.gyp:init',
       ],
     },
     {
@@ -37,7 +40,8 @@
         'LogDisplayer.cpp',
       ],
       'dependencies': [
-        '<(AOS)/build/aos.gyp:libaos',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/atom_code/atom_code.gyp:init',
       ],
     },
     {
@@ -47,7 +51,8 @@
         'CRIOLogReader.cpp',
       ],
       'dependencies': [
-        '<(AOS)/build/aos.gyp:libaos',
+        '<(AOS)/build/aos.gyp:logging',
+        '<(AOS)/atom_code/atom_code.gyp:init',
       ],
     },
   ],
diff --git a/aos/atom_code/init.cc b/aos/atom_code/init.cc
index 4776261..7eecde3 100644
--- a/aos/atom_code/init.cc
+++ b/aos/atom_code/init.cc
@@ -12,8 +12,9 @@
 #include <stdlib.h>
 #include <stdint.h>
 
-#include "aos/aos_core.h"
 #include "aos/common/die.h"
+#include "aos/atom_code/logging/atom_logging.h"
+#include "aos/atom_code/ipc_lib/shared_mem.h"
 
 namespace aos {
 
@@ -69,10 +70,7 @@
     Die("%s-init: creating shared memory reference failed\n",
         program_invocation_short_name);
   }
-  if (log_init(program_invocation_short_name) != 0) {
-    Die("%s-init: initializing logging failed\n",
-        program_invocation_short_name);
-  }
+  logging::atom::Register();
 }
 
 const char *const kNoRealtimeEnvironmentVariable = "AOS_NO_REALTIME";
diff --git a/aos/atom_code/ipc_lib/mutex.cpp b/aos/atom_code/ipc_lib/mutex.cpp
index d1f0ef2..4753e78 100644
--- a/aos/atom_code/ipc_lib/mutex.cpp
+++ b/aos/atom_code/ipc_lib/mutex.cpp
@@ -2,6 +2,8 @@
 
 #include <inttypes.h>
 #include <errno.h>
+#include <stdio.h>
+#include <string.h>
 
 #include "aos/aos_core.h"
 #include "aos/common/type_traits.h"
diff --git a/aos/atom_code/ipc_lib/queue.c b/aos/atom_code/ipc_lib/queue.c
index 5cfd2ac..2e45326 100644
--- a/aos/atom_code/ipc_lib/queue.c
+++ b/aos/atom_code/ipc_lib/queue.c
@@ -6,6 +6,8 @@
 #include <errno.h>
 #include <assert.h>
 
+#include "aos/common/logging/logging.h"
+
 #define READ_DEBUG 0
 #define WRITE_DEBUG 0
 #define REF_DEBUG 0
@@ -36,7 +38,7 @@
 		abort();
 	}
 #if REF_DEBUG
-	printf("ref_free_count: %p\n", msg);
+	printf("ref free: %p\n", msg);
 #endif
 	--pool->used;
 
@@ -484,10 +486,7 @@
 		msg = pool->pool[pool->used];
 	} else {
 		if (pool->length >= pool->mem_length) {
-			//TODO(brians) log this if it isn't the log queue
-			fprintf(stderr, "queue: overused_pool\n");
-			msg = NULL;
-			goto exit;
+			LOG(FATAL, "overused pool %p\n", pool);
 		}
 		msg = pool->pool[pool->length] = aos_alloc_msg(pool);
 		++pool->length;
@@ -500,7 +499,6 @@
 #endif
 	header->index = pool->used;
 	++pool->used;
-exit:
 	mutex_unlock(&pool->pool_lock);
 	return msg;
 }
diff --git a/aos/atom_code/logging/atom_logging.cc b/aos/atom_code/logging/atom_logging.cc
new file mode 100644
index 0000000..c9b1195
--- /dev/null
+++ b/aos/atom_code/logging/atom_logging.cc
@@ -0,0 +1,145 @@
+#include "aos/atom_code/logging/atom_logging.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/prctl.h>
+
+#include <algorithm>
+
+#include "aos/common/die.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/atom_code/thread_local.h"
+#include "aos/atom_code/ipc_lib/queue.h"
+
+namespace aos {
+namespace logging {
+namespace {
+
+using internal::Context;
+
+AOS_THREAD_LOCAL Context *my_context(NULL);
+
+std::string GetMyName() {
+  // The maximum number of characters that can make up a thread name.
+  // The docs are unclear if it can be 16 characters with no '\0', so we'll be
+  // safe by adding our own where necessary.
+  static const size_t kThreadNameLength = 16;
+
+  std::string process_name(program_invocation_short_name);
+
+  char thread_name_array[kThreadNameLength + 1];
+  if (prctl(PR_GET_NAME, thread_name_array) != 0) {
+    Die("prctl(PR_GET_NAME, %p) failed with %d: %s\n",
+        thread_name_array, errno, strerror(errno));
+  }
+  thread_name_array[sizeof(thread_name_array) - 1] = '\0';
+  std::string thread_name(thread_name_array);
+
+  // If the first bunch of characters are the same.
+  // We cut off comparing at the shorter of the 2 strings because one or the
+  // other often ends up cut off.
+  if (strncmp(thread_name.c_str(), process_name.c_str(),
+              std::min(thread_name.length(), process_name.length())) == 0) {
+    // This thread doesn't have an actual name.
+    return process_name;
+  }
+
+  return process_name + '.' + thread_name;
+}
+
+static const aos_type_sig message_sig = {sizeof(LogMessage), 1234, 1500};
+static aos_queue *queue;
+
+}  // namespace
+namespace internal {
+
+Context *Context::Get() {
+  if (my_context == NULL) {
+    my_context = new Context();
+    std::string name = GetMyName();
+    char *name_chars = new char[name.size() + 1];
+    my_context->name_size = std::min(name.size() + 1, sizeof(LogMessage::name));
+    memcpy(name_chars, name.c_str(), my_context->name_size);
+    name_chars[my_context->name_size - 1] = '\0';
+    my_context->name = name_chars;
+    my_context->source = getpid();
+  }
+  return my_context;
+}
+
+void Context::Delete() {
+  delete my_context;
+  my_context = NULL;
+}
+
+}  // namespace internal
+namespace atom {
+namespace {
+
+class AtomLogImplementation : public LogImplementation {
+  virtual void DoLog(log_level level, const char *format, va_list ap) {
+    LogMessage *message = static_cast<LogMessage *>(aos_queue_get_msg(queue));
+    if (message == NULL) {
+      LOG(FATAL, "queue get message failed\n");
+    }
+
+    internal::FillInMessage(level, format, ap, message);
+
+    Write(message);
+  }
+};
+
+}  // namespace
+
+void Register() {
+  Init();
+
+  queue = aos_fetch_queue("LoggingQueue", &message_sig);
+  if (queue == NULL) {
+    Die("logging: couldn't fetch queue\n");
+  }
+
+  AddImplementation(new AtomLogImplementation());
+}
+
+const LogMessage *ReadNext(int flags, int *index) {
+  return static_cast<const LogMessage *>(
+      aos_queue_read_msg_index(queue, flags, index));
+}
+
+const LogMessage *ReadNext() {
+  return ReadNext(BLOCK);
+}
+
+const LogMessage *ReadNext(int flags) {
+  const LogMessage *r = NULL;
+  do {
+    r = static_cast<const LogMessage *>(aos_queue_read_msg(queue, flags));
+    // not blocking means return a NULL if that's what it gets
+  } while ((flags & BLOCK) && r == NULL);
+  return r;
+}
+
+LogMessage *Get() {
+  return static_cast<LogMessage *>(aos_queue_get_msg(queue));
+}
+
+void Free(const LogMessage *msg) {
+  aos_queue_free_msg(queue, msg);
+}
+
+void Write(LogMessage *msg) {
+  if (aos_queue_write_msg_free(queue, msg, OVERRIDE) < 0) {
+    LOG(FATAL, "writing failed");
+  }
+}
+
+}  // namespace atom
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/atom_code/logging/atom_logging.cpp b/aos/atom_code/logging/atom_logging.cpp
deleted file mode 100644
index e98078b..0000000
--- a/aos/atom_code/logging/atom_logging.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <limits.h>
-
-#include <algorithm>
-
-#include "aos/aos_core.h"
-#include "aos/common/die.h"
-
-#define DECL_LEVEL(name, value) const log_level name = value;
-DECL_LEVELS
-#undef DECL_LEVEL
-
-log_level log_min = 0;
-
-static const aos_type_sig message_sig = {sizeof(log_queue_message), 1234, 1500};
-static const char *name;
-static size_t name_size;
-static aos_queue *queue;
-static log_message corked_message;
-static int cork_line_min, cork_line_max;
-bool log_initted = false;
-
-static inline void cork_init() {
-  corked_message.message[0] = '\0'; // make strlen of it 0
-  cork_line_min = INT_MAX;
-  cork_line_max = -1;
-}
-int log_init(const char *name_in){
-  if (log_initted) {
-    return 1;
-  }
-
-  const size_t name_in_len = strlen(name_in);
-  const char *last_slash = static_cast<const char *>(memrchr(name_in,
-                                                                   '/', name_in_len));
-  if (last_slash == NULL) {
-    name_size = name_in_len;
-    last_slash = name_in - 1;
-  } else {
-    name_size = name_in + name_in_len - last_slash;
-  }
-  if (name_size >= sizeof(log_message::name)) {
-    fprintf(stderr, "logging: error: name '%s' (going to use %zu bytes) is too long\n",
-        name_in, name_size);
-    return -1;
-  }
-  char *const tmp = static_cast<char *>(malloc(name_size + 1));
-  if (tmp == NULL) {
-    fprintf(stderr, "logging: error: couldn't malloc(%zd)\n", name_size + 1);
-    return -1;
-  }
-  name = tmp;
-  memcpy(tmp, last_slash + 1, name_size);
-  tmp[name_size] = 0;
-  queue = aos_fetch_queue("LoggingQueue", &message_sig);
-  if (queue == NULL) {
-    fprintf(stderr, "logging: error: couldn't fetch queue\n");
-    return -1;
-  }
-
-  cork_init();
-
-  log_initted = true;
-  return 0;
-}
-void log_uninit() {
-  free(const_cast<char *>(name));
-  name = NULL;
-  name_size = 0;
-  queue = NULL;
-  log_initted = false;
-}
-
-static inline void check_init() {
-	if (!log_initted) {
-		fprintf(stderr, "logging: warning: not initialized in %jd."
-            " initializing using \"<null>\" as name\n", static_cast<intmax_t>(getpid()));
-		log_init("<null>");
-	}
-}
-
-const log_message *log_read_next2(int flags, int *index) {
-  check_init();
-  return static_cast<const log_message *>(aos_queue_read_msg_index(queue, flags, index));
-}
-const log_message *log_read_next1(int flags) {
-	check_init();
-	const log_message *r = NULL;
-	do {
-		r = static_cast<const log_message *>(aos_queue_read_msg(queue, flags));
-	} while ((flags & BLOCK) && r == NULL); // not blocking means return a NULL if that's what it gets
-	return r;
-}
-void log_free_message(const log_message *msg) {
-	check_init();
-	aos_queue_free_msg(queue, msg);
-}
-
-int log_crio_message_send(log_crio_message &to_send) {
-	check_init();
-
-	log_crio_message *msg = static_cast<log_crio_message *>(aos_queue_get_msg(queue));
-	if (msg == NULL) {
-		fprintf(stderr, "logging: error: couldn't get a message to send '%s'\n",
-            to_send.message);
-		return -1;
-	}
-  //*msg = to_send;
-  static_assert(sizeof(to_send) == sizeof(*msg), "something is very wrong here");
-  memcpy(msg, &to_send, sizeof(to_send));
-	if (aos_queue_write_msg(queue, msg, OVERRIDE) < 0) {
-		fprintf(stderr, "logging: error: writing crio message '%s' failed\n", msg->message);
-		aos_queue_free_msg(queue, msg);
-		return -1;
-	}
-
-	return 0;
-}
-
-// Prints format (with ap) into output and correctly deals with the message
-// being too long etc.
-// Returns whether it succeeded or not.
-static inline bool vsprintf_in(char *output, size_t output_size,
-                               const char *format, va_list ap) {
-	static const char *continued = "...\n";
-	const size_t size = output_size - strlen(continued);
-	const int ret = vsnprintf(output, size, format, ap);
-	if (ret < 0) {
-		fprintf(stderr, "logging: error: vsnprintf failed with %d (%s)\n",
-            errno, strerror(errno));
-    return false;
-	} else if (static_cast<uintmax_t>(ret) >= static_cast<uintmax_t>(size)) {
-		// overwrite the NULL at the end of the existing one and
-    // copy in the one on the end of continued
-		memcpy(&output[size - 1], continued, strlen(continued) + 1);
-	}
-  return true;
-}
-static inline bool write_message(log_message *msg, log_level level) {
-	msg->level = level;
-	msg->source = getpid();
-	memcpy(msg->name, name, name_size + 1);
-	if (clock_gettime(CLOCK_REALTIME, &msg->time) == -1) {
-		fprintf(stderr, "logging: warning: couldn't get the current time "
-            "because of %d (%s)\n", errno, strerror(errno));
-		msg->time.tv_sec = 0;
-		msg->time.tv_nsec = 0;
-	}
-
-  static uint8_t local_sequence = -1;
-  msg->sequence = ++local_sequence;
-
-	if (aos_queue_write_msg(queue, msg, OVERRIDE) < 0) {
-		fprintf(stderr, "logging: error: writing message '%s' failed\n", msg->message);
-		aos_queue_free_msg(queue, msg);
-    return false;
-	}
-  return true;
-}
-static inline int vlog_do(log_level level, const char *format, va_list ap) {
-	log_message *msg = static_cast<log_message *>(aos_queue_get_msg(queue));
-	if (msg == NULL) {
-		fprintf(stderr, "logging: error: couldn't get a message to send '%s'\n", format);
-		return -1;
-	}
-
-  if (!vsprintf_in(msg->message, sizeof(msg->message), format, ap)) {
-    return -1;
-  }
-
-  if (!write_message(msg, level)) {
-    return -1;
-  }
-
-  if (level == FATAL) {
-    aos::Die("%s", msg->message);
-  }
-
-	return 0;
-}
-int log_do(log_level level, const char *format, ...) {
-	check_init();
-	va_list ap;
-	va_start(ap, format);
-	const int ret = vlog_do(level, format, ap);
-	va_end(ap);
-  return ret;
-}
-
-static inline int vlog_cork(int line, const char *format, va_list ap) {
-  const size_t message_length = strlen(corked_message.message);
-  if (line > cork_line_max) cork_line_max = line;
-  if (line < cork_line_min) cork_line_min = line;
-  return vsprintf_in(corked_message.message + message_length,
-                     sizeof(corked_message.message) - message_length, format, ap) ? 0 : -1;
-}
-int log_cork(int line, const char *format, ...) {
-  check_init();
-	va_list ap;
-	va_start(ap, format);
-	const int ret = vlog_cork(line, format, ap);
-	va_end(ap);
-  return ret;
-}
-static inline bool log_uncork_helper(char *output, size_t output_size,
-                                     const char *format, ...) {
-  check_init();
-	va_list ap;
-	va_start(ap, format);
-	const bool ret = vsprintf_in(output, output_size, format, ap);
-	va_end(ap);
-  return ret;
-}
-int log_uncork(int line, log_level level, const char *begin_format,
-               const char *format, ...) {
-  check_init();
-	va_list ap;
-	va_start(ap, format);
-	const int ret = vlog_cork(line, format, ap);
-	va_end(ap);
-  if (ret != 0) {
-    return ret;
-  }
-
-	log_message *msg = static_cast<log_message *>(aos_queue_get_msg(queue));
-	if (msg == NULL) {
-		fprintf(stderr, "logging: error: couldn't get a message to send '%s'\n", format);
-    cork_init();
-		return -1;
-  }
-
-  static char new_format[LOG_MESSAGE_LEN];
-  if (!log_uncork_helper(new_format, sizeof(new_format), begin_format,
-                         cork_line_min, cork_line_max)) {
-    cork_init();
-    return -1;
-  }
-  const size_t new_length = strlen(new_format);
-  memcpy(msg->message, new_format, new_length);
-  memcpy(msg->message + new_length, corked_message.message,
-          std::min(strlen(corked_message.message) + 1,
-              sizeof(msg->message) - new_length));
-  // in case corked_message.message was too long, it'll still be NULL-terminated
-  msg->message[sizeof(msg->message) - 1] = '\0';
-  cork_init();
-
-  if (!write_message(msg, level)) {
-    return -1;
-  }
-
-  return 0;
-}
-
diff --git a/aos/atom_code/logging/atom_logging.h b/aos/atom_code/logging/atom_logging.h
index 6211e22..45f2a07 100644
--- a/aos/atom_code/logging/atom_logging.h
+++ b/aos/atom_code/logging/atom_logging.h
@@ -1,109 +1,30 @@
 #ifndef AOS_ATOM_CODE_LOGGING_LOGGING_H_
 #define AOS_ATOM_CODE_LOGGING_LOGGING_H_
 
-// IWYU pragma: private, include "aos/common/logging/logging.h"
+#include "aos/common/logging/logging_impl.h"
 
-#ifndef AOS_COMMON_LOGGING_LOGGING_H_
-#error This file may only be #included through common/logging/logging.h!!!
-#endif
+namespace aos {
+namespace logging {
+namespace atom {
 
-#include "aos/aos_core.h"
+// Calls AddImplementation to register the usual atom logging implementation
+// which sends the messages through a queue. This implementation relies on
+// another process(es) to read the log messages that it puts into the queue.
+// It gets called by aos::Init*.
+void Register();
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+// Fairly simple wrappers around the raw queue calls.
 
-int log_init(const char *name);
-// WARNING: THIS LEAKS MEMORY AND SHARED MEMORY
-void log_uninit(void);
+// This one never returns NULL if flags contains BLOCK.
+const LogMessage *ReadNext(int flags);
+const LogMessage *ReadNext(int flags, int *index);
+const LogMessage *ReadNext();
+LogMessage *Get();
+void Free(const LogMessage *msg);
+void Write(LogMessage *msg);
 
-extern log_level log_min;
-
-// The basic structure that goes into the shared memory queue.
-// It is packed so the pid_t at the front is at the same location as
-// the one in log_crio_message.
-typedef struct log_message_t_ {
-	pid_t source;
-	log_level level;
-	char message[LOG_MESSAGE_LEN];
-	char name[40];
-	struct timespec time;
-  uint8_t sequence; // per process
-} __attribute__((packed)) log_message;
-
-#ifdef __cplusplus
-#define LOG_BOOL bool
-#else
-#define LOG_BOOL uint8_t
-#endif
-extern LOG_BOOL log_initted;
-#undef LOG_BOOL
-
-// Unless explicitly stated otherwise, format must always be a string constant
-// and args are printf-style arguments for format.
-// The validitiy of format and args together will be checked at compile time
-// using a gcc function attribute.
-
-// Logs the specified thing.
-#define LOG(level, format, args...) do { \
-	if (level >= log_min) { \
-		log_do(level, LOG_SOURCENAME ": " STRINGIFY(__LINE__) ": " format, ##args); \
-	} \
-} while (0)
-// Allows "bottling up" multiple log fragments which can then all be logged in
-// one message with LOG_UNCORK.
-// format does not have to be a constant
-#define LOG_CORK(format, args...) do { \
-  log_cork(__LINE__, format, ##args); \
-} while (0)
-// Actually logs all of the saved up log fragments (including format and args on
-// the end).
-#define LOG_UNCORK(level, format, args...) do { \
-  log_uncork(__LINE__, level, LOG_SOURCENAME ": %d-%d: ", format, ##args); \
-} while (0)
-// Makes a normal logging call if possible or just prints it out on stderr.
-#define LOG_IFINIT(level, format, args...) do{ \
-	if(log_initted) { \
-		LOG(level, format, args); \
-	} else { \
-		fprintf(stderr, "%s-noinit: " format, log_str(level), ##args); \
-	} \
-}while(0)
-
-// All functions return 0 for success and - for error.
-
-// Actually implements the basic logging call.
-// Does not check that level is valid.
-// TODO(brians): Fix this so it works with clang.
-int log_do(log_level level, const char *format, ...)
-  __attribute__((format(gnu_printf, 2, 3)));
-
-// TODO(brians): Fix this so it works with clang.
-int log_cork(int line, const char *format, ...)
-  __attribute__((format(gnu_printf, 2, 3)));
-// Implements the uncork logging call.
-// IMPORTANT: begin_format must have 2 %d formats as its only 2 format specifiers
-// which will get passed the minimum and maximum line numbers that have been
-// corked into this call.
-// TODO(brians): Fix this so it works with clang.
-int log_uncork(int line, log_level level, const char *begin_format,
-               const char *format, ...)
-  __attribute__((format(gnu_printf, 4, 5)));
-
-const log_message *log_read_next1(int flags);
-const log_message *log_read_next2(int flags, int *index);
-inline const log_message *log_read_next(void) { return log_read_next1(BLOCK); }
-void log_free_message(const log_message *msg);
-
-// The structure that is actually in the shared memory queue.
-union log_queue_message {
-  log_message atom;
-  log_crio_message crio;
-};
-
-#ifdef __cplusplus
-}
-#endif
+}  // namespace atom
+}  // namespace logging
+}  // namespace aos
 
 #endif
-
diff --git a/aos/atom_code/logging/atom_logging_test.cpp b/aos/atom_code/logging/atom_logging_test.cpp
deleted file mode 100644
index a97d1e9..0000000
--- a/aos/atom_code/logging/atom_logging_test.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-#include <string>
-
-#include "gtest/gtest.h"
-
-#include "aos/aos_core.h"
-#include "aos/atom_code/ipc_lib/sharedmem_test_setup.h"
-#include "aos/common/control_loop/Timing.h"
-#include "aos/common/inttypes.h"
-#include "aos/common/time.h"
-
-using ::aos::time::Time;
-using ::testing::AssertionResult;
-using ::testing::AssertionSuccess;
-using ::testing::AssertionFailure;
-
-namespace aos {
-namespace testing {
-
-static const std::string kLoggingName = "LoggingTestName";
-
-class LoggingTest : public SharedMemTestSetup {
-  virtual void SetUp() {
-    SharedMemTestSetup::SetUp();
-    ASSERT_EQ(0, log_init(kLoggingName.c_str()));
-  }
-  virtual void TearDown() {
-    log_uninit();
-    SharedMemTestSetup::TearDown();
-  }
-
- public:
-  AssertionResult WasAnythingLogged() {
-    const log_message *msg = log_read_next1(NON_BLOCK);
-    if (msg != NULL) {
-      char bad_msg[LOG_MESSAGE_LEN];
-      memcpy(bad_msg, msg->message, sizeof(bad_msg));
-      log_free_message(msg);
-      return AssertionSuccess() << "read message '" << bad_msg << "'";
-    }
-    return AssertionFailure();
-  }
-  AssertionResult WasLogged(log_level level, const std::string value) {
-    const log_message *msg = NULL;
-    char bad_msg[LOG_MESSAGE_LEN];
-    bad_msg[0] = '\0';
-    const pid_t owner = getpid();
-    while (true) {
-      if (msg != NULL) {
-        static_assert(sizeof(bad_msg) == sizeof(msg->message),
-                      "something is wrong");
-        if (bad_msg[0] != '\0') {
-          printf("read bad message: %s", bad_msg);
-        }
-        memcpy(bad_msg, msg->message, sizeof(bad_msg));
-        log_free_message(msg);
-        msg = NULL;
-      }
-      msg = log_read_next1(NON_BLOCK);
-      if (msg == NULL) {
-        return AssertionFailure() << "last message read was '" << bad_msg << "'"
-            " instead of '" << value << "'";
-      }
-      if (msg->source != owner) continue;
-      if (msg->level != level) continue;
-      if (strcmp(msg->name, kLoggingName.c_str()) != 0) continue;
-      if (strcmp(msg->message + strlen(msg->message) - value.length(),
-                 value.c_str()) != 0) continue;
-
-      // if it's gotten this far, then the message is correct
-      log_free_message(msg);
-      return AssertionSuccess();
-    }
-  }
-};
-typedef LoggingTest LoggingDeathTest;
-
-// Tests both basic logging functionality and that the test setup works
-// correctly.
-TEST_F(LoggingTest, Basic) {
-  EXPECT_FALSE(WasAnythingLogged());
-  LOG(INFO, "test log 1\n");
-  EXPECT_TRUE(WasLogged(INFO, "test log 1\n"));
-  LOG(INFO, "test log 1.5\n");
-  // there's a subtle typo on purpose...
-  EXPECT_FALSE(WasLogged(INFO, "test log 15\n"));
-  LOG(ERROR, "test log 2=%d\n", 55);
-  EXPECT_TRUE(WasLogged(ERROR, "test log 2=55\n"));
-  LOG(ERROR, "test log 3\n");
-  EXPECT_FALSE(WasLogged(WARNING, "test log 3\n"));
-  LOG(WARNING, "test log 4\n");
-  EXPECT_TRUE(WasAnythingLogged());
-}
-TEST_F(LoggingTest, Cork) {
-  static const int begin_line = __LINE__;
-  LOG_CORK("first part ");
-  LOG_CORK("second part (=%d) ", 19);
-  EXPECT_FALSE(WasAnythingLogged());
-  LOG_CORK("third part ");
-  static const int end_line = __LINE__;
-  LOG_UNCORK(WARNING, "last part %d\n", 5);
-  char *expected;
-  ASSERT_GT(asprintf(&expected, "atom_logging_test.cpp: %d-%d: "
-                        "first part second part (=19) third part last part 5\n",
-                        begin_line + 1, end_line + 1), 0);
-  EXPECT_TRUE(WasLogged(WARNING, std::string(expected)));
-}
-
-TEST_F(LoggingDeathTest, Fatal) {
-  ASSERT_EXIT(LOG(FATAL, "this should crash it\n"),
-              ::testing::KilledBySignal(SIGABRT),
-              "this should crash it");
-}
-
-TEST_F(LoggingTest, PrintfDirectives) {
-  LOG(INFO, "test log %%1 %%d\n");
-  EXPECT_TRUE(WasLogged(INFO, "test log %1 %d\n"));
-  LOG_DYNAMIC(WARNING, "test log %%2 %%f\n");
-  EXPECT_TRUE(WasLogged(WARNING, "test log %2 %f\n"));
-  LOG_CORK("log 3 part %%1 %%d ");
-  LOG_UNCORK(DEBUG, "log 3 part %%2 %%f\n");
-  EXPECT_TRUE(WasLogged(DEBUG, "log 3 part %1 %d log 3 part %2 %f\n"));
-}
-
-// For writing only.
-TEST_F(LoggingTest, Timing) {
-  static const long kTimingCycles = 5000;
-  Time start = Time::Now();
-  for (long i = 0; i < kTimingCycles; ++i) {
-    LOG(INFO, "a\n");
-  }
-  Time elapsed = Time::Now() - start;
-
-  printf("short message took %"PRId64" nsec for %ld\n", elapsed.ToNSec(),
-      kTimingCycles);
-
-  start = Time::Now();
-  for (long i = 0; i < kTimingCycles; ++i) {
-    LOG(INFO, "something longer than just \"a\" to log to test timing\n");
-  }
-  elapsed = Time::Now() - start;
-  printf("long message took %"PRId64" nsec for %ld\n", elapsed.ToNSec(),
-      kTimingCycles);
-}
-
-}  // namespace testing
-}  // namespace aos
diff --git a/aos/atom_code/logging/logging.gyp b/aos/atom_code/logging/logging.gyp
index 5d29da8..dfb189c 100644
--- a/aos/atom_code/logging/logging.gyp
+++ b/aos/atom_code/logging/logging.gyp
@@ -1,15 +1,4 @@
 {
   'targets': [
-    {
-      'target_name': 'atom_logging_test',
-      'type': 'executable',
-      'sources': [
-        'atom_logging_test.cpp',
-      ],
-      'dependencies': [
-        '<(EXTERNALS):gtest',
-        '<(AOS)/build/aos.gyp:libaos',
-      ],
-    },
   ],
 }
diff --git a/aos/atom_code/output/HTTPServer.cpp b/aos/atom_code/output/HTTPServer.cpp
index 88e3c6f..b0d6b93 100644
--- a/aos/atom_code/output/HTTPServer.cpp
+++ b/aos/atom_code/output/HTTPServer.cpp
@@ -4,6 +4,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <string.h>
 
 #include <memory>
 
diff --git a/aos/atom_code/starter/starter.cpp b/aos/atom_code/starter/starter.cpp
index 0cfddd5..e47e213 100644
--- a/aos/atom_code/starter/starter.cpp
+++ b/aos/atom_code/starter/starter.cpp
@@ -8,54 +8,56 @@
 #include <sys/inotify.h>
 #include <sys/stat.h>
 
-#include "aos/aos_core.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/atom_code/init.h"
 
 void niceexit(int status);
 
 pid_t start(const char *cmd, uint8_t times) {
   char *which_cmd, *which_cmd_stm;
   if (asprintf(&which_cmd, "which %s", cmd) == -1) {
-    LOG_IFINIT(ERROR, "creating \"which %s\" failed with %d: %s\n",
-               cmd, errno, strerror(errno));
+    LOG(ERROR, "creating \"which %s\" failed with %d: %s\n",
+        cmd, errno, strerror(errno));
     niceexit(EXIT_FAILURE);
   }
   if (asprintf(&which_cmd_stm, "which %s.stm", cmd) == -1) {
-    LOG_IFINIT(ERROR, "creating \"which %s.stm\" failed with %d: %s\n",
-               cmd, errno, strerror(errno));
+    LOG(ERROR, "creating \"which %s.stm\" failed with %d: %s\n",
+        cmd, errno, strerror(errno));
     niceexit(EXIT_FAILURE);
   }
   FILE *which = popen(which_cmd, "r");
   char exe[CMDLEN + 5], orig_exe[CMDLEN];
   size_t ret;
   if ((ret = fread(orig_exe, 1, sizeof(orig_exe), which)) == CMDLEN) {
-    LOG_IFINIT(ERROR, "`which %s` was too long. not starting '%s'\n", cmd, cmd);
+    LOG(ERROR, "`which %s` was too long. not starting '%s'\n", cmd, cmd);
     return 0;
   }
   orig_exe[ret] = '\0';
   if (pclose(which) == -1) {
-    LOG_IFINIT(WARNING, "pclose failed with %d: %s\n", errno, strerror(errno));
+    LOG(WARNING, "pclose failed with %d: %s\n", errno, strerror(errno));
   }
   free(which_cmd);
   if (strlen(orig_exe) == 0) { // which returned nothing; check if stm exists
-    LOG_IFINIT(INFO, "%s didn't exist. trying %s.stm\n", cmd, cmd);
+    LOG(INFO, "%s didn't exist. trying %s.stm\n", cmd, cmd);
     FILE *which_stm = popen(which_cmd_stm, "r");
     if ((ret = fread(orig_exe, 1, sizeof(orig_exe), which_stm)) == CMDLEN) {
-      LOG_IFINIT(ERROR, "`which %s.stm` was too long. not starting %s\n", cmd, cmd);
+      LOG(ERROR, "`which %s.stm` was too long. not starting %s\n", cmd, cmd);
       return 0;
     }
     orig_exe[ret] = '\0';
     if (pclose(which) == -1) {
-      LOG_IFINIT(WARNING, "pclose failed with %d: %s\n", errno, strerror(errno));
+      LOG(WARNING, "pclose failed with %d: %s\n", errno, strerror(errno));
     }
   }
   if (strlen(orig_exe) == 0) {
-    LOG_IFINIT(WARNING, "couldn't find file '%s[.stm]'. not going to start it\n",
-               cmd);
+    LOG(WARNING, "couldn't find file '%s[.stm]'. not going to start it\n",
+        cmd);
     return 0;
   }
   if (orig_exe[strlen(orig_exe) - 1] != '\n') {
-    LOG_IFINIT(WARNING, "no \\n on the end of `which %s[.stm]` output ('%s')\n",
-               cmd, orig_exe);
+    LOG(WARNING, "no \\n on the end of `which %s[.stm]` output ('%s')\n",
+        cmd, orig_exe);
   } else {
     orig_exe[strlen(orig_exe) - 1] = '\0'; // get rid of the \n
   }
@@ -65,11 +67,11 @@
   struct stat st;
   errno = 0;
   if (stat(orig_exe, &st) != 0 && errno != ENOENT) {
-    LOG_IFINIT(ERROR, "killing everything because stat('%s') failed with %d: %s\n",
-               orig_exe, errno, strerror(errno));
+    LOG(ERROR, "killing everything because stat('%s') failed with %d: %s\n",
+        orig_exe, errno, strerror(errno));
     niceexit(EXIT_FAILURE);
   } else if (errno == ENOENT) {
-    LOG_IFINIT(WARNING, "binary '%s' doesn't exist. not starting it\n", orig_exe);
+    LOG(WARNING, "binary '%s' doesn't exist. not starting it\n", orig_exe);
     return 0;
   }
   struct stat st2;
@@ -78,38 +80,38 @@
   if (!orig_zero) {
     // if it failed and it wasn't because it was missing
     if (unlink(exe) != 0 && (errno != EROFS && errno != ENOENT)) {
-      LOG_IFINIT(ERROR,
-                 "killing everything because unlink('%s') failed with %d: %s\n",
-                 exe, errno, strerror(errno));
+      LOG(ERROR,
+          "killing everything because unlink('%s') failed with %d: %s\n",
+          exe, errno, strerror(errno));
       niceexit(EXIT_FAILURE);
     }
     if (link(orig_exe, exe) != 0) {
-      LOG_IFINIT(ERROR,
-                 "killing everything because link('%s', '%s') failed with %d: %s\n",
-                 orig_exe, exe, errno, strerror(errno));
+      LOG(ERROR,
+          "killing everything because link('%s', '%s') failed with %d: %s\n",
+          orig_exe, exe, errno, strerror(errno));
       niceexit(EXIT_FAILURE);
     }
   }
   if (errno == EEXIST) {
-    LOG_IFINIT(INFO, "exe ('%s') already existed\n", exe);
+    LOG(INFO, "exe ('%s') already existed\n", exe);
   }
 
   pid_t child;
   if ((child = fork()) == 0) {
     execlp(exe, orig_exe, static_cast<char *>(NULL));
-    LOG_IFINIT(ERROR,
-               "killing everything because execlp('%s', '%s', NULL) "
-               "failed with %d: %s\n",
-               exe, cmd, errno, strerror(errno));
+    LOG(ERROR,
+        "killing everything because execlp('%s', '%s', NULL) "
+        "failed with %d: %s\n",
+        exe, cmd, errno, strerror(errno));
     _exit(EXIT_FAILURE); // don't niceexit or anything because this is the child!!
   }
   if (child == -1) {
-    LOG_IFINIT(WARNING, "fork on '%s' failed with %d: %s",
-               cmd, errno, strerror(errno));
+    LOG(WARNING, "fork on '%s' failed with %d: %s",
+        cmd, errno, strerror(errno));
     if (times < 100) {
       return start(cmd, times + 1);
     } else {
-      LOG_IFINIT(ERROR, "tried to start '%s' too many times. giving up\n", cmd);
+      LOG(ERROR, "tried to start '%s' too many times. giving up\n", cmd);
       return 0;
     }
   } else {
@@ -117,9 +119,9 @@
     files[child] = orig_exe;
     int ret = inotify_add_watch(notifyfd, orig_exe, IN_ATTRIB | IN_MODIFY);
     if (ret < 0) {
-      LOG_IFINIT(WARNING, "inotify_add_watch('%s') failed: "
-                 "not going to watch for changes to it because of %d: %s\n",
-                 orig_exe, errno, strerror(errno));
+      LOG(WARNING, "inotify_add_watch('%s') failed: "
+          "not going to watch for changes to it because of %d: %s\n",
+          orig_exe, errno, strerror(errno));
     } else {
       watches[ret] = child;
       mtimes[ret] = st2.st_mtime;
@@ -164,6 +166,8 @@
 
   atexit(exit_handler);
 
+  aos::logging::Init();
+
   notifyfd = inotify_init1(IN_NONBLOCK);
 
   pid_t core = start("core", 0);
@@ -330,18 +334,6 @@
           niceexit(EXIT_FAILURE);
         }
 
-        /*// remove all of the watches assigned to the pid that just died
-        for (auto it = watches.begin(); it != watches.end(); ++it) {
-          if (it->second == infop.si_pid) {
-            watches_to_ignore.insert(it->first);
-          }
-        }
-        for (auto it = watches_to_ignore.begin();
-             it != watches_to_ignore.end(); ++it) {
-          LOG(DEBUG, "watch id %d was on PID %d\n", *it, infop.si_pid);
-          watches.erase(*it);
-        }*/
-
         start(children[infop.si_pid], 0);
         LOG(DEBUG, "erasing %d from children\n", infop.si_pid);
         children.erase(infop.si_pid);
diff --git a/aos/atom_code/starter/starter.gyp b/aos/atom_code/starter/starter.gyp
index 44e4b08..cff6d07 100644
--- a/aos/atom_code/starter/starter.gyp
+++ b/aos/atom_code/starter/starter.gyp
@@ -7,7 +7,7 @@
         'starter.cpp',
       ],
       'dependencies': [
-        '<(AOS)/build/aos.gyp:libaos',
+        '<(AOS)/atom_code/atom_code.gyp:init',
       ],
       'copies': [
         {
diff --git a/aos/atom_code/thread_local.h b/aos/atom_code/thread_local.h
new file mode 100644
index 0000000..9563a87
--- /dev/null
+++ b/aos/atom_code/thread_local.h
@@ -0,0 +1,13 @@
+#ifndef AOS_ATOM_CODE_THREAD_LOCAL_H_
+#define AOS_ATOM_CODE_THREAD_LOCAL_H_
+
+// The storage class to use when declaring thread-local variables. This provides
+// a single place to change it if/when we want to switch to something standard.
+//
+// Example: AOS_THREAD_LOCAL void *bla;  // at namespace (aka global) scope
+//
+// C++11 has thread_local, but it's not clear whether Clang supports that as of
+// 12/18/12.
+#define AOS_THREAD_LOCAL __thread
+
+#endif  // AOS_ATOM_CODE_THREAD_LOCAL_H_