Index: uspace/lib/cpp/include/impl/mutex.hpp
===================================================================
--- uspace/lib/cpp/include/impl/mutex.hpp	(revision c4049e626273ba323a04efe45158784fbaa8c474)
+++ uspace/lib/cpp/include/impl/mutex.hpp	(revision 9283830f49ecdb0b8a77c1fd2b8d90175b10e756)
@@ -31,13 +31,9 @@
 
 #include <internal/common.hpp>
+#include <internal/thread.hpp>
 #include <thread>
 
 namespace std
 {
-    extern "C" {
-        #include <fibril.h>
-        #include <fibril_synch.h>
-    }
-
     /**
      * 20.4.1.2.1, class mutex:
@@ -47,5 +43,10 @@
     {
         public:
-            constexpr mutex() noexcept;
+            constexpr mutex() noexcept
+                : mtx_{}
+            {
+                aux::threading::mutex::init(mtx_);
+            }
+
             ~mutex();
 
@@ -57,9 +58,9 @@
             void unlock();
 
-            using native_handle_type = fibril_mutex_t*;
+            using native_handle_type = aux::mutex_t*;
             native_handle_type native_handle();
 
         private:
-            native_handle_type mtx_;
+            aux::mutex_t mtx_;
     };
 
@@ -81,9 +82,9 @@
             void unlock();
 
-            using native_handle_type = fibril_mutex_t*;
+            using native_handle_type = aux::mutex_t*;
             native_handle_type native_handle();
 
         private:
-            native_handle_type mtx_;
+            aux::mutex_t mtx_;
             size_t lock_level_;
             thread::id owner_;
Index: uspace/lib/cpp/include/impl/ratio.hpp
===================================================================
--- uspace/lib/cpp/include/impl/ratio.hpp	(revision c4049e626273ba323a04efe45158784fbaa8c474)
+++ uspace/lib/cpp/include/impl/ratio.hpp	(revision 9283830f49ecdb0b8a77c1fd2b8d90175b10e756)
@@ -89,5 +89,5 @@
     {
         public:
-            static_assert(D != 0, "ratio with denominator == 0");
+            /* static_assert(D != 0, "ratio with denominator == 0"); */
 
             static constexpr intmax_t num = aux::sign_v<N> * aux::sign_v<D>
Index: uspace/lib/cpp/include/impl/thread.hpp
===================================================================
--- uspace/lib/cpp/include/impl/thread.hpp	(revision c4049e626273ba323a04efe45158784fbaa8c474)
+++ uspace/lib/cpp/include/impl/thread.hpp	(revision 9283830f49ecdb0b8a77c1fd2b8d90175b10e756)
@@ -32,13 +32,9 @@
 #include <chrono>
 #include <internal/common.hpp>
+#include <internal/thread.hpp>
 #include <ostream>
 
 namespace std
 {
-    extern "C" {
-        #include <fibril.h>
-        #include <fibril_synch.h>
-    }
-
     namespace aux
     {
@@ -59,14 +55,14 @@
                       finished_{false}, detached_{false}
                 {
-                    fibril_mutex_initialize(&join_mtx_);
-                    fibril_condvar_initialize(&join_cv_);
+                    aux::threading::mutex::init(join_mtx_);
+                    aux::threading::condvar::init(join_cv_);
                 }
 
                 void join()
                 {
-                    fibril_mutex_lock(&join_mtx_);
+                    aux::threading::mutex::lock(join_mtx_);
                     while (!finished_)
-                        fibril_condvar_wait(&join_cv_, &join_mtx_);
-                    fibril_mutex_unlock(&join_mtx_);
+                        aux::threading::condvar::wait(join_cv_, join_mtx_);
+                    aux::threading::mutex::unlock(join_mtx_);
                 }
 
@@ -87,6 +83,6 @@
 
             protected:
-                fibril_mutex_t join_mtx_;
-                fibril_condvar_t join_cv_;
+                aux::mutex_t join_mtx_;
+                aux::condvar_t join_cv_;
                 bool finished_;
                 bool detached_;
@@ -105,9 +101,9 @@
                     callable_();
 
-                    fibril_mutex_lock(&join_mtx_);
+                    aux::threading::mutex::lock(join_mtx_);
                     finished_ = true;
-                    fibril_mutex_unlock(&join_mtx_);
-
-                    fibril_condvar_broadcast(&join_cv_);
+                    aux::threading::mutex::unlock(join_mtx_);
+
+                    aux::threading::condvar::broadcast(join_cv_);
                 }
 
@@ -126,5 +122,5 @@
             class id;
 
-            using native_handle_type = fibril_t*;
+            using native_handle_type = aux::thread_t*;
 
             /**
@@ -150,9 +146,11 @@
                 joinable_wrapper_ = static_cast<aux::joinable_wrapper*>(callable_wrapper);
 
-                id_ = fibril_create(
-                        aux::thread_main<decltype(callable_wrapper)>,
-                        static_cast<void*>(callable_wrapper)
+                id_ = aux::threading::thread::create(
+                    aux::thread_main<decltype(callable_wrapper)>,
+                    *callable_wrapper
                 );
-                fibril_add_ready(id_);
+
+                aux::threading::thread::start(id_);
+                // TODO: fibrils are weird here, 2 returns with same thread ids
             }
 
@@ -182,5 +180,5 @@
 
         private:
-            fid_t id_;
+            aux::thread_t id_;
             aux::joinable_wrapper* joinable_wrapper_{nullptr};
 
@@ -223,7 +221,7 @@
         {
             auto now = Clock::now();
-            auto usecs = chrono::duration_cast<chrono::duration<typename Duration::rep, micro>>(abs_time - now);
-
-            fibril_usleep(usecs.count());
+
+            auto time = aux::threading::time::convert(abs_time - now);
+            aux::threading::time::sleep(time);
         }
 
@@ -235,6 +233,6 @@
 
             // TODO: timeouts?
-            auto usecs = chrono::duration_cast<chrono::duration<Rep, micro>>(rel_time);
-            fibril_usleep(usecs.count());
+            auto time = aux::threading::time::convert(rel_time);
+            aux::threading::time::sleep(time);
         }
     }
Index: uspace/lib/cpp/include/internal/thread.hpp
===================================================================
--- uspace/lib/cpp/include/internal/thread.hpp	(revision 9283830f49ecdb0b8a77c1fd2b8d90175b10e756)
+++ uspace/lib/cpp/include/internal/thread.hpp	(revision 9283830f49ecdb0b8a77c1fd2b8d90175b10e756)
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2018 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBCPP_INTERNAL_THREAD
+#define LIBCPP_INTERNAL_THREAD
+
+namespace std
+{ // TODO: fix cheaders
+    extern "C" {
+        #include <fibril.h>
+        #include <fibril_synch.h>
+    }
+}
+
+#include <chrono>
+
+namespace std::aux
+{
+    struct fibril_tag
+    { /* DUMMY BODY */ };
+
+    struct thread_tag
+    { /* DUMMY BODY */ };
+
+    template<class>
+    struct threading_policy;
+
+    template<>
+    struct threading_policy<fibril_tag>
+    {
+        using mutex_type   = fibril_mutex_t;
+        using thread_type  = fid_t;
+        using condvar_type = fibril_condvar_t;
+        using time_unit    = suseconds_t;
+
+        struct thread
+        {
+            template<class Callable, class Payload>
+            static thread_type create(Callable clbl, Payload& pld)
+            {
+                return fibril_create(clbl, (void*)&pld);
+            }
+
+            static void start(thread_type thr)
+            {
+                fibril_add_ready(thr);
+            }
+
+            static thread_type this_thread()
+            {
+                return fibril_get_id();
+            }
+
+            static void yield()
+            {
+                fibril_yield();
+            }
+
+            /**
+             * Note: join & detach are performed at the C++
+             *       level at the moment, but eventually should
+             *       be moved here once joinable fibrils are in libc.
+             */
+        };
+
+        struct mutex
+        {
+            static void init(mutex_type& mtx)
+            {
+                fibril_mutex_initialize(&mtx);
+            }
+
+            static void lock(mutex_type& mtx)
+            {
+                fibril_mutex_lock(&mtx);
+            }
+
+            static void unlock(mutex_type& mtx)
+            {
+                fibril_mutex_unlock(&mtx);
+            }
+
+            static bool try_lock(mutex_type& mtx)
+            {
+                return fibril_mutex_trylock(&mtx);
+            }
+
+            static bool try_lock_for(mutex_type& mtx, time_unit timeout)
+            {
+                // TODO: we need fibril_mutex_trylock_for() :/
+                return try_lock(mtx);
+            }
+        };
+
+        struct condvar
+        {
+            static void init(condvar_type& cv)
+            {
+                fibril_condvar_initialize(&cv);
+            }
+
+            static void wait(condvar_type& cv, mutex_type& mtx)
+            {
+                fibril_condvar_wait(&cv, &mtx);
+            }
+
+            static void wait_for(condvar_type& cv, mutex_type& mtx, time_unit timeout)
+            {
+                fibril_condvar_wait_timeout(&cv, &mtx, timeout);
+            }
+
+            static void signal(condvar_type& cv)
+            {
+                fibril_condvar_signal(&cv);
+            }
+
+            static void broadcast(condvar_type& cv)
+            {
+                fibril_condvar_broadcast(&cv);
+            }
+        };
+
+        struct time
+        {
+            template<class Rep, class Period>
+            static time_unit convert(std::chrono::duration<Rep, Period> dur)
+            {
+                return std::chrono::duration_cast<std::chrono::duration<Rep, micro>>(dur).count();
+            }
+
+            static void sleep(time_unit time)
+            {
+                fibril_usleep(time);
+            }
+        };
+    };
+
+    template<>
+    struct threading_policy<thread_tag>
+    {
+        // TODO:
+    };
+
+    using default_tag = fibril_tag;
+    using threading = threading_policy<default_tag>;
+
+    using thread_t    = typename threading::thread_type;
+    using mutex_t     = typename threading::mutex_type;
+    using condvar_t   = typename threading::condvar_type;
+    using time_unit_t = typename threading::time_unit;
+}
+
+#endif
Index: uspace/lib/cpp/src/mutex.cpp
===================================================================
--- uspace/lib/cpp/src/mutex.cpp	(revision c4049e626273ba323a04efe45158784fbaa8c474)
+++ uspace/lib/cpp/src/mutex.cpp	(revision 9283830f49ecdb0b8a77c1fd2b8d90175b10e756)
@@ -31,37 +31,20 @@
 namespace std
 {
-    constexpr mutex::mutex() noexcept
-        : mtx_{}
-    {
-        fibril_mutex_initialize(&mtx_);
-    }
-
     mutex::~mutex()
-    {
-        if (fibril_mutex_is_locked(&mtx_))
-        {
-            /**
-             * According to the standard, this is
-             * undefined behavior, we could unlock the
-             * mutex, but that could cause issues if we
-             * are not the current owner.
-             */
-            // fibril_mutex_unlock(&mtx_);
-        }
-    }
+    { /* DUMMY BODY */ }
 
     void mutex::lock()
     {
-        fibril_mutex_lock(&mtx_);
+        aux::threading::mutex::lock(mtx_);
     }
 
     bool mutex::try_lock()
     {
-        return fibril_mutex_trylock(&mtx_);
+        return aux::threading::mutex::try_lock(mtx_);
     }
 
     void mutex::unlock()
     {
-        fibril_mutex_unlock(&mtx_);
+        aux::threading::mutex::unlock(mtx_);
     }
 
@@ -74,5 +57,5 @@
         : mtx_{}, lock_level_{}, owner_{}
     {
-        fibril_mutex_initialize(&mtx_);
+        aux::threading::mutex::init(mtx_);
     }
 
@@ -84,5 +67,5 @@
         if (owner_ != this_thread::get_id())
         {
-            fibril_mutex_lock(&mtx_);
+            aux::threading::mutex::lock(mtx_);
             owner_ = this_thread::get_id();
             lock_level_ = 1;
@@ -96,5 +79,5 @@
         if (owner_ != this_thread::get_id())
         {
-            bool res = fibril_mutex_trylock(&mtx_);
+            bool res = aux::threading::mutex::try_lock(mtx_);
             if (res)
             {
@@ -116,5 +99,5 @@
             return;
         else if (--lock_level_ == 0)
-            fibril_mutex_unlock(&mtx_);
+            aux::threading::mutex::unlock(mtx_);
     }
 
Index: uspace/lib/cpp/src/thread.cpp
===================================================================
--- uspace/lib/cpp/src/thread.cpp	(revision c4049e626273ba323a04efe45158784fbaa8c474)
+++ uspace/lib/cpp/src/thread.cpp	(revision 9283830f49ecdb0b8a77c1fd2b8d90175b10e756)
@@ -28,6 +28,9 @@
 
 #include <cstdlib>
+#include <exception>
 #include <thread>
 #include <utility>
+
+#include <iostream>
 
 namespace std
@@ -39,9 +42,13 @@
     thread::~thread()
     {
-        if (joinable())
-        {
-            // TODO: call std::terminate
-        }
+        // TODO: investigate joinable() in detail
+        //       + std::terminate behaves weirdly on HelenOS
+        if (joinable() && false)
+            std::terminate();
 
+        // TODO: check for finished too?
+        // TODO: WAIT! if it's not detached, then
+        //       we are joinable and std::terminate was called?
+        // TODO: review this entire thing
         if (joinable_wrapper_ && !joinable_wrapper_->detached())
             delete joinable_wrapper_;
@@ -49,7 +56,8 @@
 
     thread::thread(thread&& other) noexcept
-        : id_{other.id_}
+        : id_{other.id_}, joinable_wrapper_{other.joinable_wrapper_}
     {
-        other.id_ = fid_t{};
+        other.id_ = aux::thread_t{};
+        other.joinable_wrapper_ = nullptr;
     }
 
@@ -57,10 +65,11 @@
     {
         if (joinable())
-        {
-            // TODO: call std::terminate
-        }
+            std::terminate();
 
         id_ = other.id_;
-        other.id_ = fid_t{};
+        other.id_ = aux::thread_t{};
+
+        joinable_wrapper_ = other.joinable_wrapper_;
+        other.joinable_wrapper_ = nullptr;
 
         return *this;
@@ -70,9 +79,10 @@
     {
         std::swap(id_, other.id_);
+        std::swap(joinable_wrapper_, other.joinable_wrapper_);
     }
 
     bool thread::joinable() const noexcept
     {
-        return id_ != fid_t{};
+        return id_ != aux::thread_t{};
     }
 
@@ -85,5 +95,5 @@
     void thread::detach()
     {
-        id_ = fid_t{};
+        id_ = aux::thread_t{};
 
         if (joinable_wrapper_)
@@ -124,10 +134,10 @@
         thread::id get_id() noexcept
         {
-            return thread::id{fibril_get_id()};
+            return thread::id{aux::threading::thread::this_thread()};
         }
 
         void yield() noexcept
         {
-            fibril_yield();
+            aux::threading::thread::yield();
         }
     }
