// driver for the scheduling algorithm simulation #include #include #include // I know I know, I am mixing C and C++ io #include "linkedlist.h" #include "sched.h" int getproc(); void spew_stats(linked_list* done, int longest, int now, int loadsum); void parse_args(int argc, char* argv[], sched** method); // ----------------------------------------------------------------- int main(int argc, char* argv[]) { // ready, run and done queues // linked_list ready; // The way I've worked it out, there is no need for a ready queue. linked_list run; linked_list done; sched* scheduler; // relative system time int now = 0; // execution time of next incoming process. Set to 0 if none pending. int nextproc = 0; // remember the longest process for stats calculation int longest = 0; // used to calculate virtual system load int loadsum = 0; parse_args(argc, argv, &scheduler); // while there is input pending or there are 'processes' in the // ready or run queues, keep looping while ((! feof(stdin)) || run.node_count() /* || ready.node_count() */ ) { // "Time is an illusion, lunchtime doubly so." now++; // get a line of input, if available nextproc = getproc(); // keep track of longest process so far, for stats calculation later if (nextproc > longest) longest = nextproc; // add current load to the overall sum loadsum += run.node_count(); // 'execute' the 'process' for a simulated time slice if (run.node_count()) { run.current()->time_remaining --; // if a process has finished, put it on done queue if (! run.current()->time_remaining) { run.current()->exit_time = now; // ============== // Danger Will Robinson! I am assuming that current ALWAYS == head // ============== done.insert_tail(run.remove_head()); } } // call the scheduler scheduler->schedule(nextproc, now, &run); } // calculate and print out the sadistics spew_stats(&done, longest, now, loadsum); } // ---------------------------------------------------------------------- int getproc() { char temp[80]; if (! feof(stdin)) { fgets(temp, sizeof(temp), stdin); // plain gets is a security risk return(atoi(temp)); } else { return(0); } } // ---------------------------------------------------------------------- void spew_stats(linked_list* done, int longest, int now, int loadsum) { pcb* temp; int *min; int *max; int *sum; int *count; int i; int runtime; cout << longest << endl; cout << setiosflags(ios::fixed) << setprecision(2) << (float) loadsum / (float) now << endl; min = new int[longest]; max = new int[longest]; sum = new int[longest]; count = new int[longest]; for (i = 0; i < longest; i++) { min[i] = 32767; // Dammit, I can't remember what to include for maxint! max[i] = 0; sum[i] = 0; count[i] = 0; } while (done->node_count()) { temp = done->remove_head(); runtime = temp->exit_time - temp->start_time; if (runtime < min[temp->execution_time - 1]) min[temp->execution_time - 1] = runtime; if (runtime > max[temp->execution_time - 1]) max[temp->execution_time - 1] = runtime; sum[temp->execution_time - 1] += runtime; count[temp->execution_time - 1] ++; } for (i = 0; i < longest; i++) { // precision is set this way for no better reason than to match the load cout << i + 1 << " " << setiosflags(ios::fixed) << setprecision(2) << (float) sum[i] / (float) count[i] << " " << min[i] << " " << max[i] << endl; } //while (done->node_count()) //{ // temp = done->remove_head(); // cout << temp->execution_time << " " << temp->exit_time - temp->start_time // << endl; // delete temp; //} } // --------------------------------------------------------------- void parse_args(int argc, char* argv[], sched** method) { int error = 0; if (argc != 2) { error = 1; } else { switch (atoi(argv[1])) { case 1: *method = new fcfs; break; case 2: *method = new rr; break; case 3: *method = new sjn; break; default: error ++; break; } } if (error) { cout << "USAGE:" << endl; cout << " sched [method]" << endl << endl; cout << " where [method] is" << endl; cout << " 1 - First Come First Served" << endl; cout << " 2 - Round-Robin" << endl; cout << " 3 - Shortest Job Next" << endl; exit (1); } }