Exemplo n.º 1
0
int kframe_alloc(int *frame, int frames_wanted)
{

	int rv, id;
	static int id_cur = 0;

	// only acquire lock and initialize idgen AFTER booting -- due to kmalloc
	if (booting){
		id = id_cur++;
	} else {
		lock_acquire(coremap_lock);
			if (!q_empty(id_not_used)){
				id = (int) q_remhead(id_not_used);
			} else {
				id = id_cur++;
			}
	}
			rv = frame_alloc_continuous(frame, KERNEL, 0, id, frames_wanted);
			if (rv && id_not_used != NULL) {
				q_addtail(id_not_used, (void*)id);
			}
	if (!booting) lock_release(coremap_lock);

	return rv;
}
Exemplo n.º 2
0
static
int
q_grow(struct queue *q, int targetsize)
{
	void **olddata = q->data;
	int onr = q->nextread;
	int onw = q->nextwrite;
	int osize = q->size;

	int nsize;
	void **ndata;

	int i, result;

	nsize = q->size;
	while (nsize < targetsize) {
		nsize *= 2;
		/* prevent infinite loop */
		KASSERT(nsize > 0);
	}
	ndata = kmalloc(nsize * sizeof(void *));
	if (ndata == NULL) {
		return ENOMEM;
	}
	q->size = nsize;
	q->data = ndata;
	q->nextread = q->nextwrite = 0;
	
	for (i=onr; i!=onw; i = (i+1)%osize) {
		result = q_addtail(q, olddata[i]);
		KASSERT(result==0);
	}
	kfree(olddata);
	return 0;
}
Exemplo n.º 3
0
void
cv_wait(struct cv *cv, struct lock *lock)
{
	int spl;
		
	//We must complete an unconditional wait once an unlock occurs and we can then take the lock. We will check the conditions now.
	assert(cv != NULL);
	assert(lock !=NULL);
	assert (lock_do_i_hold(lock));
	
	//If these steps above are valid we can now release the lock, sleep and then lock again.
	//This must be done atomically.
	
	//Like locks and semaphores, we want to make sure before we disable interrupts that we are not currently in the interrupt handler.
	assert(in_interrupt == 0);
	
	spl = splhigh(); //Disable All Interrupts
	
	lock_release(lock); //Unlock
	
	cv->count++; //Add one to the count since we have one more thread waiting now.
	
	q_preallocate(cv->thread_queue,cv->count); // not sure about this.
	
	q_addtail(cv->thread_queue, curthread); //add the currently waiting thread in the queue;
	
	thread_sleep(curthread); // now that the thread is in the queue, it can sleep.
	
	lock_acquire(lock); //When awoken, reacquire the lock if available. If not available, the thread will go back to bed inside lock_acquire();

	splx(spl); //Re-enable interrupts
	
	(void)cv;    // suppress warning until code gets written
	(void)lock;  // suppress warning until code gets written
}
Exemplo n.º 4
0
void frame_free(int frame)
{
	KASSERT(frame >= 0 && frame < num_frames);

	lock_acquire(coremap_lock);
		int pid = coremap_ptr[frame].pid;
		int id = coremap_ptr[frame].id;

		if (pid != 0) {
			KASSERT(curproc->pid == pid);
			set_frame(frame, UNALLOCATED, 0,0);
			ZERO_OUT_FRAME(frame);
			goto FRAME_FREE_DONE;
		}
		for (int i = 0; i < num_frames; i++){
			if (coremap_ptr[i].pid != 0 || coremap_ptr[i].id != id) continue;
			set_frame(i, UNALLOCATED, 0,0);
			ZERO_OUT_FRAME(i);
			if (id_not_used != NULL){ // recycle id's for kernel memory
				q_addtail(id_not_used, (void*)id);
			}
			goto FRAME_FREE_DONE;
		}

		panic("Invalid freeing of the frame for the unique pair (pid,id)=(%d,%d)\n", pid, id);
FRAME_FREE_DONE:
	lock_release(coremap_lock);
}
Exemplo n.º 5
0
static
void
testq(struct queue *q, int n)
{
	int i, result, *x, *r;

	x = kmalloc(n * sizeof(int));
	for (i=0; i<n; i++) {
		x[i] = i;
	}

	assert(q_empty(q));

	for (i=0; i<n; i++) {
		kprintf("queue: adding %d\n", i);
		result = q_addtail(q, &x[i]);
		assert(result==0);
	}

	for (i=0; i<n; i++) {
		r = q_remhead(q);
		assert(r != NULL);
		kprintf("queue: got %d, should be %d\n", *r, i);
		assert(*r == i);
	}

	assert(q_empty(q));

	kfree(x);
}
Exemplo n.º 6
0
Arquivo: synch.c Projeto: jessZhAnG/OS
void
cv_wait(struct cv *cv, struct lock *lock)
{
#if OPT_A1
    // validate parameter
    assert (cv != NULL);
    assert (lock != NULL);
    // disable interrupts
    int spl = splhigh();

    // release the lock
    assert (lock->status == 1);

    lock_release(lock);
    assert (lock->status == 0);

    q_addtail(cv->sleeping_list,curthread);
    // sleep
    thread_sleep(curthread);



    lock_acquire(lock);
    // enable interrupts
    splx(spl);

#else
    (void) cv;
    (void) lock;
#endif
}
Exemplo n.º 7
0
/* 
 * Make a thread runnable.
 * With the base scheduler, just add it to the end of the run queue.
 */
int
make_runnable(struct thread *t)
{
	// meant to be called with interrupts off
	assert(curspl>0);

	return q_addtail(runqueue, t);
}
Exemplo n.º 8
0
int
make_runnable(struct thread *t)
{
	// meant to be called with interrupts off
	assert(curspl>0);

	// Use the priority of t to determine which queue to add it to.
	return(q_addtail(runqueue[t->priority], t));
}
Exemplo n.º 9
0
/*
 * Actual scheduler. Returns the next thread to run.  Calls cpu_idle()
 * if there's nothing ready. (Note: cpu_idle must be called in a loop
 * until something's ready - it doesn't know whether the things that
 * wake it up are going to make a thread runnable or not.) 
 */
struct thread *
scheduler(void)
{
	// meant to be called with interrupts off
	assert(curspl>0);
	
	while (q_empty(runqueue)) {
		cpu_idle();
	}

	// You can actually uncomment this to see what the scheduler's
	// doing - even this deep inside thread code, the console
	// still works. However, the amount of text printed is
	// prohibitive.
	// 
	//print_run_queue();
	
	/* We will have a defined variable in scheduler.h that will control
		the type of scheduling */
	
	if(scheduler_type == SCHEDULER_RANDOM)
	{
						
		/* Random queue method */
		// We could manipulate q->next_read, an integer that indexes the next in line
		// i.e. pick an index based on the size of the queue (q->size), and change
		// runqueue->next_read to that index

		// We might also be able to just jump in and get a random index from the queue
				
		// queue size is 32 by default
		int queue_size = q_getsize(runqueue);
		int random_index;

		struct thread * temp_thread;

		// We will have to get the thread number from within the active part
		// of the queue
		int start = q_getstart(runqueue);
		int end = q_getend(runqueue);
		
		
		int random_range = (end - start);
		
		// We have a problem if the start and end are the same
		assert(random_range != 0);

		// The startup code seems to have issues if you pick it right off the bat
		

		if (random_range < 0)
			random_range = random_range + queue_size;
		
		// No need to pick a random thread if there is only 1 in the queue
		if (random_range == 1)
			return q_remhead(runqueue);


		DEBUG(DB_THREADS, "Number of active threads: %u.\n", random_range);
		DEBUG(DB_THREADS, "Start: %u.\n", start);
		DEBUG(DB_THREADS, "End: %u.\n", end);
		random_index = (random() % random_range + start) % queue_size;
								
		DEBUG(DB_THREADS, "%u index chosen.\n", random_index);
		
		// Now, we have to move our chosen thread to the front of the line
		// There is probably some other way to do this that is more efficient, but
		// I had no success with q_getguy()

		// We start with the next thread in the queue, and work our way to the chosen one
		while(q_getstart(runqueue) != random_index)
		{
			temp_thread = q_remhead(runqueue);
			q_addtail(runqueue, temp_thread);
		}
		
		DEBUG(DB_THREADS, "New start: %u.\n", q_getstart(runqueue));
		DEBUG(DB_THREADS, "New end: %u.\n", q_getend(runqueue));

		return q_remhead(runqueue);
		
	}
	
	else if (scheduler_type == SCHEDULER_MLFQ)
	{
		/* MLFQ method */
		
		// We will go through all of our queue, looking for the highest priority thread
		// By starting at the next read and working up, on a tie we are taking the first in
		
		
		// queue size is 32 by default
		int queue_size = q_getsize(runqueue);
		int i;
		int chosen_index;
		int priority;
		int random_choice;

		struct thread * temp_thread;

		// We will have to get the thread number from within the active part
		// of the queue
		int start = q_getstart(runqueue);
		int end = q_getend(runqueue);
		
		cycles++;
		
		if (cycles > 2000) {
		// reset priorities 
			//kprintf("Resetting priorities");
			i = start;
			while( i != end)
			{
				temp_thread = q_getguy(runqueue, i);
				DEBUG(DB_THREADS, "Setting priority\n");
				thread_set_priority(temp_thread, 50);
							
				i = (i+1) % queue_size;
			}
			cycles = 0;
			// A bit of randomness to prevent immediate restarving
			return q_remhead(runqueue);
		}


		int highest_priority = -1; // 100 is maximum priority

		i = start;
		
		while( i != end)
		{
			temp_thread = q_getguy(runqueue, i);
			DEBUG(DB_THREADS, "Getting priority\n");
			priority = thread_get_priority(temp_thread);
			DEBUG(DB_THREADS, "Priority: %u.\n", priority);
			if (priority > highest_priority)
			{
				chosen_index = i;
				highest_priority = priority;
			}
			
			// In the event of a tie, random pick
			else if (priority == highest_priority)
			{
				random_choice == random() % 3;
				if (random_choice == 0)
					chosen_index = i;
			}

			i = (i+1) % queue_size;
		}
				
		DEBUG(DB_THREADS, "Start: %u.\n", start);
		DEBUG(DB_THREADS, "End: %u.\n", end);					
		DEBUG(DB_THREADS, "%u index chosen with priority %u.\n", chosen_index, highest_priority);
		//kprintf("%u index chosen with priority %u.\n", chosen_index, highest_priority);
		// Now, we have to move our chosen thread to the front of the line
		// There is probably some other way to do this that is more efficient, but
		// I had no success with q_getguy()

		// We start with the next thread in the queue, and work our way to the chosen one
		while(q_getstart(runqueue) != chosen_index)
		{
			temp_thread = q_remhead(runqueue);
			q_addtail(runqueue, temp_thread);
		}
		
		DEBUG(DB_THREADS, "New start: %u.\n", q_getstart(runqueue));
		DEBUG(DB_THREADS, "New end: %u.\n", q_getend(runqueue));

		return q_remhead(runqueue);
	}
	
	// Fall through to default FIFO scheduler

	return q_remhead(runqueue);
}
Exemplo n.º 10
0
void enter_kitchen(const int creature_type) {
    /*
     * Policy: Let any amount of cats try to access any amount of bowls at once,
     * or let any amount of mice try to access any amount of bowls at once, but
     * never mix.
     *
     * So, if the kitchen is empty, the first creature can enter regardless. If
     * that creature is a mouse, let all subsequent creatures that are mice enter
     * without delay. But, as soon as the next creature is a cat, stop letting
     * all subsequent creatures in, and put them in groups waiting in line.
     * Idea is to wait until all the mice currently in the kitchen are done, then
     * let a "burst" of cats in, then wait until all of them are done, then let a
     * "burst" of mice in, etc.
     *
     * For example, if x's are mice, and y's are cats, say we have this stream of
     * animals (arrived at the kitchen in order from right to left)
     *
     *   Time   |   Outside of Kitchen    |    Inside Kitchen   |  Done eating
     *    t0       yyyxyyyyyxxxxxxyyyyxx
     *    t1       yyyxyyyyyxxxxxxyyyy               xx
     *    t2       yyyxyyyyyxxxxxx                   yyyy               xx
     *    t3       yyyxyyyyy                         xxxxxx         yyyyxx
     *
     *
     * This policy has the objective of being as fair as possible, with efficieny
     * as an important but secondary objective (we let any amount of 1 creature
     * type in at once). Besides, we are multithreading to get a huge efficiency
     * gain in the first place.
     */

    // Want mutual exclusion for group processing
    lock_acquire(k->kitchen_lock);

    // First creature in gets to initially set the current_creature flag and enter
    if (k->current_creature == 2) {
        k->current_creature = creature_type;
    }
    /* 
     * If the queue is not empty, know that there are other groups to go first.
     * Don't barge ahead of another group even if you match the current creature.
     */
    else if (!q_empty(k->group_list)) {
        // Inspect the last group in line
        int index = q_getend(k->group_list) > 0 ? q_getend(k->group_list)-1 : q_getsize(k->group_list) - 1;
        struct kgroup *g = (struct kgroup *)q_getguy(k->group_list, index);

        if (g->type == creature_type) {
            // If the last group is of your type, merge into that group
            g->amount++;
        } else {
            // Otherwise, start a new last group
            g = kmalloc(sizeof(struct kgroup));
            g->type = creature_type;
            g->amount = 1;

            // Enqueue new group
            q_addtail(k->group_list, g);
        }

        // Wait
        cv_wait(k->kitchen_cv, k->kitchen_lock);
    }
    /*
     * If we aren't the first creature, and the queue is empty, check if we match the
     * creature currently in the kitchen. If not, we are going to start the only group
     * in the queue.
     */
    else if (k->current_creature != creature_type) {
        // Create a group struct
        struct kgroup *g = kmalloc(sizeof(struct kgroup));

        // Group is of your type with 1 creature so far
        g->type = creature_type;
        g->amount = 1;

        // Enqueue new group
        q_addtail(k->group_list, g);

        // Wait
        cv_wait(k->kitchen_cv, k->kitchen_lock);
    }

    // If here, we have been granted access to the kitchen

    // Set the creature type currently owning the kitchen
    k->current_creature = creature_type;

    // Increment creature count
    k->creature_count++;

    /*
     * Release kitchen lock before accessing the bowls, because we want any amount
     * of one type of creature to be able to access the bowls at once.
     */
    lock_release(k->kitchen_lock);
}
Exemplo n.º 11
0
void
intersection_before_entry(Direction origin, Direction destination) 
{
  /* replace this default implementation with your own implementation */
  //(void)origin;  /* avoid compiler complaint about unused parameter */
  (void)destination; /* avoid compiler complaint about unused parameter */
  // KASSERT(intersectionSem != NULL);
  // P(intersectionSem);
  KASSERT(intersection_lock != NULL);
  KASSERT(next_lights != NULL);
  KASSERT(cv_south_go != NULL);
  KASSERT(cv_north_go != NULL);
  KASSERT(cv_east_go != NULL);
  KASSERT(cv_west_go != NULL);


  lock_acquire(intersection_lock);
  // bool check = in_queue(origin);
  // if (!check){
  //   check = true;
  // }
  // if (q_empty(next_lights)){
  //   first_dir = origin;
  //   current_light = &first_dir;
  // }
  // add the cu
  // if(!in_queue(origin)){
        
  //       q_addtail(next_lights,pointer);
  //   }

  // current_light = q_peek(next_lights);
  // q_remhead(next_lights);

  // if (origin == north){
  //   // if the light is green
    
  //   if(!in_queue(origin)){
  //     q_addtail(next_lights,&north_dir);
  //   }

  //   current_light = q_peek(next_lights);
  //   // q_remhead(next_lights);
  //   if (origin == *current_light)  {
  //     if (num_vehicles_waiting_north != 0){
  //         num_vehicles_waiting_north++;
  //         cv_wait(cv_north_go,intersection_lock);
  //     }
  //   }
  //   else{
  //       num_vehicles_waiting_north++;
  //       cv_wait(cv_north_go,intersection_lock);
  //   }
  // }
  // else if (origin == south){
  //   // if the light is green
  //   if(!in_queue(origin)){
  //     q_addtail(next_lights,&south_dir);
  //   }
  //   current_light = q_peek(next_lights);
  //   // q_remhead(next_lights);
  //   if (origin == *current_light) {
  //     if (num_vehicles_waiting_south != 0){
  //     num_vehicles_waiting_south++;    
  //     cv_wait(cv_south_go,intersection_lock);
  //     }
  //   }
  //       else{
  //       num_vehicles_waiting_south++;
  //       cv_wait(cv_south_go,intersection_lock);
  //   }
  // }  
  // else if (origin == east){
  //   // if the light is green
  //   if(!in_queue(origin)){
  //     q_addtail(next_lights,&east_dir);
  //   }
    
  //   current_light = q_peek(next_lights);
  //   // q_remhead(next_lights);
  //   if (origin == *current_light) {
  //     if (num_vehicles_waiting_east != 0){
  //     num_vehicles_waiting_east++;   
  //     cv_wait(cv_east_go,intersection_lock);
  //     }
  //   }
  //   else{
  //     num_vehicles_waiting_east++;   
  //     cv_wait(cv_east_go,intersection_lock);      
  //   }
  // }  
  // else if (origin == west){
  //   // if the light is green
  //   if(!in_queue(origin)){
  //     q_addtail(next_lights,&west_dir);
  //   }
    
  //   current_light = q_peek(next_lights);
  //   // q_remhead(next_lights);
  //   if (origin == *current_light) {
  //     if (num_vehicles_waiting_west != 0){
  //     num_vehicles_waiting_west++;     
  //     cv_wait(cv_west_go,intersection_lock);
  //     }

  //   }else{
  //     num_vehicles_waiting_west++;     
  //     cv_wait(cv_west_go,intersection_lock);
  //   }
  // }

  if (origin == north)
    {
    // if the light is green
    if(!in_queue(origin)){
      q_addtail(next_lights,&north_dir);
    }
    current_light = q_peek(next_lights);
    // q_remhead(next_lights);
    num_vehicles_waiting_north++;
    if (origin != *current_light)  {
      cv_wait(cv_north_go,intersection_lock);
    }
   
  }
  else if (origin == south){
    // if the light is green
    if(!in_queue(origin)){
      q_addtail(next_lights,&south_dir);
    }
    current_light = q_peek(next_lights);
    // q_remhead(next_lights);
    num_vehicles_waiting_south++;    

    if (origin != *current_light) {
      
      cv_wait(cv_south_go,intersection_lock);
      
    }
       
  }  
  else if (origin == east){
    // if the light is green
    if(!in_queue(origin)){
      q_addtail(next_lights,&east_dir);
    }
    
    current_light = q_peek(next_lights);
    num_vehicles_waiting_east++;
    // q_remhead(next_lights);
    if (origin != *current_light) {
      cv_wait(cv_east_go,intersection_lock); 
    }

  }  
  else if (origin == west){
    // if the light is green
    if(!in_queue(origin)){
      q_addtail(next_lights,&west_dir);
    }
    num_vehicles_waiting_west++; 
    current_light = q_peek(next_lights);
    // q_remhead(next_lights);
    if (origin == *current_light) {
      cv_wait(cv_west_go,intersection_lock);
      

    }
  }
  lock_release(intersection_lock);
}