diff --git a/src/thread/thread.c b/src/thread/thread.c index 1acfa4c..e678e05 100644 --- a/src/thread/thread.c +++ b/src/thread/thread.c @@ -16,7 +16,8 @@ #define WAS_ALLOCATED(entry) (entry->status & ALLOCATED) #define WAITING 0x4 #define IS_WAITING(entry) (entry->status & WAITING) -#define IS_WAITING_THREAD_FINISHED(entry) (((struct context_entry*)entry->retvalue)->status & FINISHED) +#define GET_WAITING_THREAD(entry) ((struct context_entry*)entry->waiting) +#define IS_WAITING_THREAD_FINISHED(entry) (GET_WAITING_THREAD(entry)->status & FINISHED) #define WAITED 0x8 #define IS_WAITED(entry) (entry->status & WAITED) @@ -24,7 +25,7 @@ #define STACK_SIZE 4096 #endif -// Variables used to clean up everything at the end of the processes +// Variables used to clean up everything at the end of the processus static char stack_for_freeing[STACK_SIZE] = {0}; static int stack_valgrind_id = 0; static ucontext_t context_for_freeing; @@ -34,6 +35,7 @@ struct context_entry { link; // Use to navigate inside the list ucontext_t context; thread_t id; + void *waiting; void* retvalue; int valgrind_id; char status; @@ -136,8 +138,8 @@ int thread_join(thread_t thread, void** retval) { TRACE("Join thread %p", thread); struct context_entry* entry = thread; - // Check if the target is not already waited by an other - if (IS_WAITED(entry)) { + // Check if the target is not already waited by another + if (IS_WAITED(entry) || IS_WAITING(entry) && GET_WAITING_THREAD(entry) != running) { return -1; } @@ -145,14 +147,13 @@ int thread_join(thread_t thread, void** retval) // Use status to be in waiting state running->status |= WAITING; // Use retvalue to share which thread we are currently waiting for - running->retvalue = entry; + running->waiting = entry; // Mark the waited thread as waited to not be waited by any other thread. entry->status |= WAITED; entry->retvalue = running; do { thread_yield(); } while (!IS_FINISHED(entry)); - // Exit from waiting state running->status &= ~WAITING; } @@ -177,7 +178,7 @@ void thread_exit(void* retval) { TRACE("Exit thread %p", running); print_entry(running); - if (running == 0) { + if (running == NULL) { exit(0); } @@ -240,8 +241,8 @@ void __attribute__((constructor)) setup_main_thread() void __attribute__((destructor)) clear_last_thread() { TRACE("POST"); - TAILQ_INSERT_HEAD(&head, running, link); // Running is the initial main thread. No need to switch to a static stack. + TAILQ_INSERT_HEAD(&head, running, link); if (!WAS_ALLOCATED(running)) { clear_context(); exit(0);