copying branch over from other 2013 repo
diff --git a/aos/common/logging/logging_impl.h b/aos/common/logging/logging_impl.h
new file mode 100644
index 0000000..0b1e256
--- /dev/null
+++ b/aos/common/logging/logging_impl.h
@@ -0,0 +1,205 @@
+#ifndef AOS_COMMON_LOGGING_LOGGING_IMPL_H_
+#define AOS_COMMON_LOGGING_LOGGING_IMPL_H_
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <string>
+
+#include "aos/common/logging/logging.h"
+#include "aos/common/type_traits.h"
+#include "aos/common/mutex.h"
+
+// This file has all of the logging implementation. It can't be #included by C
+// code like logging.h can.
+
+namespace aos {
+namespace logging {
+
+// Unless explicitly stated otherwise, format must always be a string constant,
+// args are printf-style arguments for format, and ap is a va_list of args.
+// The validitiy of format and args together will be checked at compile time
+// using a gcc function attribute.
+
+// The struct that the code uses for making logging calls.
+// Packed so that it ends up the same under both linux and vxworks.
+struct __attribute__((packed)) LogMessage {
+#ifdef __VXWORKS__
+  static_assert(sizeof(pid_t) == sizeof(int),
+                "we use task IDs (aka ints) and pid_t interchangeably");
+#endif
+  // Actually the task ID (aka a pointer to the TCB) on the cRIO.
+  pid_t source;
+  static_assert(sizeof(source) == 4, "that's how they get printed");
+  // Per task/thread.
+  uint16_t sequence;
+  log_level level;
+  int32_t seconds, nseconds;
+  char name[100];
+  char message[LOG_MESSAGE_LEN];
+};
+static_assert(shm_ok<LogMessage>::value, "it's going in a queue");
+
+// Returns left > right. LOG_UNKNOWN is most important.
+static inline bool log_gt_important(log_level left, log_level right) {
+  if (left == ERROR) left = 3;
+  if (right == ERROR) right = 3;
+  return left > right;
+}
+
+// Returns a string representing level or "unknown".
+static inline const char *log_str(log_level level) {
+#define DECL_LEVEL(name, value) if (level == name) return #name;
+  DECL_LEVELS;
+#undef DECL_LEVEL
+  return "unknown";
+}
+// Returns the log level represented by str or LOG_UNKNOWN.
+static inline log_level str_log(const char *str) {
+#define DECL_LEVEL(name, value) if (!strcmp(str, #name)) return name;
+  DECL_LEVELS;
+#undef DECL_LEVEL
+  return LOG_UNKNOWN;
+}
+
+// Takes a message and logs it. It will set everything up and then call DoLog
+// for the current LogImplementation.
+void VLog(log_level level, const char *format, va_list ap);
+// Adds to the saved up message.
+void VCork(int line, const char *format, va_list ap);
+// Actually logs the saved up message.
+void VUnCork(int line, log_level level, const char *file,
+             const char *format, va_list ap);
+
+// Will call VLog with the given arguments for the next logger in the chain.
+void LogNext(log_level level, const char *format, ...)
+  __attribute__((format(LOG_PRINTF_FORMAT_TYPE, 2, 3)));
+
+// Represents a system that can actually take log messages and do something
+// useful with them.
+// All of the code (transitively too!) in the DoLog here can make
+// normal LOG and LOG_DYNAMIC calls but can NOT call LOG_CORK/LOG_UNCORK. These
+// calls will not result in DoLog recursing. However, implementations must be
+// safe to call from multiple threads/tasks at the same time. Also, any other
+// overriden methods may end up logging through a given implementation's DoLog.
+class LogImplementation {
+ public:
+  LogImplementation() : next_(NULL) {}
+
+  // The one that this one's implementation logs to.
+  // NULL means that there is no next one.
+  LogImplementation *next() { return next_; }
+  // Virtual in case a subclass wants to perform checks. There will be a valid
+  // logger other than this one available while this is called.
+  virtual void set_next(LogImplementation *next) { next_ = next; }
+
+ private:
+  // Actually logs the given message. Implementations should somehow create a
+  // LogMessage and then call internal::FillInMessage.
+  virtual void DoLog(log_level level, const char *format, va_list ap) = 0;
+
+  // Function of this class so that it can access DoLog.
+  // Levels is how many LogImplementations to not use off the stack.
+  static void DoVLog(log_level, const char *format, va_list ap, int levels);
+  // Friends so that they can access DoVLog.
+  friend void VLog(log_level, const char *, va_list);
+  friend void LogNext(log_level, const char *, ...);
+
+  LogImplementation *next_;
+};
+
+// Adds another implementation to the stack of implementations in this
+// task/thread.
+// Any tasks/threads created after this call will also use this implementation.
+// The cutoff is when the state in a given task/thread is created (either lazily
+// when needed or by calling Load()).
+// The logging system takes ownership of implementation. It will delete it if
+// necessary, so it must be created with new.
+void AddImplementation(LogImplementation *implementation);
+
+// Must be called at least once per process/load before anything else is
+// called. This function is safe to call multiple times from multiple
+// tasks/threads.
+void Init();
+
+// Forces all of the state that is usually lazily created when first needed to
+// be created when called. Cleanup() will delete it.
+void Load();
+// Resets all information in this task/thread to its initial state.
+// NOTE: This is not the opposite of Init(). The state that this deletes is
+// lazily created when needed. It is actually the opposite of Load().
+void Cleanup();
+
+// This is where all of the code that is only used by actual LogImplementations
+// goes.
+namespace internal {
+
+// An separate instance of this class is accessible from each task/thread.
+struct Context {
+  Context();
+
+  // Gets the Context object for this task/thread. Will create one the first
+  // time it is called.
+  //
+  // The implementation for each platform will lazily instantiate a new instance
+  // and then initialize name the first time.
+  // IMPORTANT: The implementation of this can not use logging.
+  static Context *Get();
+  // 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.
+  static void Delete();
+
+  // Which one to log to right now.
+  // Will be NULL if there is no logging implementation to use right now.
+  LogImplementation *implementation;
+
+  // A string representing this task/(process and thread).
+  const char *name;
+  // The number of bytes in name (including the terminating '\0').
+  // Must be <= sizeof(LogMessage::name).
+  size_t name_size;
+
+  // What to assign LogMessage::source to in this task/thread.
+  pid_t source;
+
+  // The sequence value to send out with the next message.
+  uint16_t sequence;
+
+  // Contains all of the information related to implementing LOG_CORK and
+  // LOG_UNCORK.
+  struct {
+    char message[LOG_MESSAGE_LEN];
+    int line_min, line_max;
+    // Sets the data up to record a new series of corked logs.
+    void Reset() {
+      message[0] = '\0';  // make strlen of it 0
+      line_min = INT_MAX;
+      line_max = -1;
+      function = NULL;
+    }
+    // The function that the calls are in.
+    // REMEMBER: While the compiler/linker will probably optimize all of the
+    // identical strings to point to the same data, it might not, so using == to
+    // compare this with another value is a bad idea.
+    const char *function;
+  } cork_data;
+};
+
+// Fills in *message according to the given inputs. Used for implementing
+// LogImplementation::DoLog.
+void FillInMessage(log_level level, const char *format, va_list ap,
+                   LogMessage *message);
+
+// Prints message to output.
+void PrintMessage(FILE *output, const LogMessage &message);
+
+}  // namespace internal
+}  // namespace logging
+}  // namespace aos
+
+#endif  // AOS_COMMON_LOGGING_LOGGING_IMPL_H_