void init_proxy() { steque_init(&fldes_queue); // create segment for (int i = 0; i < segments; i++) { char str_id[16] = ""; sprintf(str_id, "%d", i); segment_id = (char*) malloc((strlen(str_id) + strlen(SHAREDMPATH) + 1) * sizeof(char)); bzero(segment_id, (strlen(str_id) + strlen(SHAREDMPATH) + 1) * sizeof(char)); strcpy(segment_id, SHAREDMPATH); strcat(segment_id, str_id); shm_unlink(segment_id); fprintf(stdout, "Created Segment ID: %s\n", segment_id); fflush(stdout); steque_enqueue(&fldes_queue, segment_id); } fldes_queue_size = steque_size(&fldes_queue); max_fldes_queue_size = steque_size(&fldes_queue); // fprintf(stdout, "init queue done.\n"); }
/* The gtthread_exit() function is analogous to pthread_exit. */ void gtthread_exit(void* retval) { sigprocmask(SIG_BLOCK, &vtalrm, NULL); gtthread_t *thread = steque_front(&g_threads_steque); thread->is_finished = 1; if(retval != NULL) thread->retval = retval; /* If this was the last thread in the queue, clean up and exit */ if(steque_size(&g_threads_steque) == 1) { gtthread_t *dead_thread; int num = steque_size(&g_dead_threads_steque); while(num > 0) { dead_thread = steque_front(&g_dead_threads_steque); if(dead_thread->context && dead_thread->context->uc_stack.ss_sp) free(dead_thread->context->uc_stack.ss_sp); if(dead_thread->context) free(dead_thread->context); if(dead_thread->id == 0) free(dead_thread); if(steque_size(&g_dead_threads_steque) > 1) steque_cycle(&g_dead_threads_steque); num--; } if(thread->context) free(thread->context); // Main thread was the only one that was dynamically allocated. if(thread->id == 0) free(thread); steque_destroy(&g_threads_steque); steque_destroy(&g_dead_threads_steque); steque_destroy(&g_cancelatorium); steque_destroy(&g_join_steque); /* So apparently we can't free the stack of the thread that is running. */ // if(thread->context && thread->context->uc_stack.ss_sp) // free(thread->context->uc_stack.ss_sp); exit(0); } sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); alarm_safe_yield(); }
gtthread_blk_t *get_thread(gtthread_t tID){ int queue_len, i; gtthread_blk_t *tmp, *ret; int match = 0; DEBUG_MSG("get_thread, tID: %ld\n", tID); queue_len = steque_size(&thread_queue); for(i = 0; i < queue_len; i++){ tmp = (gtthread_blk_t *)steque_pop(&thread_queue); steque_enqueue(&thread_queue, tmp); if(tmp->tID == tID){ ret = tmp; match = 1; } } if(!match) DEBUG_MSG("No Match!\n"); return ret; }
/** * Cycles through the join_steque to update the waiting status of any threads that may * be waiting on a thread to join. */ static void joininator(gtthread_t *joinee) { int i; for(i=0; i<steque_size(&g_join_steque); i++) { gtthread_t *curr = steque_front(&g_join_steque); if(curr->wait_tid == joinee->id) { curr->is_joined = 1; curr->joinee = joinee; } steque_cycle(&g_join_steque); } }
/* Find a thread by its id */ static gtthread_int_t * find_thread(gtthread_t thread) { int queue_len; int i; gtthread_int_t *item; queue_len = steque_size(&threads); for (i = 0; i < queue_len; i++) { item = (gtthread_int_t *) steque_pop(&threads); steque_enqueue(&threads, item); if (item->id == thread) { return item; } } return NULL; }
void print_run_queue(void) { int queue_len; int i; gtthread_int_t *item; queue_len = steque_size(&run_queue); for (i = 0; i < queue_len; i++) { item = (gtthread_int_t *) steque_pop(&run_queue); steque_enqueue(&run_queue, item); printf("%d->", (int) item->id); fflush(stdout); } printf("\n"); fflush(stdout); }
void list_thread(){ int queue_len, i; gtthread_blk_t *tmp; DEBUG_MSG("----------------------------------------------\n"); queue_len = steque_size(&thread_queue); for(i = 0; i < queue_len; i++){ tmp = (gtthread_blk_t *)steque_pop(&thread_queue); DEBUG_MSG("tmp->tID: %ld, state: %d, context: %x\n", tmp->tID, tmp->state, &tmp->uctx); steque_enqueue(&thread_queue, tmp); } DEBUG_MSG("----------------------------------------------\n"); }
/* to find thread with threadId in the globalQ */ gtthread* getThread(gtthread_t threadId) { int size = steque_size(&globalQ); int i = 0; gtthread *temp, *returnThread; returnThread = NULL; /* Get front of queue in temp, compare id Do this till you find a match, save it in returnThread and continue loop to restore original order */ while(i < size) { temp = (gtthread *) steque_front(&globalQ); if(temp -> id == threadId) { returnThread = temp; } steque_cycle(&globalQ); i++; } return returnThread; }
/** * Helper function for yield. */ static void yield_helper(int is_alarm_safe) { if(is_alarm_safe) sigprocmask(SIG_BLOCK, &vtalrm, NULL); // Don't need to do anything if there's just one thread in the queue. if(steque_size(&g_threads_steque) == 1) return; gtthread_t *old_thread = steque_pop(&g_threads_steque); gtthread_t *new_thread = NULL; /* Find an eligible new thread - i.e., a thread that isn't queued for cancelation. */ if(!is_alarm_safe) sigprocmask(SIG_BLOCK, &vtalrm, NULL); while(steque_size(&g_threads_steque) > 0) { new_thread = steque_front(&g_threads_steque); /* Cancels threads when it's their turn to run */ int i; int canceled=0; for(i=0; i < steque_size(&g_cancelatorium); i++) { if((long) steque_front(&g_cancelatorium) == new_thread->id) { new_thread->is_finished = 1; new_thread->retval = (void *) -1; steque_pop(&g_cancelatorium); steque_pop(&g_threads_steque); steque_enqueue(&g_dead_threads_steque, new_thread); canceled=1; joininator(new_thread); // Attempt to join the thread you just canceled. break; } if(steque_size(&g_cancelatorium) > 0) steque_cycle(&g_cancelatorium); } if(!canceled) break; } /* If the thread that yielded finsihed executing, put it in the finished steque. */ if(old_thread->is_finished) { steque_enqueue(&g_dead_threads_steque, old_thread); joininator(old_thread); } else { steque_enqueue(&g_threads_steque, old_thread); } if(!is_alarm_safe) sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); // All threads have finished running. Is this necessary? if(steque_size(&g_threads_steque) == 0) exit(0); // Don't context switch if the original thread is the only one left in the queue. if(gtthread_equal(*((gtthread_t *) steque_front(&g_threads_steque)), *old_thread)) return; if(is_alarm_safe) { T.it_value.tv_usec = global_period; // Reset timer so that the next period can start immediately. sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); } swapcontext(old_thread->context, new_thread->context); }
/* The gtthread_join() function is analogous to pthread_join. All gtthreads are joinable. */ int gtthread_join(gtthread_t thread, void **status) { sigprocmask(SIG_BLOCK, &vtalrm, NULL); gtthread_t *self = steque_front(&g_threads_steque); sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); /* The range [0, g_thread_id) indicates the range of thread ids that have ever belonged to valid threads. Also can't join with self. */ if(thread.id >= g_thread_id || thread.id == self->id) return 1; sigprocmask(SIG_BLOCK, &vtalrm, NULL); self->is_joined = 0; self->wait_tid = thread.id; sigprocmask(SIG_BLOCK, &vtalrm, NULL); int found_among_dead = 0; /* First look for joinee among threads that have already terminated. */ int i; for(i=0; i<steque_size(&g_dead_threads_steque); i++) { sigprocmask(SIG_BLOCK, &vtalrm, NULL); gtthread_t *curr = steque_front(&g_dead_threads_steque); sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); if(curr->id == self->wait_tid) { found_among_dead = 1; sigprocmask(SIG_BLOCK, &vtalrm, NULL); self->joinee = curr; self->is_joined = 1; sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); break; } sigprocmask(SIG_BLOCK, &vtalrm, NULL); steque_cycle(&g_dead_threads_steque); sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); } /* If we haven't found it, wait until it terminates. */ if(!found_among_dead) { // First check to see that the thread I am waiting on is not already waiting on me. for(i=0; i<steque_size(&g_join_steque); i++) { sigprocmask(SIG_BLOCK, &vtalrm, NULL); gtthread_t *curr = steque_front(&g_join_steque); sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); if(curr->wait_tid == self->id && curr->id == self->wait_tid) { sigprocmask(SIG_BLOCK, &vtalrm, NULL); self->is_joined = -1; self->wait_tid = -1L; sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); return 1; } sigprocmask(SIG_BLOCK, &vtalrm, NULL); steque_cycle(&g_join_steque); sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); } // If joinee isn't already waiting on me, enqueue myself in the join queue... sigprocmask(SIG_BLOCK, &vtalrm, NULL); steque_enqueue(&g_join_steque, self); sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); // ... and wait until joinee terminates. while(!self->is_joined) alarm_safe_yield(); } if(status) *status = self->joinee->retval; sigprocmask(SIG_BLOCK, &vtalrm, NULL); self->joinee = NULL; self->wait_tid = -1L; self->is_joined = -1; sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); /* Remove yourself from the join steque, if you put yourself there. */ if(!found_among_dead) { for(i=0; i<steque_size(&g_join_steque); i++) { sigprocmask(SIG_BLOCK, &vtalrm, NULL); gtthread_t *curr = steque_front(&g_join_steque); sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); if(gtthread_equal(*self, *curr)) { steque_pop(&g_join_steque); break; } if(steque_size(&g_join_steque) > 0) { sigprocmask(SIG_BLOCK, &vtalrm, NULL); steque_cycle(&g_join_steque); sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); } } } return 0; }