X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=libthreads.c;h=2ffe958ed193909cc2960fabcf28c9ee4d3eae4c;hb=dcd84cc88d70497bdc173c4bb78ce30afe4fb5c5;hp=bd7f501df3cc4c76a1d7bb30c982f66df802cc1e;hpb=6ac83ab66e4c564ffd0470ad25d5554eb5d52f28;p=model-checker.git diff --git a/libthreads.c b/libthreads.c index bd7f501..2ffe958 100644 --- a/libthreads.c +++ b/libthreads.c @@ -1,19 +1,25 @@ #include #include -//#define CONFIG_DEBUG - #include "libthreads.h" +#include "schedule.h" +#include "common.h" -#define STACK_SIZE (1024 * 1024) +/* global "model" object */ +#include "model.h" -static struct thread *current, *main_thread; +#define STACK_SIZE (1024 * 1024) static void *stack_allocate(size_t size) { return malloc(size); } +static void stack_free(void *stack) +{ + free(stack); +} + static int create_context(struct thread *t) { int ret; @@ -32,7 +38,7 @@ static int create_context(struct thread *t) t->context.uc_stack.ss_sp = t->stack; t->context.uc_stack.ss_size = STACK_SIZE; t->context.uc_stack.ss_flags = 0; - t->context.uc_link = &main_thread->context; + t->context.uc_link = &model->system_thread->context; makecontext(&t->context, t->start_routine, 1, t->arg); return 0; @@ -41,58 +47,68 @@ static int create_context(struct thread *t) static int create_initial_thread(struct thread *t) { memset(t, 0, sizeof(*t)); + model->assign_id(t); return create_context(t); } -static int thread_swap(struct thread *old, struct thread *new) +static int thread_swap(struct thread *t1, struct thread *t2) { - return swapcontext(&old->context, &new->context); + return swapcontext(&t1->context, &t2->context); } -static int thread_yield() +static void thread_dispose(struct thread *t) { - struct thread *old, *next; + DEBUG("completed thread %d\n", thread_current()->id); + t->state = THREAD_COMPLETED; + stack_free(t->stack); +} - DBG(); - if (current) { - old = current; - schedule_add_thread(old); - } else { - old = main_thread; +/* + * Return 1 if found next thread, 0 otherwise + */ +static int thread_system_next(void) +{ + struct thread *curr, *next; + + curr = thread_current(); + if (curr) { + if (curr->state == THREAD_READY) + model->scheduler->add_thread(curr); + else if (curr->state == THREAD_RUNNING) + /* Stopped while running; i.e., completed */ + thread_dispose(curr); + else + DEBUG("ERROR: current thread in unexpected state??\n"); } - schedule_choose_next(&next); - current = next; - return thread_swap(old, next); + next = model->scheduler->next_thread(); + if (next) + next->state = THREAD_RUNNING; + DEBUG("(%d, %d)\n", curr ? curr->id : -1, next ? next->id : -1); + if (!next) + return 1; + return thread_swap(model->system_thread, next); } -static int master_thread_yield() +static void thread_wait_finish(void) { - struct thread *next; DBG(); - if (current) { - DEBUG("completed thread %d\n", current->index); - current->completed = 1; - } - schedule_choose_next(&next); - if (next && !next->completed) { - current = next; - return thread_swap(main_thread, next); - } - return 1; + while (!thread_system_next()); } -int thread_create(struct thread *t, void (*start_routine), void *arg) +/* + * User program API functions + */ +int thread_create(struct thread *t, void (*start_routine)(), void *arg) { - static int created = 1; int ret = 0; DBG(); memset(t, 0, sizeof(*t)); - t->index = created++; - DEBUG("create thread %d\n", t->index); + model->assign_id(t); + DEBUG("create thread %d\n", t->id); t->start_routine = start_routine; t->arg = arg; @@ -102,52 +118,53 @@ int thread_create(struct thread *t, void (*start_routine), void *arg) if (ret) return ret; - schedule_add_thread(t); + t->state = THREAD_CREATED; + + model->scheduler->add_thread(t); return 0; } void thread_join(struct thread *t) { - while (!t->completed) + while (t->state != THREAD_COMPLETED) thread_yield(); } -void a(int *idx) +int thread_yield(void) { - int i; + struct thread *old, *next; - for (i = 0; i < 10; i++) { - printf("Thread %d, loop %d\n", *idx, i); - if (i % 2) - thread_yield(); - } + DBG(); + old = thread_current(); + old->state = THREAD_READY; + next = model->system_thread; + return thread_swap(old, next); } -void user_main() +struct thread *thread_current(void) { - struct thread t1, t2; - int i = 2, j = 3; - - printf("%s() creating 2 threads\n", __func__); - thread_create(&t1, &a, &i); - thread_create(&t2, &a, &j); - - thread_join(&t1); - thread_join(&t2); - printf("%s() is finished\n", __func__); + return model->scheduler->get_current_thread(); } +/* + * Main system function + */ int main() { struct thread user_thread; + struct thread *main_thread; + + model = new ModelChecker(); - main_thread = malloc(sizeof(struct thread)); + main_thread = (struct thread *)malloc(sizeof(*main_thread)); create_initial_thread(main_thread); + model->add_system_thread(main_thread); + /* Start user program */ thread_create(&user_thread, &user_main, NULL); /* Wait for all threads to complete */ - while (master_thread_yield() == 0); + thread_wait_finish(); DEBUG("Exiting\n"); return 0;