Example #1
0
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);
}
Example #2
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);
}
Example #3
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;
}
Example #4
0
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;
}
Example #6
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");

}
Example #8
0
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
  }
}
Example #9
0
/**
 * 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();
}
Example #10
0
/*
 * 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);
  } 
}
Example #11
0
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;
}
Example #13
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);
}
Example #14
0
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;
}
Example #15
0
/*
 * 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);
}
Example #16
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);
}
Example #17
0
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();
}
Example #18
0
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();
}
Example #19
0
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;
}