I am trying to implement a user=level thread library using the setcontext/getcontext/ect... library of system calls. For the life of me I cannot figure out why I am getting a segfault when I try to swap contexts in my waitall and yield functions below. I have tried debugging with print statement, valgrind, and gdb extensively but I still haven't managed to make sense of it yet. Thanks!
static struct node* ready;
static ucontext_t main;
void ta_libinit(void) {
ready = malloc(sizeof(struct node));
getcontext(&main);
ready -> thread = main;
ready -> isMain = 0;
ready -> next = NULL;
return;
}
void ta_create(void (*func)(void *), void *arg) {
ucontext_t thread; // fix ptrs
unsigned char *stack = (unsigned char *)malloc(STACKSIZE);
assert(stack);
/* Set up thread*/
getcontext(&thread);
thread.uc_stack.ss_sp = stack;
thread.uc_stack.ss_size = STACKSIZE;
thread.uc_link = &main;
makecontext(&thread, (void (*)(void))func, 1, arg);
fifo_append(thread, &ready);
return;
}
void ta_yield(void) {
// Switches to the next thread on the ready queue, pushing the current
// thread to the back.
struct node* current = fifo_pop(&ready);
fifo_push(current, ready);
swapcontext(&(current -> thread), &(ready -> thread));
return;
}
int ta_waitall(void) {
// Only called from calling program - wait for all threads to finish.
while (ready -> next != NULL) {
struct node *current = fifo_pop(&ready);
swapcontext(¤t -> thread, &ready -> thread);
// Took this out for testing purposes.
//free((¤t -> thread.uc_stack));
//free(current);
}
return -1;
}