#include #include #include #include #include #include #include #include using namespace std; struct process_detail { //cpu_burst_times[0] is arrival time int pid; vector burst_times; int in_cpu; int current_burst_index; }; struct clock{ int push_signal; //boolean int timer; }; vector processes; queue ready_queue_fifo; struct process_detail* CPU = NULL; vector waiting; ofstream output_file("cpu_times.txt"); // -------------------------------------- THE FIFO -------------------------------------------------- void fifo() { //clock initialized to 0 struct clock time; memset(&time, 0, sizeof(struct clock)); time.timer = 0; time.push_signal = 0; int process_count = processes.size(); int completed_processes = 0; while(completed_processes < process_count){ // ready queue, waiting queue, cpu in check, ready queue subtraction, waiting queue subtraction // breaking from the infinite loop for(int i = 0; i < process_count; ++i) { if(processes[i].burst_times[processes[i].current_burst_index] == -2) { completed_processes++; } } //managing arrival times for(int i = 0; i < process_count; ++i) { //if process not in cpu if(processes[i].in_cpu != 1) { if(time.timer == processes[i].burst_times[0]) { ready_queue_fifo.push(&processes[i]); processes[i].current_burst_index++; } } } // managing waiting queue for(int j = 0; j < waiting.size(); ++j) { if(waiting[j] != NULL) { if(waiting[j]->burst_times[waiting[j]->current_burst_index] == 0) { ready_queue_fifo.push(waiting[j]); waiting[j]->current_burst_index++; waiting[j] = NULL; } } } if(CPU == NULL && !ready_queue_fifo.empty()) { CPU = ready_queue_fifo.front(); CPU->in_cpu = 1; // Record in_time when the process enters the CPU output_file << "P" << CPU->pid+1 << ",1" << " " << time.timer; ready_queue_fifo.pop(); } else if(CPU != NULL){ //check cpu_burst complete for(int i = 0; i < process_count; ++i) { if(processes[i].in_cpu == 1) { if(CPU->burst_times[processes[i].current_burst_index] == 0){ // Record out_time when the process exits the CPU output_file << " " << time.timer << endl; CPU->in_cpu = 0; CPU->current_burst_index++; waiting.push_back(CPU); // process added to waiting queue if(!ready_queue_fifo.empty()) { CPU = ready_queue_fifo.front(); // process added to CPU CPU->in_cpu = 1; output_file << "P" << CPU->pid+1 << ",1" << " " << time.timer; // New entry time ready_queue_fifo.pop(); } else { CPU = NULL; } } } } } if(CPU != NULL) { CPU->burst_times[CPU->current_burst_index]--; } for(int j = 0; j < waiting.size(); ++j) { if(waiting[j] != NULL) { if(waiting[j]->burst_times[waiting[j]->current_burst_index] != 0) { waiting[j]->burst_times[waiting[j]->current_burst_index]--; // reducing the io burst till it reaches 0 } } } time.timer++; } output_file.close(); return; } // ----------------------------------------- The Shortest Job Fist ------------------------------------------- // Custom comparator for the priority queue struct Compare { bool operator()(process_detail* a, process_detail* b) { // Compare the elements in the vector at the given indices return a->burst_times[a->current_burst_index] > b->burst_times[b->current_burst_index]; } }; priority_queue, Compare> ready_queue; void sjf() { //clock initialized to 0 struct clock time; memset(&time, 0, sizeof(struct clock)); time.timer = 0; time.push_signal = 0; int process_count = processes.size(); int completed_processes = 0; while(completed_processes < process_count){ // ready queue, waiting queue, cpu in check, ready queue subtraction, waiting queue subtraction // breaking from the infinite loop for(int i = 0; i < process_count; ++i) { if(processes[i].burst_times[processes[i].current_burst_index] == -2) { completed_processes++; } } //managing arrival times for(int i = 0; i < process_count; ++i) { //if process not in cpu if(processes[i].in_cpu != 1) { if(time.timer == processes[i].burst_times[0]) { ready_queue.push(&processes[i]); processes[i].current_burst_index++; } } } // managing waiting queue for(int j = 0; j < waiting.size(); ++j) { if(waiting[j] != NULL) { if(waiting[j]->burst_times[waiting[j]->current_burst_index] == 0) { ready_queue.push(waiting[j]); waiting[j]->current_burst_index++; waiting[j] = NULL; } } } if(CPU == NULL && !ready_queue.empty()) { CPU = ready_queue.top(); CPU->in_cpu = 1; // Record in_time when the process enters the CPU output_file << "P" << CPU->pid+1 << ",1" << " " << time.timer; ready_queue.pop(); } else if(CPU != NULL){ //check cpu_burst complete for(int i = 0; i < process_count; ++i) { if(processes[i].in_cpu == 1) { if(CPU->burst_times[processes[i].current_burst_index] == 0){ // Record out_time when the process exits the CPU output_file << " " << time.timer << endl; CPU->in_cpu = 0; CPU->current_burst_index++; waiting.push_back(CPU); // process added to waiting queue if(!ready_queue.empty()) { CPU = ready_queue.top(); // process added to CPU CPU->in_cpu = 1; output_file << "P" << CPU->pid+1 << ",1" << " " << time.timer; // New entry time ready_queue.pop(); } else { CPU = NULL; } } } } } if(CPU != NULL) { // reducing the cpu burst till it reaches 0 CPU->burst_times[CPU->current_burst_index]--; } for(int j = 0; j < waiting.size(); ++j) { if(waiting[j] != NULL) { if(waiting[j]->burst_times[waiting[j]->current_burst_index] != 0) { // reducing the io burst till it reaches 0 waiting[j]->burst_times[waiting[j]->current_burst_index]--; } } } time.timer++; } output_file.close(); return; } // ------------------------------------Pre-emptive shortest job -------------------------------------------- void pre_sjf() { //clock initialized to 0 struct clock time; memset(&time, 0, sizeof(struct clock)); time.timer = 0; time.push_signal = 0; int process_count = processes.size(); int completed_processes = 0; while(completed_processes < process_count){ // ready queue, waiting queue, cpu in check, ready queue subtraction, waiting queue subtraction // breaking from the infinite loop for(int i = 0; i < process_count; ++i) { if(processes[i].burst_times[processes[i].current_burst_index] == -2) { completed_processes++; } } //managing arrival times for(int i = 0; i < process_count; ++i) { //if process not in cpu if(processes[i].in_cpu != 1) { if(time.timer == processes[i].burst_times[0]) { ready_queue.push(&processes[i]); if(CPU != NULL) { ready_queue.push(CPU); CPU->in_cpu = 0; output_file << " " << time.timer << endl; CPU = ready_queue.top(); CPU->in_cpu = 1; output_file << "P" << CPU->pid+1 << ",1" << " " << time.timer; // New entry time ready_queue.pop(); } processes[i].current_burst_index++; } } } // managing waiting queue for(int j = 0; j < waiting.size(); ++j) { if(waiting[j] != NULL) { if(waiting[j]->burst_times[waiting[j]->current_burst_index] == 0) { ready_queue.push(waiting[j]); if(CPU != NULL) { ready_queue.push(CPU); CPU->in_cpu = 0; output_file << " " << time.timer << endl; CPU = ready_queue.top(); CPU->in_cpu = 1; output_file << "P" << CPU->pid+1 << ",1" << " " << time.timer; // New entry time ready_queue.pop(); } waiting[j]->current_burst_index++; waiting[j] = NULL; } } } if(CPU == NULL && !ready_queue.empty()) { CPU = ready_queue.top(); CPU->in_cpu = 1; // Record in_time when the process enters the CPU output_file << "P" << CPU->pid+1 << ",1" << " " << time.timer; ready_queue.pop(); } else if(CPU != NULL){ //check cpu_burst complete for(int i = 0; i < process_count; ++i) { if(processes[i].in_cpu == 1) { if(CPU->burst_times[processes[i].current_burst_index] == 0){ // Record out_time when the process exits the CPU output_file << " " << time.timer << endl; CPU->in_cpu = 0; CPU->current_burst_index++; waiting.push_back(CPU); // process added to waiting queue if(!ready_queue.empty()) { CPU = ready_queue.top(); // process added to CPU CPU->in_cpu = 1; output_file << "P" << CPU->pid+1 << ",1" << " " << time.timer; // New entry time ready_queue.pop(); } else { CPU = NULL; } } } } } if(CPU != NULL) { // reducing the cpu burst till it reaches 0 CPU->burst_times[CPU->current_burst_index]--; } for(int j = 0; j < waiting.size(); ++j) { if(waiting[j] != NULL) { if(waiting[j]->burst_times[waiting[j]->current_burst_index] != 0) { // reducing the io burst till it reaches 0 waiting[j]->burst_times[waiting[j]->current_burst_index]--; } } } time.timer++; } output_file.close(); return; } // ------------------------------------------- Round Robin -------------------------------------------------- void round_robin() { // Clock initialized to 0 struct clock time; memset(&time, 0, sizeof(struct clock)); time.timer = 0; time.push_signal = 5; int process_count = processes.size(); int completed_processes = 0; int time_quantum = 2; // Define a time quantum for Round Robin // To keep track of the remaining quantum for the current process int current_quantum = 0; while (completed_processes < process_count) { // Ready queue, waiting queue, CPU in check, ready queue subtraction, waiting queue subtraction // Breaking from the loop for (int i = 0; i < process_count; ++i) { if (processes[i].burst_times[processes[i].current_burst_index] == -2) { completed_processes++; } } // Managing arrival times for (int i = 0; i < process_count; ++i) { // If process not in CPU if (processes[i].in_cpu != 1) { if (time.timer == processes[i].burst_times[0]) { ready_queue_fifo.push(&processes[i]); processes[i].current_burst_index++; } } } // Managing waiting queue for (int j = 0; j < waiting.size(); ++j) { if (waiting[j] != NULL) { if (waiting[j]->burst_times[waiting[j]->current_burst_index] == 0) { ready_queue_fifo.push(waiting[j]); waiting[j]->current_burst_index++; waiting[j] = NULL; } } } if (CPU == NULL && !ready_queue_fifo.empty()) { // Assign the first process from the ready queue to the CPU CPU = ready_queue_fifo.front(); CPU->in_cpu = 1; // Record in_time when the process enters the CPU output_file << "P" << CPU->pid + 1 << ",1 " << time.timer; ready_queue_fifo.pop(); current_quantum = time_quantum; // Reset the time quantum for the new process } else if (CPU != NULL) { // Check if CPU burst is complete or quantum expired if (CPU->burst_times[CPU->current_burst_index] == 0 || current_quantum == 0) { // Record out_time when the process exits the CPU output_file << " " << time.timer << endl; CPU->in_cpu = 0; CPU->current_burst_index++; // If the process still has bursts left, move it to the waiting queue if (CPU->burst_times[CPU->current_burst_index] > 0) { waiting.push_back(CPU); } // Assign the next process from the ready queue to the CPU if (!ready_queue_fifo.empty()) { CPU = ready_queue_fifo.front(); CPU->in_cpu = 1; output_file << "P" << CPU->pid + 1 << ",1 " << time.timer; // New entry time ready_queue_fifo.pop(); current_quantum = time_quantum; // Reset the time quantum for the new process } else { CPU = NULL; } } } if (CPU != NULL) { // Decrement the burst time of the process currently in the CPU CPU->burst_times[CPU->current_burst_index]--; current_quantum--; // Decrement the quantum counter // If quantum is exhausted but burst isn't finished, preempt the process if (current_quantum == 0 && CPU->burst_times[CPU->current_burst_index] > 0) { ready_queue_fifo.push(CPU); // Re-add the process to the ready queue CPU->in_cpu = 0; CPU = NULL; // Preempt the process from the CPU } } // Reduce the IO burst times of the processes in the waiting queue for (int j = 0; j < waiting.size(); ++j) { if (waiting[j] != NULL) { if (waiting[j]->burst_times[waiting[j]->current_burst_index] != 0) { waiting[j]->burst_times[waiting[j]->current_burst_index]--; // Reducing the IO burst until it reaches 0 } } } time.timer++; } output_file.close(); return; } int main(int argc, char **argv) { if(argc != 3) { cout <<"usage: ./scheduler.out \nprovided arguments:\n"; for(int i = 0; i < argc; i++) cout << argv[i] << "\n"; return -1; } char *file_to_search_in = argv[1]; char *scheduler_algorithm = argv[2]; ifstream file(file_to_search_in, ios::binary); string buffer; int pid = 0; while(getline(file, buffer)) { if(buffer[0] == '<'){ continue; } istringstream iss(buffer); string word; struct process_detail pd; memset(&pd,0,sizeof(struct process_detail)); pd.pid = pid++; pd.current_burst_index = 0; while(iss>>word){ pd.burst_times.push_back(stoi(word)); } processes.push_back(pd); } map temp; temp["fifo"] = 1; temp["sjf"] = 2; temp["pre_sjf"] = 3; temp["rr"] = 4; string temp1 = scheduler_algorithm; switch(temp[temp1]){ case 1: fifo(); break; case 2: sjf(); break; case 3: pre_sjf(); break; case 4: round_robin(); break; default: cout << "enter fifo or sjf or pre_sjf or rr" << endl; } return 0; }