diff --git a/src/thread/thread.c b/src/thread/thread.c index 0e1c9fe..bda3397 100644 --- a/src/thread/thread.c +++ b/src/thread/thread.c @@ -1,3 +1,4 @@ +#include #ifndef USE_PTHREAD #include "thread.h" @@ -9,19 +10,21 @@ #include #include +#define FINISHED 0x1 +#define ALLOCATED 0x2 + #ifndef STACK_SIZE #define STACK_SIZE 4096*4 #endif struct context_entry { + TAILQ_ENTRY(context_entry) link; ucontext_t context; thread_t id; thread_t parent; - int was_allocated; - int finished; void *retvalue; int valgrind_id; - TAILQ_ENTRY(context_entry) link; + char status; }; static TAILQ_HEAD(context_head, context_entry) head = TAILQ_HEAD_INITIALIZER(head); @@ -33,17 +36,21 @@ int thread_yield(void) { return 0; } struct context_entry *first; + int count = 0; do { + if (count++ == counter) { + return 0; + } first = TAILQ_FIRST(&head); if (!first) { return -1; } + TAILQ_REMOVE(&head, first, link); + TAILQ_INSERT_TAIL(&head, first, link); if (first->id == running->id) { return 0; } - TAILQ_REMOVE(&head, first, link); - TAILQ_INSERT_TAIL(&head, first, link); - } while (first->finished); + } while (first->status & FINISHED); struct context_entry *old_runner = running; running = first; swapcontext(&old_runner->context, &running->context); @@ -61,17 +68,18 @@ int thread_create(thread_t *newthread, void *(*func)(void *), void *funcarg) { TRACE("Create a new thread that execute function %p", func); if (counter == 0) { struct context_entry *main = malloc(sizeof(*main)); + memset(main, 0, sizeof(*main)); getcontext(&main->context); main->id = 0; main->parent = 0; - main->finished = 0; + main->status = 0; main->retvalue = 0; - main->was_allocated = 0; TAILQ_INSERT_HEAD(&head, main, link); running = main; counter++; } struct context_entry *new_entry = malloc(sizeof(*new_entry)); + memset(new_entry, 0, sizeof(*new_entry)); getcontext(&new_entry->context); new_entry->context.uc_stack.ss_sp = malloc(STACK_SIZE); new_entry->context.uc_stack.ss_size = STACK_SIZE; @@ -81,9 +89,8 @@ int thread_create(thread_t *newthread, void *(*func)(void *), void *funcarg) { ); new_entry->id = new_entry; new_entry->parent = running->id; - new_entry->finished = 0; + new_entry->status = ALLOCATED; new_entry->retvalue = 0; - new_entry->was_allocated = 1; *newthread = new_entry; makecontext(&new_entry->context, (void (*)()) func, 1, funcarg); counter++; @@ -92,7 +99,7 @@ int thread_create(thread_t *newthread, void *(*func)(void *), void *funcarg) { } void print_entry(struct context_entry *entry) { - TRACE("CONTEXT (%p, %p, %d, %p);\n", entry, entry->id, entry->finished, entry->parent); + TRACE("CONTEXT (%p, %p, %d, %p);\n", entry, entry->id, (entry->status & FINISHED) > 0, entry->parent); } int thread_join(thread_t thread, void **retval) { @@ -102,20 +109,27 @@ int thread_join(thread_t thread, void **retval) { if (entry->id != thread) { continue; } - while (!entry->finished) { + TRACE("FIND"); + print_entry(entry); + while (!entry->status & FINISHED) { + TRACE("NOT FINISHED"); thread_yield(); } + TRACE("AFTER"); if (retval) *retval = entry->retvalue; TAILQ_REMOVE(&head, entry, link); - if (entry->was_allocated) { + if (entry->status & ALLOCATED) { + TRACE("FREE\n"); VALGRIND_STACK_DEREGISTER(entry->valgrind_id); free(entry->context.uc_stack.ss_sp); + } else { + TRACE("NOT ALLOCATED\n"); } free(entry); if (--counter == 1) { TAILQ_REMOVE(&head, running, link); - if (running->was_allocated) { + if (running->status & ALLOCATED) { VALGRIND_STACK_DEREGISTER(running->valgrind_id); free(running->context.uc_stack.ss_sp); } @@ -130,7 +144,7 @@ int thread_join(thread_t thread, void **retval) { void thread_exit(void *retval) { TRACE("Exit thread %p", running); - running->finished = 1; + running->status |= FINISHED; running->retvalue = retval; thread_yield(); }