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; }