void test_dequeue() { multilevel_queue_t q; void *value; int x1 = 5; int x2 = 6; int x3 = 7; // Testing null queue assert(multilevel_queue_dequeue(NULL, 0, &value) == -1); assert(value == NULL); // Testing empty queue q = multilevel_queue_new(2); assert(multilevel_queue_dequeue(q, 3, &value) == -1); assert(value == NULL); // Testing queue assert(multilevel_queue_enqueue(q, 0, &x2) == 0); assert(multilevel_queue_enqueue(q, 1, &x3) == 0); assert(multilevel_queue_enqueue(q, 0, &x1) == 0); assert(multilevel_queue_dequeue(q, 2, (&value)) == -1); assert(multilevel_queue_dequeue(q, 0, (&value)) == 0); assert(*((int*) value) == x2); assert(multilevel_queue_length(q) == 2); assert(multilevel_queue_dequeue(q, 1, (&value)) == 1); assert(*((int*) value) == x3); assert(multilevel_queue_length(q) == 1); assert(multilevel_queue_dequeue(q, 1, &value) == 0); assert(*((int*) value) == x1); assert(multilevel_queue_length(q) == 0); assert(multilevel_queue_dequeue(q, 0, &value) == -1); assert(multilevel_queue_free(q) == 0); }
void test_length() { multilevel_queue_t q1; void *p; int i1 = 0; int i2 = 0; // Test null queue assert(multilevel_queue_length(NULL) == -1); // Test queues q1 = multilevel_queue_new(2); assert(multilevel_queue_length(q1) == 0); assert(multilevel_queue_enqueue(q1, 1, &i1) == 0); assert(multilevel_queue_length(q1) == 1); assert(multilevel_queue_enqueue(q1, 1, &i2) == 0); assert(multilevel_queue_length(q1) == 2); assert(multilevel_queue_enqueue(q1, 0, &i1) == 0); assert(multilevel_queue_length(q1) == 3); assert(multilevel_queue_enqueue(q1, 0, &i2) == 0); assert(multilevel_queue_length(q1) == 4); assert(multilevel_queue_dequeue(q1, 0, &p) == 0); assert(multilevel_queue_length(q1) == 3); assert(multilevel_queue_dequeue(q1, 0, &p) == 0); assert(multilevel_queue_length(q1) == 2); assert(multilevel_queue_dequeue(q1, 1, &p) == 1); assert(multilevel_queue_dequeue(q1, 1, &p) == 1); assert(multilevel_queue_length(q1) == 0); assert(multilevel_queue_free(q1) == 0); }
/* * Initialization. * * minithread_system_initialize: * This procedure should be called from your C main procedure * to turn a single threaded UNIX process into a multithreaded * program. * * Initialize any private data structures. * Create the idle thread. * Fork the thread which should call mainproc(mainarg) * Start scheduling. * * Note that the runnable_q is protected by disabling interrupts. * All other data structures are protected with binary semaphores. * */ void minithread_system_initialize(proc_t mainproc, arg_t mainarg) { minithread_t clean_up_thread = NULL; minithread_t process_packets_thread = NULL; int a = 0; void* dummy_ptr = NULL; dummy_ptr = (void*)&a; current_id = 0; // the next thread id to be assigned id_lock = semaphore_create(); semaphore_initialize(id_lock,1); runnable_q = multilevel_queue_new(4); blocked_q = queue_new(); blocked_q_lock = semaphore_create(); semaphore_initialize(blocked_q_lock,1); dead_q = queue_new(); dead_q_lock = semaphore_create(); semaphore_initialize(dead_q_lock,1); dead_sem = semaphore_create(); semaphore_initialize(dead_sem,0); clean_up_thread = minithread_create(clean_up, NULL); multilevel_queue_enqueue(runnable_q, clean_up_thread->priority,clean_up_thread); runnable_count++; minimsg_initialize(); process_packets_thread = minithread_create(process_packets, NULL); multilevel_queue_enqueue(runnable_q, process_packets_thread->priority,process_packets_thread); runnable_count++; minithread_clock_init(TIME_QUANTA, (interrupt_handler_t)clock_handler); network_initialize((network_handler_t) network_handler); init_alarm(); current_thread = minithread_create(mainproc, mainarg); minithread_switch(&dummy_ptr, &(current_thread->stacktop)); return; }
int minithread_add_to_ready_queue(minithread_t tcb, int disable_interrupts) { int ret; interrupt_level_t prev_level; // Turn off interrupts while we access ready_queue & ready_threads if (disable_interrupts == 1) { prev_level = set_interrupt_level(DISABLED); } // Add the thread to the ready queue ret = multilevel_queue_enqueue(ready_queue, tcb->priority, (void*) tcb); // Increment the number of threads on the ready queue if (ret == 0) ready_threads++; // Restore the interrupt level if (disable_interrupts == 1) { set_interrupt_level(prev_level); } return ret; }
int minithread_yield() { current->priority = PRIORITY_SHORT; current->age = ticks; multilevel_queue_enqueue(ready_queue, current->priority, current); minithread_schedule(); return 0; }
static void yield_running_thread() { minithread_t *first_runnable = NULL; minithread_t *temp = running_thread; int res = multilevel_queue_dequeue(runnable_queue, curr_level, (void **)(&first_runnable)); if (running_thread != scheduler_thread) { multilevel_queue_enqueue(runnable_queue, running_thread->level, running_thread); } if (res != -1) { // if the level of dequeued thread is different from current running, update the curr_level // and also the curr_level_quanta is reset to 0, since we are switching to the next level if (curr_level != first_runnable->level) { curr_level = first_runnable->level; curr_level_quanta = 0; } if (running_thread != first_runnable) { running_thread = first_runnable; minithread_switch(&temp->top, &running_thread->top); } } else { running_thread = scheduler_thread; minithread_switch(&temp->top, &running_thread->top); } }
// Store NUM_TOTAL_ELEMENTS in level 0, // dequeue and make sure level is always 0 // and proper elements returned. void test1() { printf("Beginning test 1.\n"); multilevel_queue_t ml_q = multilevel_queue_new(NUM_LEVELS); int i; for (i = 0; i < NUM_TOTAL_ELEMENTS; i++) { int *int_ptr = (int *)malloc(sizeof(int)); *int_ptr = i; multilevel_queue_enqueue(ml_q, 0, int_ptr); } int **int_ptr_ptr = (int **)malloc(sizeof(int *)); int level_found_on; for (i = 0; i < NUM_TOTAL_ELEMENTS; i++) { level_found_on = multilevel_queue_dequeue(ml_q, 0, (void **)int_ptr_ptr); assert(level_found_on == 0); assert(**int_ptr_ptr == i); free(*int_ptr_ptr); } free(int_ptr_ptr); multilevel_queue_free(ml_q); printf("Test 1 passed.\n"); }
void minithread_start(minithread_t *t) { t->status = RUNNABLE; interrupt_level_t old_level = set_interrupt_level(DISABLED); int response = multilevel_queue_enqueue(schedule_data->multi_run_queue, t->level, t); set_interrupt_level(old_level); if (response != 0) { exit(1); //enqueue failed } }
/** * minithread_demote_priority is called from the clock handler. * Interrupts are already disabled when this function is called so mutual exclusion gauranteed. * This threads priority is decreased, its quanta replenished, placed back on runnable queue * and the scheduler is invoked. **/ void minithread_demote_priority() { if (current_thread->priority == LOWEST_PRIORITY); else current_thread->priority++; current_thread->rem_quanta = 1 << current_thread->priority; if (multilevel_queue_enqueue(runnable_q, current_thread->priority,current_thread) == 0) { runnable_count++; } scheduler(); }
/* * Make thread t runnable. */ void minithread_start(minithread_t *t) { t->s = RUNNABLE; if (runnable_queue) { // the runnable queue, being critical section i.e. can be modified // inside interrupt handler as well, therefore, interrupts // are disabled in this section. interrupt_level_t old_level = set_interrupt_level(DISABLED); multilevel_queue_enqueue(runnable_queue, t->level, t); set_interrupt_level(old_level); } }
minithread_t minithread_fork(proc_t proc, arg_t arg) { minithread_t new_thread = minithread_create(proc,arg); semaphore_P(runnable_q_lock); if(multilevel_queue_enqueue(runnable_q, new_thread->priority,new_thread) == 0) { runnable_count++; //add to queue } semaphore_V(runnable_q_lock); return new_thread; }
/* * Thread Age - function that is used to promote threads * of a certain age to the next priority level, which * ensures that lower priority threads still get a chance * to use the CPU even when there are many high priority * threads */ int minithread_age(multilevel_queue_t queue) { minithread_t thread = NULL; multilevel_queue_peak(queue, PRIORITY_LONG, (any_t*)&thread); while( thread && ((ticks - thread->age) >= PROMOTE_AGE) ) { multilevel_queue_dequeue(queue, PRIORITY_LONG, (any_t*)&thread); // reset priority but age stays the same thread->priority = PRIORITY_SHORT; multilevel_queue_enqueue(queue, PRIORITY_SHORT, thread); multilevel_queue_peak(queue, PRIORITY_LONG, (any_t*)&thread); } return 0; }
void minithread_start(minithread_t t) { t->status = RUNNABLE; t->priority = 0; t->rem_quanta = 1; semaphore_P(runnable_q_lock); if (multilevel_queue_enqueue(runnable_q, t->priority,t) == 0) { runnable_count++; } semaphore_V(runnable_q_lock); }
minithread_t minithread_fork(proc_t proc, arg_t arg) { interrupt_level_t l; minithread_t new_thread = minithread_create(proc,arg); l = set_interrupt_level(DISABLED); if(multilevel_queue_enqueue(runnable_q, new_thread->priority,new_thread) == 0) { runnable_count++; //add to queue } set_interrupt_level(l); return new_thread; }
/* * This is tested via valgrind */ void test_free() { multilevel_queue_t q1, q2, q3; int i; int i1 = 0; int i2 = 0; // Test null queue assert(multilevel_queue_free(NULL) == -1); // Test empty queue q1 = multilevel_queue_new(2); assert(multilevel_queue_free(q1) == 0); // Test queue with elements q2 = multilevel_queue_new(2); assert(multilevel_queue_enqueue(q2, 0, &i1) == 0); assert(multilevel_queue_enqueue(q2, 1, &i2) == 0); assert(multilevel_queue_free(q2) == 0); // Stress test for leaks q3 = multilevel_queue_new(2); for (i = 0; i < 10; i++) { assert(multilevel_queue_enqueue(q3, 0, &i1) == 0); assert(multilevel_queue_enqueue(q3, 1, &i2) == 0); } assert(multilevel_queue_free(q3) == 0); }
void minithread_start(minithread_t t) { interrupt_level_t l; t->status = RUNNABLE; t->priority = 0; t->rem_quanta = 1; l = set_interrupt_level(DISABLED); if (multilevel_queue_enqueue(runnable_q, t->priority,t) == 0) { runnable_count++; } set_interrupt_level(l); }
void minithread_yield() { //put current thread at end of runnable semaphore_P(runnable_q_lock); current_thread->priority = 0; current_thread->rem_quanta = 1; if (multilevel_queue_enqueue(runnable_q, current_thread->priority,current_thread) == 0) { runnable_count++; } semaphore_V(runnable_q_lock); //call scheduler here scheduler(); }
void minithread_yield() { interrupt_level_t l; //put current thread at end of runnable current_thread->priority = 0; current_thread->rem_quanta = 1; l = set_interrupt_level(DISABLED); if (multilevel_queue_enqueue(runnable_q, current_thread->priority,current_thread) == 0) { runnable_count++; } set_interrupt_level(l); //call scheduler here scheduler(); }
void minithread_yield() { interrupt_level_t old_level = set_interrupt_level(DISABLED); if (multilevel_queue_total_elements(schedule_data->multi_run_queue) == 0) { set_interrupt_level(old_level); return; } minithread_t* old = schedule_data->running_thread; old->status = RUNNABLE; //adds itself to the end of the run queue multilevel_queue_enqueue(schedule_data->multi_run_queue, old->level, old); //yields to the next minithread in the run_queue minithread_t* next = next_runnable(); next->status = RUNNING; schedule_data->running_thread = next; minithread_switch(&old->stacktop, &next->stacktop); }
// Store NUM_TOTAL_ELEMENTS evenly dispersed // across levels 0-4. Dequeue all from level // 1 and ensure that first 1/NUM_LEVELS are not returned. void test3() { printf("Beginning test 3.\n"); multilevel_queue_t ml_q = multilevel_queue_new(NUM_LEVELS); int i; int j; int level_fraction = NUM_TOTAL_ELEMENTS / NUM_LEVELS; for (i = 1; i <= NUM_LEVELS; i++) { for (j = i * level_fraction; j < (i+1) * level_fraction; j++) { int *int_ptr = (int *)malloc(sizeof(int)); *int_ptr = j; multilevel_queue_enqueue(ml_q, i, int_ptr); } } int **int_ptr_ptr = (int **)malloc(sizeof(int *)); int level_found_on; for (i = 0; i<= NUM_LEVELS; i++) { for (j = i * level_fraction; j < (i-1) * level_fraction; j++) { level_found_on = multilevel_queue_dequeue(ml_q, 1, (void **)int_ptr_ptr); if (j > level_fraction * (NUM_LEVELS - 1)/NUM_LEVELS) { assert(level_found_on == -1); } else { assert(level_found_on == i+1); assert(**int_ptr_ptr == j + level_fraction); free(*int_ptr_ptr); } } } free(int_ptr_ptr); multilevel_queue_free(ml_q); printf("Test 3 passed.\n"); }
//Place the argument thread on the ready queue int minithread_start(minithread_t t) { queue_delete(stop_queue, t); t->age = ticks; multilevel_queue_enqueue(ready_queue, current->priority, t); return 0; }