diff --git a/inc/mthread/mthread.h b/inc/mthread/mthread.h
index c708a4414d54bce351aaa564ee4a5b4da46c9f2d..2e76942fac27e11ccadcec1b954f95a8de84f264 100644
--- a/inc/mthread/mthread.h
+++ b/inc/mthread/mthread.h
@@ -9,8 +9,11 @@ typedef struct mthread_list_s mthread_list_t;
 struct mthread_s;
 typedef struct mthread_s *mthread_t;
 
-struct mthread_attr_s;
-typedef struct mthread_attr_s mthread_attr_t;
+typedef enum {
+    ATTR_NONE           = 0,
+    ATTR_DETACHED       = (1 << 1),
+    ATTR_DETACHED_FREE  = (1 << 2),
+} mthread_attr_t;
 
 struct mthread_mutex_s {
     volatile int nb_thread;
@@ -45,37 +48,34 @@ typedef struct mthread_sem_s mthread_sem_t;
 
 /* Function for handling threads.  */
 
-int mthread_create(mthread_t *__threadp, const mthread_attr_t *__attr, void *(*__start_routine) (void *),
-                   void *__arg);
+int mthread_create(mthread_t *__threadp, const mthread_attr_t *__attr, void *(*__start_routine) (void *), void *__arg);
 
 mthread_t mthread_self(void);
-int mthread_equal(mthread_t __thread1, mthread_t __thread2);
-void mthread_exit(void *__retval);
-int mthread_join(mthread_t __th, void **__thread_return);
+int  mthread_equal (mthread_t __thread1, mthread_t __thread2);
+void mthread_exit  (void *__retval);
+int  mthread_join  (mthread_t __th, void **__thread_return);
 
 /* Functions for mutex handling.  */
 
-int mthread_mutex_init (mthread_mutex_t *__mutex,
-                        const mthread_mutexattr_t *__mutex_attr);
+int mthread_mutex_init   (mthread_mutex_t *__mutex, const mthread_mutexattr_t *__mutex_attr);
 int mthread_mutex_destroy(mthread_mutex_t *__mutex);
 int mthread_mutex_trylock(mthread_mutex_t *__mutex);
-int mthread_mutex_lock(mthread_mutex_t *__mutex);
-int mthread_mutex_unlock(mthread_mutex_t *__mutex);
+int mthread_mutex_lock   (mthread_mutex_t *__mutex);
+int mthread_mutex_unlock (mthread_mutex_t *__mutex);
 
 /* Functions for handling conditional variables.  */
 
-int mthread_cond_init(mthread_cond_t *__cond,
-                      const mthread_condattr_t *__cond_attr);
-int mthread_cond_destroy(mthread_cond_t *__cond);
-int mthread_cond_signal(mthread_cond_t *__cond);
+int mthread_cond_init     (mthread_cond_t *__cond, const mthread_condattr_t *__cond_attr);
+int mthread_cond_destroy  (mthread_cond_t *__cond);
+int mthread_cond_signal   (mthread_cond_t *__cond);
 int mthread_cond_broadcast(mthread_cond_t *__cond);
-int mthread_cond_wait(mthread_cond_t *__cond, mthread_mutex_t *__mutex);
+int mthread_cond_wait     (mthread_cond_t *__cond, mthread_mutex_t *__mutex);
 
 /* Functions for handling thread-specific data.  */
 
-int mthread_key_create(mthread_key_t *__key, void (*__destr_function) (void *));
-int mthread_key_delete(mthread_key_t __key);
-int mthread_setspecific(mthread_key_t __key, const void *__pointer);
+int mthread_key_create   (mthread_key_t *__key, void (*__destr_function) (void *));
+int mthread_key_delete   (mthread_key_t __key);
+int mthread_setspecific  (mthread_key_t __key, const void *__pointer);
 void *mthread_getspecific(mthread_key_t __key);
 
 
@@ -97,9 +97,8 @@ int mthread_sem_wait(mthread_sem_t *sem);     /* P(sem), wait(sem) */
 int mthread_sem_post(mthread_sem_t *sem);     /* V(sem), signal(sem) */
 
 int mthread_sem_getvalue(mthread_sem_t *sem, int *sval);
-int mthread_sem_trywait(mthread_sem_t *sem);
-
-int mthread_sem_destroy(mthread_sem_t *sem);  /* undo sem_init() */
+int mthread_sem_trywait (mthread_sem_t *sem);
+int mthread_sem_destroy (mthread_sem_t *sem);  /* undo sem_init() */
 
 void mthread_yield();
 
diff --git a/inc/mthread/mthread_internal.h b/inc/mthread/mthread_internal.h
index c4eb661d17602bc96fd4bb81395e9176ae039a26..0462d0cf9ea8a4139e3178279770d6941a23a504 100644
--- a/inc/mthread/mthread_internal.h
+++ b/inc/mthread/mthread_internal.h
@@ -29,6 +29,7 @@ typedef struct {
 } mthread_virtual_processor_t;
 
 typedef enum { RUNNING, BLOCKED, ZOMBIE } mthread_status_t;
+typedef volatile enum { JOINABLE = 0, DETACHED = 1, DETACHED_FREE = 2 } mthread_detached_flag_t;
 
 #define INIT_KEYS_LIST 48
 
@@ -45,6 +46,7 @@ struct mthread_s {
     void *(*__start_routine) (void *);
     volatile struct mthread_s *next;
     volatile mthread_status_t status;
+    mthread_detached_flag_t detached;
     int not_migrable;
     mthread_virtual_processor_t *vp;
     void *stack;
@@ -53,17 +55,17 @@ struct mthread_s {
 
 #define MTHREAD_LIST_INIT { .first = NULL, .last = NULL, .lock = 0 }
 
-int mthread_test_and_set(mthread_tst_t *atomic);
-void mthread_spinlock_lock(mthread_tst_t *atomic);
+int  mthread_test_and_set   (mthread_tst_t *atomic);
+void mthread_spinlock_lock  (mthread_tst_t *atomic);
 void mthread_spinlock_unlock(mthread_tst_t *atomic);
-int mthread_get_vp_rank();
+int  mthread_get_vp_rank();
 
 void *safe_malloc(size_t size);
 
 void mthread_insert_first(struct mthread_s *item, mthread_list_t *list);
-void mthread_insert_last(struct mthread_s *item, mthread_list_t *list);
+void mthread_insert_last (struct mthread_s *item, mthread_list_t *list);
+int  mthread_list_test   (struct mthread_s *item, mthread_list_t *list);
 struct mthread_s *mthread_remove_first(mthread_list_t *list);
-int mthread_list_test(struct mthread_s *item, mthread_list_t *list);
 
 void __mthread_yield(mthread_virtual_processor_t *vp);
 mthread_virtual_processor_t *mthread_get_vp();
diff --git a/src/mthread/mthread.c b/src/mthread/mthread.c
index 4944174f9b70ed5ce3dae073c32d02ec46122b75..78c9dabc8e08f30220df99467c8cbe5d282729b7 100644
--- a/src/mthread/mthread.c
+++ b/src/mthread/mthread.c
@@ -36,9 +36,10 @@ mthread_list_init(mthread_list_t *list)
 static inline void
 mthread_init_thread(struct mthread_s *thread)
 {
-    thread->next   = NULL;
-    thread->status = RUNNING;
-    thread->res    = NULL;
+    thread->detached = JOINABLE;
+    thread->next     = NULL;
+    thread->status   = RUNNING;
+    thread->res      = NULL;
 }
 
 void
@@ -91,17 +92,13 @@ extern int
 mthread_list_test(struct mthread_s *item, mthread_list_t *list)
 {
     struct mthread_s *it = (struct mthread_s *) list->last;
-
     while (it && it != item)
         it = (struct mthread_s *) it->next;
-
     return it == item;
 }
 
 static inline int
-mthread_mctx_set(struct mthread_s *mctx,
-                 void (*func) (void *), char *stack, size_t size,
-                 void *arg)
+mthread_mctx_set(struct mthread_s *mctx, void (*func) (void *), char *stack, size_t size, void *arg)
 {
     /* fetch current context */
     RETURN_IF(getcontext(&(mctx->uc)) != 0, "Error in getcontext", 1);
@@ -202,8 +199,7 @@ mthread_get_vp_rank()
 }
 
 static inline void
-mthread_init_vp(mthread_virtual_processor_t *vp, struct mthread_s *idle,
-                struct mthread_s *current, int rank)
+mthread_init_vp(mthread_virtual_processor_t *vp, struct mthread_s *idle, struct mthread_s *current, int rank)
 {
     vp->current = current;
     vp->idle    = idle;
@@ -216,7 +212,7 @@ mthread_init_vp(mthread_virtual_processor_t *vp, struct mthread_s *idle,
 void *
 mthread_main(void *arg)
 {
-    (void)arg;
+    UNUSED(arg);
     mthread_virtual_processor_t *vp = mthread_get_vp();
     while (1) {
         sched_yield();
@@ -233,7 +229,6 @@ mthread_init_lib(long i)
     char *stack               = (char *) safe_malloc(MTHREAD_DEFAULT_STACK);
     struct mthread_s *mctx    = (struct mthread_s *) safe_malloc(sizeof(struct mthread_s));
     mthread_init_thread(mctx);
-
     mthread_list_init(&(joined_list));
 
     if (i == 0) {
@@ -256,12 +251,18 @@ static void
 mthread_start_thread(void *arg)
 {
     struct mthread_s *mctx = (struct mthread_s *)arg;
-    LOG_INFO_SCT("THREAD INIT", "Thread %p started", arg);
+    LOG_INFO_SCT("THREAD", "Thread %p started", arg);
     mthread_virtual_processor_t *vp = mthread_get_vp();
     __mthread_yield(vp);
     mctx->res    = mctx->__start_routine(mctx->arg);
     mctx->status = ZOMBIE;
-    LOG_INFO_SCT("THREAD END", "Thread %p ended (%d)", arg, vp->rank);
+    LOG_INFO_SCT("THREAD", "Thread %p ended (%d)", arg, vp->rank);
+    if (mctx->detached) {
+        LOG_INFO_SCT("THREAD", "Thread %p (vp: %d) was detached, join it", arg, vp->rank);
+        mthread_join(mctx, NULL);
+        if (mctx->detached == DETACHED_FREE)
+            free(mctx);
+    }
     vp = mthread_get_vp();
     __mthread_yield(vp);
 }
@@ -289,8 +290,7 @@ mthread_init(void)
    if ATTR is NULL), and call function START_ROUTINE with given
    arguments ARG.  */
 int
-mthread_create(mthread_t *__threadp, const mthread_attr_t *__attr,
-               void *(*__start_routine) (void *), void *__arg)
+mthread_create(mthread_t *__threadp, const mthread_attr_t *__attr, void *(*__start_routine) (void *), void *__arg)
 {
     if (is_mthread_init == 0) {
         __mthread_lib_init(0);
@@ -299,23 +299,28 @@ mthread_create(mthread_t *__threadp, const mthread_attr_t *__attr,
 
     mthread_virtual_processor_t *vp = mthread_get_vp();
 
-    if (__attr == NULL) {
-        struct mthread_s *mctx = mthread_remove_first(&(joined_list));
-        if (mctx == NULL) {
-            mctx = safe_malloc(sizeof(struct mthread_s));
-            memset(mctx, 0, sizeof(struct mthread_s));
-        }
-        char *stack = mctx->stack ? mctx->stack : safe_malloc(MTHREAD_DEFAULT_STACK);
-
-        mthread_init_thread(mctx);
-        LOG_INFO_SCT("THREAD INIT", "Create thread %p", (void *) mctx);
-        mctx->arg = __arg;
-        mctx->__start_routine = __start_routine;
-        mthread_mctx_set(mctx, mthread_start_thread, stack, MTHREAD_DEFAULT_STACK, mctx);
-        mthread_insert_last(mctx, &(vp->ready_list));
-        *__threadp = mctx;
-    } else
-        not_implemented();
+    struct mthread_s *mctx = mthread_remove_first(&(joined_list));
+    if (mctx == NULL) {
+        mctx = safe_malloc(sizeof(struct mthread_s));
+        memset(mctx, 0, sizeof(struct mthread_s));
+    }
+    char *stack = mctx->stack ? mctx->stack : safe_malloc(MTHREAD_DEFAULT_STACK);
+
+    mthread_init_thread(mctx);
+
+    if (__attr) {
+        if (*__attr & ATTR_DETACHED)
+            mctx->detached = DETACHED;
+        if (*__attr & ATTR_DETACHED_FREE)
+            mctx->detached = DETACHED_FREE;
+    }
+
+    LOG_INFO_SCT("THREAD INIT", "Create thread %p", (void *) mctx);
+    mctx->arg = __arg;
+    mctx->__start_routine = __start_routine;
+    mthread_mctx_set(mctx, mthread_start_thread, stack, MTHREAD_DEFAULT_STACK, mctx);
+    mthread_insert_last(mctx, &(vp->ready_list));
+    *__threadp = mctx;
 
     return 0;
 }