bool in_queue(Direction light_to_push) { bool flag = false; int i = 0; for (i=q_getstart(next_lights); i!=q_getend(next_lights); i=(i+1)%q_getsize(next_lights)) { Direction *ptr = q_getguy(next_lights, i); if (light_to_push == *ptr){ flag = true; } } return flag; }
/* * Debugging function to dump the run queue. */ void print_run_queue(void) { /* Turn interrupts off so the whole list prints atomically. */ int spl = splhigh(); int i,k=0; i = q_getstart(runqueue); while (i!=q_getend(runqueue)) { struct thread *t = q_getguy(runqueue, i); kprintf(" %2d: %s %p\n", k, t->t_name, t->t_sleepaddr); i=(i+1)%q_getsize(runqueue); k++; } splx(spl); }
void print_run_queue(void) { /* Turn interrupts off so the whole list prints atomically. */ int spl = splhigh(); int i, j, k; for(i = 0; i < NUM_PRIORITIES; i++) { j = q_getstart(runqueue[i]); k = 0; kprintf("Priority %d:\n", i); while (j != q_getend(runqueue[i])) { struct thread *t = q_getguy(runqueue[i], j); kprintf(" %2d: %s %p\n", k, t->t_name, t->t_sleepaddr); j = (j + 1) % q_getsize(runqueue[i]); k++; } } splx(spl); }
/* * 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); }