diff --git a/projects/rocr-runtime/runtime/hsa-runtime/core/util/freebsd/os_freebsd.cpp b/projects/rocr-runtime/runtime/hsa-runtime/core/util/freebsd/os_freebsd.cpp
new file mode 100644
index 0000000000..a683c132ad
--- /dev/null
+++ b/projects/rocr-runtime/runtime/hsa-runtime/core/util/freebsd/os_freebsd.cpp
@@ -0,0 +1,989 @@
+// Sourojeet Adhikari
+// Not sure what Liscense to use
+// FreeBSD
+
+
+#ifdef __FreeBSD__
+#include "core/util/os.h"
+#include "core/util/utils.h"
+
+#include <link.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include <pthread_np.h>
+#include <limits.h>
+#include <sched.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <sys/cpuset.h>
+#include <sys/time.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <errno.h>
+#include <cstring>
+#include <atomic>
+#include <memory>
+#include <string>
+#include <utility>
+#include <semaphore.h>
+#include "core/inc/runtime.h"
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#if defined(__i386__) || defined(__x86_64__)
+#include <cpuid.h>
+#endif
+
+#ifndef CLOCK_BOOTTIME
+#ifdef CLOCK_UPTIME
+#define CLOCK_BOOTTIME CLOCK_UPTIME
+#else
+#define CLOCK_BOOTTIME CLOCK_MONOTONIC
+#endif
+#endif
+
+#ifndef MAP_NORESERVE
+#define MAP_NORESERVE 0
+#endif
+
+#ifndef MADV_HUGEPAGE
+#define MADV_HUGEPAGE 0
+#endif
+
+#ifdef __GLIBC__
+#define ABS_ADDR(base, ptr) (ptr)
+#else
+#define ABS_ADDR(base, ptr) ((base) + (ptr))
+#endif
+
+namespace rocr {
+namespace os {
+
+struct ThreadArgs {
+  void* entry_args;
+  ThreadEntry entry_function;
+};
+
+void* __stdcall ThreadTrampoline(void* arg) {
+  ThreadArgs* ar = (ThreadArgs*)arg;
+  ThreadEntry CallMe = ar->entry_function;
+  void* Data = ar->entry_args;
+  CallMe(Data);
+  return nullptr;
+}
+
+// Thread container allows multiple waits and separate close (destroy).
+class os_thread {
+ public:
+  explicit os_thread(ThreadEntry function,
+                      void* threadArgument,
+                      uint stackSize,
+                      int priority)
+      : thread(0), lock(nullptr), state(RUNNING) {
+    int err;
+    lock = CreateMutex();
+    if (lock == nullptr) return;
+
+    args.entry_args = threadArgument;
+    args.entry_function = function;
+
+    pthread_attr_t attrib;
+    err = pthread_attr_init(&attrib);
+    if (err != 0) {
+      fprintf(stderr, "pthread_attr_init failed: %s\n", strerror(err));
+      return;
+    }
+
+    MAKE_SCOPE_GUARD([&]() {
+      if (pthread_attr_destroy(&attrib))
+        fprintf(stderr, "pthread_attr_destroy failed: %s\n", strerror(err));
+    });
+
+    if (stackSize != 0) {
+      stackSize = Max(uint(PTHREAD_STACK_MIN), stackSize);
+      stackSize = AlignUp(stackSize, 4096);
+      err = pthread_attr_setstacksize(&attrib, stackSize);
+      if (err != 0) {
+        fprintf(stderr, "pthread_attr_setstacksize failed: %s\n", strerror(err));
+        return;
+      }
+    }
+
+    int cores = 0;
+    cpuset_t cpuset;
+
+    if (core::Runtime::runtime_singleton_->flag().override_cpu_affinity()) {
+      cores = sysconf(_SC_NPROCESSORS_CONF);
+      CPU_ZERO(&cpuset);
+      for (int i = 0; i < cores; i++) {
+        CPU_SET(i, &cpuset);
+      }
+#ifdef HAVE_PTHREAD_ATTR_SETAFFINITY_NP
+      err = pthread_attr_setaffinity_np(&attrib, sizeof(cpuset), &cpuset);
+      if (err != 0) {
+        fprintf(stderr, "pthread_attr_setaffinity_np failed: %s\n", strerror(err));
+        return;
+      }
+#endif
+    }
+
+    do {
+      err = pthread_create(&thread, &attrib, ThreadTrampoline, &args);
+      if (!err) break;
+
+      if (err != EINVAL || stackSize == 0) {
+        fprintf(stderr, "pthread_create failed %d (%s)\n", errno, strerror(errno));
+        thread = 0;
+        return;
+      }
+
+      // Probably a stack size error since system limits can be different from PTHREAD_STACK_MIN
+      // Attempt to grow the stack within reason.
+      stackSize *= 2;
+      if (pthread_attr_setstacksize(&attrib, stackSize)) {
+        fprintf(stderr, "pthread_attr_setstacksize failed: %s\n", strerror(err));
+        thread = 0;
+        return;
+      }
+    } while (stackSize < 20 * 1024 * 1024);
+
+#ifndef HAVE_PTHREAD_ATTR_SETAFFINITY_NP
+    if (cores) {
+      err = pthread_setaffinity_np(thread, sizeof(cpuset), &cpuset);
+      if (err != 0) {
+        fprintf(stderr, "pthread_setaffinity_np failed: %s\n", strerror(err));
+        thread = 0;
+        return;
+      }
+    }
+#endif
+    struct sched_param param = {};
+    if (priority != OS_THREAD_PRIORITY_DEFAULT) {
+      int set_priority;
+      int max_priority = sched_get_priority_max(SCHED_FIFO);
+
+      if (priority == OS_THREAD_PRIORITY_MAX)
+        set_priority = max_priority;
+      else if (priority == OS_THREAD_PRIORITY_HIGH)
+        set_priority = max_priority - 1;
+      else if (priority > max_priority)
+        set_priority = max_priority;
+      else
+        set_priority = priority;
+
+      param.sched_priority = set_priority;
+      if (pthread_setschedparam(thread, SCHED_FIFO, &param)) {
+        fprintf(stderr, "pthread_setschedparam failed\n");
+        return;
+      }
+
+      int policy = 0;
+      if (pthread_getschedparam(thread, &policy, &param))
+        fprintf(stderr, "pthread_getschedparam failed: %s\n", strerror(err));
+
+      if (policy != SCHED_FIFO || param.sched_priority != set_priority)
+        fprintf(stderr, "Failed to adjust thread priority (policy:%s requested:%d current:%d)\n",
+                          policy == SCHED_FIFO ? "FIFO" :
+                          policy == SCHED_OTHER ? "OTHER" :
+                          policy == SCHED_RR ? "RR" : "Unknown",
+                          set_priority, param.sched_priority);
+    }
+  }
+
+  os_thread(os_thread&& rhs) {
+    thread = rhs.thread;
+    args = rhs.args;
+    lock = rhs.lock;
+    state = int(rhs.state);
+    rhs.thread = 0;
+    rhs.lock = nullptr;
+  }
+
+  os_thread(os_thread&) = delete;
+
+  ~os_thread() {
+    if (lock != nullptr) DestroyMutex(lock);
+    if ((state == RUNNING) && (thread != 0)) {
+      int err = pthread_detach(thread);
+      if (err != 0) fprintf(stderr, "pthread_detach failed: %s\n", strerror(err));
+    }
+  }
+
+  bool Valid() { return (lock != nullptr) && (thread != 0); }
+
+  bool Wait() {
+    if (state == FINISHED) return true;
+    AcquireMutex(lock);
+    if (state == FINISHED) {
+      ReleaseMutex(lock);
+      return true;
+    }
+    int err = pthread_join(thread, NULL);
+    bool success = (err == 0);
+    if (success) state = FINISHED;
+    ReleaseMutex(lock);
+    return success;
+  }
+
+ private:
+  pthread_t thread;
+  struct ThreadArgs args;
+  Mutex lock;
+  std::atomic<int> state;
+  enum { FINISHED = 0, RUNNING = 1 };
+};
+
+static_assert(sizeof(LibHandle) == sizeof(void*), "OS abstraction size mismatch");
+static_assert(sizeof(Semaphore) == sizeof(sem_t*), "OS abstraction size mismatch");
+static_assert(sizeof(Mutex) == sizeof(pthread_mutex_t*), "OS abstraction size mismatch");
+static_assert(sizeof(SharedMutex) == sizeof(pthread_rwlock_t*), "OS abstraction size mismatch");
+static_assert(sizeof(Thread) == sizeof(os_thread*), "OS abstraction size mismatch");
+
+LibHandle LoadLib(std::string filename) {
+  int dlopen_flags = RTLD_LAZY;
+#ifdef RTLD_NODELETE
+  dlopen_flags |= RTLD_NODELETE;
+#endif
+  void* ret = dlopen(filename.c_str(), dlopen_flags);
+  if (ret == nullptr) debug_print("LoadLib(%s) failed: %s\n", filename.c_str(), dlerror());
+  return ret;
+}
+
+void* GetExportAddress(LibHandle lib, std::string export_name) {
+  void* ret = dlsym(*(void**)&lib, export_name.c_str());
+
+  if (ret == NULL) return ret;
+
+  link_map* map;
+  int err = dlinfo(*(void**)&lib, RTLD_DI_LINKMAP, &map);
+  if (err == -1) {
+    fprintf(stderr, "dlinfo failed: %s\n", dlerror());
+    return nullptr;
+  }
+
+  Dl_info info;
+  err = dladdr(ret, &info);
+  if (err == 0) {
+    fprintf(stderr, "dladdr failed.\n");
+    return nullptr;
+  }
+
+  if (strcmp(info.dli_fname, map->l_name) == 0) return ret;
+
+  return NULL;
+}
+
+bool CloseLib(LibHandle lib) { return (dlclose(*(void**)&lib) == 0) ? true : false; }
+
+#if defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("address")))
+#endif
+#endif
+static int callback(struct dl_phdr_info* info, size_t size, void* data) {
+  std::vector<std::string>* loadedToolsLib = (std::vector<std::string>*)data;
+  assert(loadedToolsLib != nullptr);
+
+  if ((info) && (info->dlpi_name) && (info->dlpi_name[0] != '\0')) {
+    if (std::string(info->dlpi_name).find("vdso.so") != std::string::npos) return 0;
+
+    for (int i = 0; i < info->dlpi_phnum; i++) {
+      if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) {
+        Elf64_Dyn* dyn_section = (Elf64_Dyn*)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
+
+        char* strings = nullptr;
+        Elf64_Xword limit = 0;
+
+        for (int j = 0;; j++) {
+          if (dyn_section[j].d_tag == DT_NULL) break;
+
+          if (dyn_section[j].d_tag == DT_STRTAB) strings = (char*)ABS_ADDR(info->dlpi_addr, dyn_section[j].d_un.d_ptr);
+
+          if (dyn_section[j].d_tag == DT_STRSZ) limit = dyn_section[j].d_un.d_val;
+        }
+
+        if (strings == nullptr) debug_print("String table not found");
+
+        if (strings != nullptr) {
+          char* end = strings + limit;
+          while (strings < end) {
+            if (strcmp(strings, "HSA_AMD_TOOL_PRIORITY") == 0) {
+              loadedToolsLib->push_back(info->dlpi_name);
+              return 0;
+            }
+            strings += (strlen(strings) + 1);
+          }
+        }
+      }
+    }
+  }
+  return 0;
+}
+
+std::vector<LibHandle> GetLoadedToolsLib() {
+  std::vector<LibHandle> ret;
+  std::vector<std::string> names;
+
+  dl_iterate_phdr(callback, &names);
+
+  if (!names.empty()) {
+    for (auto& name : names) ret.push_back(LoadLib(name));
+  }
+
+  return ret;
+}
+
+std::string GetLibraryName(LibHandle lib) {
+  link_map *map;
+  if(dlinfo(lib, RTLD_DI_LINKMAP, &map)!=0)
+    return "";
+  return map->l_name;
+}
+
+Semaphore CreateSemaphore() {
+  sem_t *sem = new sem_t;
+  sem_init(sem, 0, 0);
+  return *(Semaphore*)&sem;
+}
+
+bool WaitSemaphore(Semaphore sem) {
+  while(sem_wait(*(sem_t**)&sem))
+    if (errno != EINTR) return false;
+
+  return true;
+}
+
+void PostSemaphore(Semaphore sem) {
+  int waitval = 1;
+  if (sem_getvalue(*(sem_t**)&sem, &waitval))
+    assert(false && "Failed to get semaphore waiters");
+
+  if (waitval > 0)
+    return;
+
+  if (sem_post(*(sem_t**)&sem))
+    assert(false && "Failed to post semaphore");
+}
+
+void DestroySemaphore(Semaphore sem) {
+  sem_destroy(*(sem_t**)&sem);
+  delete *(sem_t**)&sem;
+}
+
+Mutex CreateMutex() {
+  pthread_mutex_t* mutex = new pthread_mutex_t;
+  pthread_mutex_init(mutex, NULL);
+  return *(Mutex*)&mutex;
+}
+
+bool TryAcquireMutex(Mutex lock) {
+  return pthread_mutex_trylock(*(pthread_mutex_t**)&lock) == 0;
+}
+
+bool AcquireMutex(Mutex lock) {
+  return pthread_mutex_lock(*(pthread_mutex_t**)&lock) == 0;
+}
+
+void ReleaseMutex(Mutex lock) {
+  pthread_mutex_unlock(*(pthread_mutex_t**)&lock);
+}
+
+void DestroyMutex(Mutex lock) {
+  pthread_mutex_destroy(*(pthread_mutex_t**)&lock);
+  delete *(pthread_mutex_t**)&lock;
+}
+
+void Sleep(int delay_in_millisec) { usleep(delay_in_millisec * 1000); }
+
+void uSleep(int delayInUs) { usleep(delayInUs); }
+
+void YieldThread() { sched_yield(); }
+
+Thread CreateThread(ThreadEntry function, void* threadArgument, uint stackSize, int priority) {
+  os_thread* result = new os_thread(function, threadArgument, stackSize, priority);
+  if (!result->Valid()) {
+    delete result;
+    return nullptr;
+  }
+
+  return reinterpret_cast<Thread>(result);
+}
+
+void CloseThread(Thread thread) { delete reinterpret_cast<os_thread*>(thread); }
+
+bool WaitForThread(Thread thread) { return reinterpret_cast<os_thread*>(thread)->Wait(); }
+
+bool WaitForAllThreads(Thread* threads, uint threadCount) {
+  for (uint i = 0; i < threadCount; i++) WaitForThread(threads[i]);
+  return true;
+}
+
+bool IsEnvVarSet(std::string env_var_name) {
+  char* buff = NULL;
+  buff = getenv(env_var_name.c_str());
+  return (buff != NULL);
+}
+
+void SetEnvVar(std::string env_var_name, std::string env_var_value) {
+  setenv(env_var_name.c_str(), env_var_value.c_str(), 1);
+}
+
+int GetProcessId() {
+  return ::getpid();
+}
+
+std::string GetEnvVar(std::string env_var_name) {
+  char* buff;
+  buff = getenv(env_var_name.c_str());
+  std::string ret;
+  if (buff) {
+    ret = buff;
+  }
+  return ret;
+}
+
+size_t GetUserModeVirtualMemorySize() {
+#ifdef _LP64
+  return (size_t)(0x800000000000);
+#else
+  return (size_t)(0xffffffff);  // ~4GB
+#endif
+}
+
+size_t GetUsablePhysicalHostMemorySize() {
+  unsigned long physmem;
+  size_t len = sizeof(physmem);
+  int mib[2] = { CTL_HW, HW_PHYSMEM };
+  if (sysctl(mib, 2, &physmem, &len, NULL, 0) != 0) {
+    return 0;
+  }
+  return std::min(GetUserModeVirtualMemorySize(), (size_t)physmem);
+}
+
+uintptr_t GetUserModeVirtualMemoryBase() { return (uintptr_t)0; }
+
+// Os event implementation
+typedef struct EventDescriptor_ {
+  pthread_cond_t event;
+  pthread_mutex_t mutex;
+  bool state;
+  bool auto_reset;
+} EventDescriptor;
+
+EventHandle CreateOsEvent(bool auto_reset, bool init_state) {
+  EventDescriptor* eventDescrp;
+  eventDescrp = (EventDescriptor*)malloc(sizeof(EventDescriptor));
+
+  if(!eventDescrp) { return nullptr; }
+
+  pthread_mutex_init(&eventDescrp->mutex, NULL);
+  pthread_cond_init(&eventDescrp->event, NULL);
+  eventDescrp->auto_reset = auto_reset;
+  eventDescrp->state = init_state;
+
+  EventHandle handle = reinterpret_cast<EventHandle>(eventDescrp);
+
+  return handle;
+}
+
+int DestroyOsEvent(EventHandle event) {
+  if (event == NULL) {
+    return -1;
+  }
+
+  EventDescriptor* eventDescrp = reinterpret_cast<EventDescriptor*>(event);
+  int ret_code = pthread_cond_destroy(&eventDescrp->event);
+  ret_code |= pthread_mutex_destroy(&eventDescrp->mutex);
+  free(eventDescrp);
+  return ret_code;
+}
+
+int WaitForOsEvent(EventHandle event, unsigned int milli_seconds) {
+  if (event == NULL) {
+    return -1;
+  }
+
+  EventDescriptor* eventDescrp = reinterpret_cast<EventDescriptor*>(event);
+  if (milli_seconds == 0) {
+    int tmp_ret = pthread_mutex_trylock(&eventDescrp->mutex);
+    if (tmp_ret == EBUSY) {
+      return 1;
+    }
+  } else {
+      pthread_mutex_lock(&eventDescrp->mutex);
+  }
+
+  int ret_code = 0;
+
+  if (!eventDescrp->state) {
+    if (milli_seconds == 0) {
+      ret_code = 1;
+    } else {
+      struct timespec ts;
+      struct timeval tp;
+
+      ret_code = gettimeofday(&tp, NULL);
+      ts.tv_sec = tp.tv_sec;
+      ts.tv_nsec = tp.tv_usec * 1000;
+
+      unsigned int sec = milli_seconds / 1000;
+      unsigned int mSec = milli_seconds % 1000;
+
+      ts.tv_sec += sec;
+      ts.tv_nsec += mSec * 1000000;
+
+      if (ts.tv_nsec > 1000000000) {
+        ts.tv_sec += 1;
+        ts.tv_nsec = ts.tv_nsec - 1000000000;
+      }
+
+      ret_code =
+          pthread_cond_timedwait(&eventDescrp->event, &eventDescrp->mutex, &ts);
+      if (ret_code == 110) {
+        ret_code = 0x14003;
+      }
+
+      if (ret_code == 0 && eventDescrp->auto_reset) {
+        eventDescrp->state = false;
+      }
+    }
+  } else if (eventDescrp->auto_reset) {
+    eventDescrp->state = false;
+  }
+  pthread_mutex_unlock(&eventDescrp->mutex);
+
+  return ret_code;
+}
+
+int SetOsEvent(EventHandle event) {
+  if (event == NULL) {
+    return -1;
+  }
+
+  EventDescriptor* eventDescrp = reinterpret_cast<EventDescriptor*>(event);
+  int ret_code = 0;
+  ret_code = pthread_mutex_lock(&eventDescrp->mutex);
+  eventDescrp->state = true;
+  ret_code = pthread_mutex_unlock(&eventDescrp->mutex);
+  ret_code |= pthread_cond_signal(&eventDescrp->event);
+
+  return ret_code;
+}
+
+int ResetOsEvent(EventHandle event) {
+  if (event == NULL) {
+    return -1;
+  }
+
+  EventDescriptor* eventDescrp = reinterpret_cast<EventDescriptor*>(event);
+  int ret_code = 0;
+  ret_code = pthread_mutex_lock(&eventDescrp->mutex);
+  eventDescrp->state = false;
+  ret_code = pthread_mutex_unlock(&eventDescrp->mutex);
+
+  return ret_code;
+}
+
+static double invPeriod = 0.0;
+
+uint64_t ReadAccurateClock() {
+  if (invPeriod == 0.0) AccurateClockFrequency();
+  timespec time;
+  int err = clock_gettime(CLOCK_MONOTONIC, &time);
+  if (err != 0) {
+    perror("clock_gettime(CLOCK_MONOTONIC,...) failed");
+    abort();
+  }
+  return (uint64_t(time.tv_sec) * 1000000000ull + uint64_t(time.tv_nsec)) * invPeriod;
+}
+
+uint64_t AccurateClockFrequency() {
+  static clockid_t clock = CLOCK_MONOTONIC;
+  timespec time;
+  int err = clock_getres(clock, &time);
+  if (err != 0) {
+    perror("clock_getres failed");
+    abort();
+  }
+  if (time.tv_sec != 0 || time.tv_nsec >= 0xFFFFFFFF) {
+    fprintf(stderr,
+            "clock_getres(CLOCK_MONOTONIC,...) returned very low "
+            "frequency (<1Hz).\n");
+    abort();
+  }
+  if (invPeriod == 0.0) invPeriod = 1.0 / double(time.tv_nsec);
+  return 1000000000ull / uint64_t(time.tv_nsec);
+}
+
+SharedMutex CreateSharedMutex() {
+  pthread_rwlockattr_t attrib;
+  int err = pthread_rwlockattr_init(&attrib);
+  if (err != 0) {
+    fprintf(stderr, "rw lock attribute init failed: %s\n", strerror(err));
+    return nullptr;
+  }
+
+#ifdef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
+  err = pthread_rwlockattr_setkind_np(&attrib, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
+  if (err != 0) {
+    fprintf(stderr, "Set rw lock attribute failure: %s\n", strerror(err));
+    return nullptr;
+  }
+#endif
+
+  std::unique_ptr<pthread_rwlock_t> lock(new pthread_rwlock_t);
+  err = pthread_rwlock_init(lock.get(), &attrib);
+  if (err != 0) {
+    fprintf(stderr, "rw lock init failed: %s\n", strerror(err));
+    return nullptr;
+  }
+
+  pthread_rwlockattr_destroy(&attrib);
+  return lock.release();
+}
+
+bool TryAcquireSharedMutex(SharedMutex lock) {
+  int err = pthread_rwlock_trywrlock(*(pthread_rwlock_t**)&lock);
+  return err == 0;
+}
+
+bool AcquireSharedMutex(SharedMutex lock) {
+  int err = pthread_rwlock_wrlock(*(pthread_rwlock_t**)&lock);
+  return err == 0;
+}
+
+void ReleaseSharedMutex(SharedMutex lock) {
+  int err = pthread_rwlock_unlock(*(pthread_rwlock_t**)&lock);
+  if (err != 0) {
+    fprintf(stderr, "SharedMutex unlock failed: %s\n", strerror(err));
+    abort();
+  }
+}
+
+bool TrySharedAcquireSharedMutex(SharedMutex lock) {
+  int err = pthread_rwlock_tryrdlock(*(pthread_rwlock_t**)&lock);
+  return err == 0;
+}
+
+bool SharedAcquireSharedMutex(SharedMutex lock) {
+  int err = pthread_rwlock_rdlock(*(pthread_rwlock_t**)&lock);
+  return err == 0;
+}
+
+void SharedReleaseSharedMutex(SharedMutex lock) {
+  int err = pthread_rwlock_unlock(*(pthread_rwlock_t**)&lock);
+  if (err != 0) {
+    fprintf(stderr, "SharedMutex unlock failed: %s\n", strerror(err));
+    abort();
+  }
+}
+
+void DestroySharedMutex(SharedMutex lock) {
+  pthread_rwlock_destroy(*(pthread_rwlock_t**)&lock);
+  delete *(pthread_rwlock_t**)&lock;
+}
+
+static uint64_t sys_clock_period_ = 0;
+
+uint64_t ReadSystemClock() {
+  struct timespec ts;
+  clock_gettime(CLOCK_BOOTTIME, &ts);
+  uint64_t time = (uint64_t(ts.tv_sec) * 1000000000 + uint64_t(ts.tv_nsec));
+  if (sys_clock_period_ != 1)
+    return time / sys_clock_period_;
+  else
+    return time;
+}
+
+uint64_t SystemClockFrequency() {
+  struct timespec ts;
+  clock_getres(CLOCK_BOOTTIME, &ts);
+  sys_clock_period_ = (uint64_t(ts.tv_sec) * 1000000000 + uint64_t(ts.tv_nsec));
+  return 1000000000 / sys_clock_period_;
+}
+
+bool ParseCpuID(cpuid_t* cpuinfo) {
+#if defined(__i386__) || defined(__x86_64__)
+  uint32_t eax, ebx, ecx, edx, max_eax = 0;
+  memset(cpuinfo, 0, sizeof(*cpuinfo));
+
+  if (!__get_cpuid_max(0x80000004, NULL)) return false;
+
+  if (!__get_cpuid(0, &max_eax, (uint32_t*)&cpuinfo->ManufacturerID[0],
+                   (uint32_t*)&cpuinfo->ManufacturerID[8],
+                   (uint32_t*)&cpuinfo->ManufacturerID[4])) {
+    return false;
+  }
+
+  if (!strcmp(cpuinfo->ManufacturerID, "AuthenticAMD")) {
+    if (__get_cpuid(0x80000001, &eax, &ebx, &ecx, &edx)) {
+      cpuinfo->mwaitx = !!((ecx >> 29) & 0x1);
+    }
+  }
+  return true;
+#else
+  return false;
+#endif
+}
+
+uint64_t TimeNanos() {
+  struct timespec tp;
+  ::clock_gettime(CLOCK_MONOTONIC, &tp);
+  return (uint64_t)tp.tv_sec * (1000ULL * 1000ULL * 1000ULL) + (uint64_t)tp.tv_nsec;
+}
+
+static inline int MemProtToOsProt(MemProt prot) {
+  switch (prot) {
+    case MEM_PROT_NONE:
+      return PROT_NONE;
+    case MEM_PROT_READ:
+      return PROT_READ;
+    case MEM_PROT_RW:
+      return PROT_READ | PROT_WRITE;
+    case MEM_PROT_RWX:
+      return PROT_READ | PROT_WRITE | PROT_EXEC;
+    default:
+      break;
+  }
+  return -1;
+}
+
+size_t PageSize() {
+  static size_t g_page_size_ = 0;
+  if (g_page_size_ == 0) {
+    g_page_size_ = (size_t)::sysconf(_SC_PAGESIZE);
+  }
+  return g_page_size_;
+}
+
+bool UnmapMemory(void* va, size_t size) { return ::munmap(va, size) == 0; }
+
+bool MapMemory(void* va, size_t size, MemProt perms, int fd, uint64_t cpu_addr) {
+  void* mapped_ptr = ::mmap(va, size, MemProtToOsProt(perms), 
+                            MAP_SHARED | MAP_FIXED, fd, cpu_addr);
+  if (mapped_ptr != va)
+      return false;
+  return true;
+}
+
+void* ReserveMemory(void* start, size_t size, size_t alignment, MemProt prot) {
+  size = AlignUp(size, PageSize());
+  if (size == 0) {
+    return NULL;
+  }
+  alignment = std::max(PageSize(), AlignUp(alignment, PageSize()));
+  assert(IsPowerOfTwo(alignment) && "not a power of 2");
+
+  size_t requested = size + alignment - PageSize();
+  address mem = (address)::mmap(start, requested, MemProtToOsProt(prot),
+                                MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS, 0, 0);
+
+  if (mem == MAP_FAILED) return NULL;
+
+  address aligned = AlignUp(mem, alignment);
+
+  if (&aligned[0] != &mem[0]) {
+    assert(&aligned[0] > &mem[0] && "check this code");
+    if (::munmap(&mem[0], &aligned[0] - &mem[0]) != 0) {
+      assert(!"::munmap failed");
+    }
+  }
+  if (&aligned[size] != &mem[requested]) {
+    assert(&aligned[size] < &mem[requested] && "check this code");
+    if (::munmap(&aligned[size], &mem[requested] - &aligned[size]) != 0) {
+      assert(!"::munmap failed");
+    }
+  }
+
+  constexpr size_t kLargePageSize = 2 * 1024 * 1024;
+  if (size >= kLargePageSize) {
+    int status = madvise(aligned, size, MADV_HUGEPAGE);
+    if (status) {
+      fprintf(stderr,
+              "madvise with advice MADV_HUGEPAGE"
+              " starting at address %p and page size 0x%zx, returned %d, errno: %s",
+              aligned, size, status, strerror(errno));
+    }
+  }
+
+  return aligned;
+}
+
+bool ReleaseMemory(void* addr, size_t size) {
+  assert(IsMultipleOf(addr, PageSize()) && "not page aligned!");
+  size = AlignUp(size, PageSize());
+
+  return 0 == ::munmap(addr, size);
+}
+
+bool CommitMemory(void* addr, size_t size, MemProt prot) {
+  assert(IsMultipleOf(addr, PageSize()) && "not page aligned!");
+  size = AlignUp(size, PageSize());
+
+  return ::mmap(addr, size, MemProtToOsProt(prot), MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1,
+                0) != MAP_FAILED;
+}
+
+bool UncommitMemory(void* addr, size_t size) {
+  assert(IsMultipleOf(addr, PageSize()) && "not page aligned!");
+  size = AlignUp(size, PageSize());
+
+  return ::mmap(addr, size, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANONYMOUS, -1,
+                0) != MAP_FAILED;
+}
+
+bool ProtectMemory(void* va, size_t size, MemProt perms) {
+  return ::mprotect(va, size, MemProtToOsProt(perms)) == 0;
+}
+
+uint64_t HostTotalPhysicalMemory() {
+  static uint64_t totalPhys = 0;
+
+  if (totalPhys != 0) {
+    return totalPhys;
+  }
+
+  totalPhys = sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES);
+  return totalPhys;
+}
+
+int Ffs(int i) { return ffs(i); }
+
+int Ctz(uint64_t i) { return __builtin_ctz(i); }
+
+int Popcount(uint32_t i) { return __builtin_popcount(i); }
+
+char* DlError() { return dlerror(); }
+
+static inline int IPCSockToFd(IPCSocket sock) {
+  return static_cast<int>(sock);
+}
+
+static inline IPCSocket FdToIPCSock(int fd) {
+  return static_cast<IPCSocket>(fd);
+}
+
+IPCSocket CreateIPCServer(const char* name, int backlog) {
+  int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+  if (fd == -1) return INVALID_SOCKET_VALUE;
+
+  struct sockaddr_un address;
+  memset(&address, 0, sizeof(address));
+  address.sun_family = AF_UNIX;
+  snprintf(address.sun_path, sizeof(address.sun_path), "/tmp/%s", name);
+
+  unlink(address.sun_path);
+
+  if (bind(fd, (struct sockaddr*)&address, sizeof(address)) != 0) {
+    close(fd);
+    return INVALID_SOCKET_VALUE;
+  }
+  if (listen(fd, backlog) != 0) {
+    close(fd);
+    return INVALID_SOCKET_VALUE;
+  }
+  return FdToIPCSock(fd);
+}
+
+IPCSocket AcceptIPCConnection(IPCSocket server) {
+  int fd = accept(IPCSockToFd(server), NULL, NULL);
+  if (fd == -1) return INVALID_SOCKET_VALUE;
+  return FdToIPCSock(fd);
+}
+
+IPCSocket ConnectToIPCServer(const char* name, std::chrono::milliseconds timeout,
+                             std::chrono::milliseconds retryInterval) {
+  int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+  if (fd == -1) return INVALID_SOCKET_VALUE;
+
+  struct sockaddr_un address;
+  memset(&address, 0, sizeof(address));
+  address.sun_family = AF_UNIX;
+  snprintf(address.sun_path, sizeof(address.sun_path), "/tmp/%s", name);
+
+  auto deadline = std::chrono::steady_clock::now() + timeout;
+  while (std::chrono::steady_clock::now() < deadline) {
+    if (connect(fd, (struct sockaddr*)&address, sizeof(address)) == 0)
+      return FdToIPCSock(fd);
+    usleep(static_cast<useconds_t>(retryInterval.count()) * 1000);
+  }
+
+  close(fd);
+  return INVALID_SOCKET_VALUE;
+}
+
+void SetIPCSocketRecvTimeout(IPCSocket sock, std::chrono::seconds timeout) {
+  struct timeval tv;
+  tv.tv_sec = static_cast<time_t>(timeout.count());
+  tv.tv_usec = 0;
+  setsockopt(IPCSockToFd(sock), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+}
+
+int IPCSocketRead(IPCSocket conn, void* buf, size_t len) {
+  return static_cast<int>(read(IPCSockToFd(conn), buf, len));
+}
+
+int IPCSocketWrite(IPCSocket conn, const void* buf, size_t len) {
+  return static_cast<int>(write(IPCSockToFd(conn), buf, len));
+}
+
+int IPCSendHandle(IPCSocket conn, intptr_t handle) {
+  int fd = static_cast<int>(handle);
+  char iov_buf[1] = {'y'};
+  struct iovec io = {.iov_base = iov_buf, .iov_len = 1};
+
+  char cmsg_buf[CMSG_SPACE(sizeof(int))];
+  memset(cmsg_buf, 0, sizeof(cmsg_buf));
+
+  struct msghdr msg = {};
+  msg.msg_iov = &io;
+  msg.msg_iovlen = 1;
+  msg.msg_control = cmsg_buf;
+  msg.msg_controllen = sizeof(cmsg_buf);
+
+  struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
+  if (!cmsg) return -1;
+  cmsg->cmsg_level = SOL_SOCKET;
+  cmsg->cmsg_type = SCM_RIGHTS;
+  cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+  memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
+
+  msg.msg_controllen = CMSG_SPACE(sizeof(int));
+
+  return (sendmsg(IPCSockToFd(conn), &msg, 0) < 0) ? -1 : 0;
+}
+
+intptr_t IPCRecvHandle(IPCSocket conn) {
+  char m_buffer[1];
+  struct iovec io = {.iov_base = m_buffer, .iov_len = sizeof(m_buffer)};
+
+  char c_buffer[256];
+  struct msghdr msg = {};
+  msg.msg_iov = &io;
+  msg.msg_iovlen = 1;
+  msg.msg_control = c_buffer;
+  msg.msg_controllen = sizeof(c_buffer);
+
+  ssize_t rcv = recvmsg(IPCSockToFd(conn), &msg, MSG_WAITALL);
+  if (rcv < 0) return -1;
+
+  while (!rcv)
+    rcv = recvmsg(IPCSockToFd(conn), &msg, MSG_WAITALL);
+
+  struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
+  if (!cmsg) return -1;
+  int fd;
+  memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));
+  return fd;
+}
+
+void CloseIPCSocket(IPCSocket sock) {
+  if (sock != INVALID_SOCKET_VALUE)
+    close(IPCSockToFd(sock));
+}
+
+}   //  namespace os
+}   //  namespace rocr
+
+#endif
