Ejemplo n.º 1
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);
}
Ejemplo n.º 2
0
void test_enqueue() {
    multilevel_queue_t q;
    int x1 = 5;
    int x2 = 6;
    int x3 = 7;
    void *value = NULL;
    // Testing null queue
    assert(multilevel_queue_enqueue(NULL, 0, &x1) == -1);
    // Testing queue
    q = multilevel_queue_new(4);
    assert(multilevel_queue_enqueue(q, 6, &x2) == -1);

    assert(multilevel_queue_enqueue(q, 2, &x1) == 0);
    assert(multilevel_queue_length(q) == 1);
    assert(multilevel_queue_enqueue(q, 1, &x2) == 0);
    assert(multilevel_queue_length(q) == 2);
    assert(multilevel_queue_enqueue(q, 3, &x3) == 0);
    assert(multilevel_queue_length(q) == 3);
    assert(multilevel_queue_dequeue(q, 2, (&value)) == 2);
    assert(*((int*) value) == x1);
    assert(multilevel_queue_dequeue(q, 3, (&value)) == 3);
    assert(*((int*) value) == x3);
    assert(multilevel_queue_dequeue(q, 1, (&value)) == 1);
    assert(*((int*) value) == x2);
    assert(multilevel_queue_length(q) == 0);
    assert(multilevel_queue_free(q) == 0);
}
Ejemplo n.º 3
0
minithread_t minithread_get_from_ready_queue(int disable_interrupts)
{
	// ISO C90...
	minithread_t tcb;
	interrupt_level_t prev_level;
	int ret;

	// Disable interrupts as we're going to access the ready queue / ready_threads
	if (disable_interrupts == 1)
	{
		prev_level = set_interrupt_level(DISABLED);
	}

	// If there are threads, get the next one
	ret = multilevel_queue_dequeue(ready_queue, current_level, (void**) &tcb);

	// If there was an error, ensure the tcb we return is NULL
	if (ret == -1)
	{
		tcb = NULL;
	}
	 else
	{
		// Otherwise tcb stays as the new thread; decrement ready_threads
		ready_threads--;
	}

	// Restore the interrupt level
	if (disable_interrupts == 1)
		set_interrupt_level(prev_level);

	return tcb;
}
Ejemplo n.º 4
0
int scheduler() {
  int next_priority = 0;
  minithread_t next = NULL;
  minithread_t temp = NULL;
   
  while (1) {
    while (runnable_count == 0) {
      set_interrupt_level(ENABLED);
    };
    
    set_interrupt_level(DISABLED);
    //dequeue from runnable threads
    next_priority = choose_priority_level();
    if (multilevel_queue_dequeue(runnable_q,
        next_priority,(void**)(&next)) != -1) {
      runnable_count--;
      temp = current_thread;
      current_thread = next;
      minithread_switch(&(temp->stacktop),&(next->stacktop));
      return 0;
    }
    //if dead/runnable queue is empty, do nothing (idle thread)
  }
  return 0;
}
Ejemplo n.º 5
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);
  }
}
Ejemplo n.º 6
0
// 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");

}
/*
 * 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;
}
Ejemplo n.º 8
0
/*
 * Initialization.
 * Initializes reaper and idle threads, starts and initializes main thread.
 * Also creates the scheduler and other data 
 *
 */
void minithread_system_initialize(proc_t mainproc, arg_t mainarg) {
  //allocate room for schedule data (global)
  schedule_data = (scheduler *) malloc(sizeof(scheduler));
  if (schedule_data == NULL) {
    exit(1); //OOM
  }
  schedule_data->cleanup_queue = queue_new();
  schedule_data->multi_run_queue = multilevel_queue_new(num_levels);

  reaper_sema = semaphore_create();
  semaphore_initialize(reaper_sema, 0);

  // create main thread
  minithread_t* main_thread = minithread_fork(mainproc, mainarg);

  // initialize idle thread
  idle_thread = (minithread_t *) malloc(sizeof(minithread_t));
  idle_thread->stacktop = NULL;
  idle_thread->thread_id = -1;

  //initialize alarm bookeeping data structure (priority queue)
  alarm_init();

  //remove from run queue and run it
  schedule_data->running_thread = main_thread;
  main_thread->status = RUNNING;
  multilevel_queue_dequeue(schedule_data->multi_run_queue, 0, (void *) main_thread);

  //reaper thread init
  reaper_thread = minithread_create(reaper_queue_cleanup, NULL);
  minithread_start(reaper_thread);

  //Start clock
  minithread_clock_init(clock_period, clock_handler);

  //Initialize network
  network_initialize(network_handler);

  //START MAIN PROC
  //minithread_switch also enables clock interrupts
  minithread_switch(&idle_thread->stacktop, &main_thread->stacktop);
  //always comes back here to idle in the kernel level (allows freeing resources)
  while (1) {
    minithread_t* next = next_runnable();

    set_interrupt_level(DISABLED);
    next->status = RUNNING;
    schedule_data->running_thread = next;
    minithread_switch(&idle_thread->stacktop, &next->stacktop);
  }
}
Ejemplo n.º 9
0
/* get the next RUNNABLE minithread from the run_queue. Waits otherwise. */
minithread_t* next_runnable() {
  void* temp;
  int count = 0;
  while(1) {
    if (multilevel_queue_size(schedule_data->multi_run_queue, (queue_level + count) % 4) > 0) {
      interrupt_level_t old_level = set_interrupt_level(DISABLED); 
      int response = multilevel_queue_dequeue(schedule_data->multi_run_queue, (queue_level + count) % 4, &temp);
      set_interrupt_level(old_level); 
      if (response == 0) {
        return temp;
      }
    }
    else {
      count = (count + 1) % 4;  //looks into the next queue
    }
  }
}
/*
 * Scheduler
 */
int minithread_schedule() {
	minithread_t old = current;
	if ( alarm_has_ready() && old != idle ) {
		current = idle;
	} else if(multilevel_queue_length(ready_queue)>0) {
		minithread_age(ready_queue);
		multilevel_queue_dequeue(ready_queue, PRIORITY_SHORT, &current);
	} else {
		current = idle;
	}

	if ( current->priority == PRIORITY_SHORT ) {
		current_quanta_end = ticks + SHORT_QUANTA;
	} else {
		current_quanta_end = ticks + LONG_QUANTA;
	}
	minithread_switch(&(old->sp), &(current->sp));
	return 0;
}
Ejemplo n.º 11
0
// 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");
}