385 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			385 lines
		
	
	
	
		
			9.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdbool.h>
 | 
						|
 | 
						|
# define MAX 4
 | 
						|
 | 
						|
	typedef struct {
 | 
						|
		char pid[5]; // Process ID (string)
 | 
						|
		int at; // Arrival Time
 | 
						|
		int bt; // Burst Time
 | 
						|
		int priority; // Priority (lower value = higher priority)
 | 
						|
		int ct; // Completion Time
 | 
						|
		int tat; // Turnaround Time
 | 
						|
		int wt; // Waiting Time
 | 
						|
		int rt; // Response Time
 | 
						|
		int remaining_bt; // Remaining Burst Time (for preemptive sjf)
 | 
						|
		int is_completed; // completion flag
 | 
						|
	} Process;
 | 
						|
 | 
						|
	void swap(Process *a, Process *b) {
 | 
						|
		Process temp = *a;
 | 
						|
		*a = *b;
 | 
						|
		*b = temp;
 | 
						|
	}
 | 
						|
 | 
						|
	// Function to calculate Completion Time, Turnaround Time, and Waiting Time
 | 
						|
	void calculate_times(Process processes[], int n) {
 | 
						|
		for (int i = 0; i < n; i++) {
 | 
						|
		processes[i].tat = processes[i].ct - processes[i].at;
 | 
						|
		processes[i].wt = processes[i].tat - processes[i].bt;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Function to calculate average times
 | 
						|
	void calculate_averages(Process processes[], int n, float *avg_ct,
 | 
						|
		float *avg_tat, float *avg_wt, float *avg_rt) {
 | 
						|
		*avg_ct = 0;
 | 
						|
		*avg_tat = 0;
 | 
						|
		*avg_wt = 0;
 | 
						|
		*avg_rt = 0;
 | 
						|
 | 
						|
		for (int i = 0; i < n; i++) {
 | 
						|
		*avg_ct += processes[i].ct;
 | 
						|
		*avg_tat += processes[i].tat;
 | 
						|
		*avg_wt += processes[i].wt;
 | 
						|
		*avg_rt += processes[i].rt;
 | 
						|
		}
 | 
						|
 | 
						|
		*avg_ct /= n;
 | 
						|
		*avg_tat /= n;
 | 
						|
		*avg_wt /= n;
 | 
						|
		*avg_rt /= n;
 | 
						|
	}
 | 
						|
 | 
						|
	// Function to display the Gantt chart
 | 
						|
	void display_gantt_chart(Process processes[], int n, int timeline[], int timeline_index) {
 | 
						|
		printf("\nGantt Chart:\n");
 | 
						|
		printf("-----------------------------------------------------------\n");
 | 
						|
		int last_process = -1;
 | 
						|
		for(int i = 0; i < timeline_index; i++) {
 | 
						|
			if(timeline[i] != last_process) {
 | 
						|
				printf("%s ", processes[timeline[i]].pid);
 | 
						|
				last_process = timeline[i];
 | 
						|
			}
 | 
						|
		}
 | 
						|
		printf("\n-----------------------------------------------------------\n");
 | 
						|
	}
 | 
						|
 | 
						|
	// Function to display the process table
 | 
						|
	void display_table(Process processes[], int n) {
 | 
						|
		printf("--------------------------------------------------------------------"
 | 
						|
		"------\n");
 | 
						|
		printf("| PID   | AT  | BT  | CT  | TAT | WT  | RT  |\n");
 | 
						|
		printf("--------------------------------------------------------------------"
 | 
						|
		"------\n");
 | 
						|
		for (int i = 0; i < n; i++) {
 | 
						|
		printf("| %-5s | %-3d | %-3d | %-3d | %-3d | %-3d | %-3d |\n",
 | 
						|
		processes[i].pid, processes[i].at, processes[i].bt,
 | 
						|
		processes[i].ct, processes[i].tat, processes[i].wt,
 | 
						|
		processes[i].rt);
 | 
						|
		}
 | 
						|
		printf("--------------------------------------------------------------------"
 | 
						|
		"------\n");
 | 
						|
	}
 | 
						|
 | 
						|
	// Preemptive SJF
 | 
						|
	void preemptive_sjf(Process processes[], int n){
 | 
						|
 | 
						|
	// process sort by AT
 | 
						|
	for (int i = 0; i < n -1; i++){
 | 
						|
		for(int j = 0; j < n - i - 1; j++){
 | 
						|
			if(processes[j].at > processes[j+1].at){
 | 
						|
				swap(&processes[j], &processes[j + 1]);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	//remaining BT + completion flag
 | 
						|
	for (int i = 0; i < n; i++){
 | 
						|
		processes[i].remaining_bt = processes[i].bt;
 | 
						|
		processes[i].rt = -1;
 | 
						|
		processes[i].is_completed = 0;
 | 
						|
	}
 | 
						|
 | 
						|
	// init for values of relevant variables, shortest=-1 to indicate no process is selected
 | 
						|
	int current_time = 0;
 | 
						|
	int completed = 0;
 | 
						|
	int shortest = -1;
 | 
						|
 | 
						|
	int *timeline = (int *)malloc((n*100)*sizeof(int));
 | 
						|
	if (timeline == NULL) {
 | 
						|
		perror ("MemAlloc Error");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	int timeline_index = 0;
 | 
						|
	int last_process = -1;
 | 
						|
 | 
						|
	// setting to large values to prevent issues
 | 
						|
	while (completed != n)
 | 
						|
	{
 | 
						|
		shortest = -1;
 | 
						|
		int min_bt = 9999;
 | 
						|
 | 
						|
		for (int j = 0; j < n; j++) {
 | 
						|
			if (processes[j].at <= current_time && processes[j].remaining_bt > 0 && processes[j].remaining_bt < min_bt){
 | 
						|
				min_bt = processes[j].remaining_bt;
 | 
						|
				shortest = j;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if (shortest == -1){
 | 
						|
			current_time++;
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		if(processes[shortest].rt == -1) {
 | 
						|
			processes[shortest].rt = current_time - processes[shortest].at;
 | 
						|
		}
 | 
						|
 | 
						|
		if(shortest != last_process) {
 | 
						|
			timeline[timeline_index++] = shortest;
 | 
						|
			last_process = shortest;
 | 
						|
		}
 | 
						|
 | 
						|
		processes[shortest].remaining_bt--;
 | 
						|
		current_time++;
 | 
						|
 | 
						|
		if (processes[shortest].remaining_bt == 0) {
 | 
						|
			completed++;
 | 
						|
			processes[shortest].ct = current_time;
 | 
						|
			processes[shortest].is_completed = 1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	calculate_times(processes, n);
 | 
						|
 | 
						|
	float avg_ct, avg_tat, avg_wt, avg_rt;
 | 
						|
	calculate_averages(processes, n, &avg_ct, &avg_tat, &avg_wt, &avg_rt);
 | 
						|
 | 
						|
 | 
						|
	printf("\nPreemptive SJF Scheduling:\n");
 | 
						|
	display_table(processes, n);
 | 
						|
 | 
						|
 | 
						|
	printf("\nAverage Completion Time: %.2f\n", avg_ct);
 | 
						|
	printf("Average Turnaround Time: %.2f\n", avg_tat);
 | 
						|
	printf("Average Waiting Time: %.2f\n", avg_wt);
 | 
						|
	printf("Average Response Time: %.2f\n", avg_rt);
 | 
						|
 | 
						|
 | 
						|
	display_gantt_chart(processes, n, timeline, timeline_index);
 | 
						|
	free(timeline);
 | 
						|
}
 | 
						|
 | 
						|
	void round_robin(Process processes[], int n, int quantum) {
 | 
						|
 | 
						|
			for (int i = 0; i < n; i++) {
 | 
						|
				processes[i].remaining_bt = processes[i].bt;
 | 
						|
				processes[i].rt = -1;
 | 
						|
				processes[i].is_completed = 0;
 | 
						|
			}
 | 
						|
 | 
						|
 | 
						|
	int current_time = 0;
 | 
						|
			int completed = 0;
 | 
						|
			int i = 0;
 | 
						|
			int *timeline = (int *)malloc((n * 100) * sizeof(int));
 | 
						|
 | 
						|
	if (timeline == NULL) {
 | 
						|
				perror("Failed to allocate memory for timeline");
 | 
						|
				return;
 | 
						|
				}
 | 
						|
 | 
						|
	int timeline_index = 0;
 | 
						|
	int last_process = -1;
 | 
						|
 | 
						|
			while (completed != n) {
 | 
						|
				if (processes[i].remaining_bt > 0 && processes[i].at <= current_time) {
 | 
						|
					if (processes[i].rt == -1) {
 | 
						|
						processes[i].rt = current_time - processes[i].at;
 | 
						|
					}
 | 
						|
 | 
						|
					if(i != last_process) {
 | 
						|
						timeline[timeline_index++] = i;
 | 
						|
						last_process = i;
 | 
						|
					}
 | 
						|
 | 
						|
					int execute_time = (processes[i].remaining_bt > quantum) ? quantum : processes[i].remaining_bt;
 | 
						|
					processes[i].remaining_bt -= execute_time;
 | 
						|
					current_time += execute_time;
 | 
						|
 | 
						|
					if (processes[i].remaining_bt == 0) {
 | 
						|
						completed++;
 | 
						|
						processes[i].ct = current_time;
 | 
						|
						processes[i].is_completed = 1;
 | 
						|
					}
 | 
						|
 | 
						|
				} else if (processes[i].at > current_time) {
 | 
						|
					current_time++;
 | 
						|
				}
 | 
						|
 | 
						|
				i = (i + 1) % n;
 | 
						|
				if (current_time > 1000) break;
 | 
						|
			}
 | 
						|
 | 
						|
			calculate_times(processes, n);
 | 
						|
 | 
						|
			float avg_ct, avg_tat, avg_wt, avg_rt;
 | 
						|
			calculate_averages(processes, n, &avg_ct, &avg_tat, &avg_wt, &avg_rt);
 | 
						|
 | 
						|
			printf("\nRound Robin Scheduling (Quantum = %d):\n", quantum);
 | 
						|
			display_table(processes, n);
 | 
						|
 | 
						|
			printf("\nAverage Completion Time: %.2f\n", avg_ct);
 | 
						|
			printf("Average Turnaround Time: %.2f\n", avg_tat);
 | 
						|
			printf("Average Waiting Time: %.2f\n", avg_wt);
 | 
						|
			printf("Average Response Time: %.2f\n", avg_rt);
 | 
						|
 | 
						|
			display_gantt_chart(processes, n, timeline, timeline_index);
 | 
						|
			free(timeline);
 | 
						|
	}
 | 
						|
 | 
						|
	void non_preemptive_priority(Process processes[], int n) {
 | 
						|
			for (int i = 0; i < n - 1; i++) {
 | 
						|
				for (int j = 0; j < n - i - 1; j++) {
 | 
						|
					if (processes[j].at > processes[j + 1].at) {
 | 
						|
						swap(&processes[j], &processes[j + 1]);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			int current_time = 0;
 | 
						|
			int completed = 0;
 | 
						|
			int *timeline = (int *)malloc((n * 100) * sizeof(int));
 | 
						|
 | 
						|
	if (timeline == NULL) {
 | 
						|
				perror("Failed to allocate memory for timeline");
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
	int timeline_index = 0;
 | 
						|
	int last_process = -1;
 | 
						|
 | 
						|
			while (completed != n) {
 | 
						|
				int highest_priority = -1;
 | 
						|
				int min_priority = 9999;
 | 
						|
 | 
						|
				for (int j = 0; j < n; j++) {
 | 
						|
					if (processes[j].at <= current_time && processes[j].bt > 0 && processes[j].priority < min_priority) {
 | 
						|
						min_priority = processes[j].priority;
 | 
						|
						highest_priority = j;
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				if (highest_priority == -1) {
 | 
						|
					current_time++;
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
 | 
						|
				if (processes[highest_priority].rt == -1) {
 | 
						|
					processes[highest_priority].rt = current_time - processes[highest_priority].at;
 | 
						|
				}
 | 
						|
 | 
						|
				if(highest_priority != last_process) {
 | 
						|
					timeline[timeline_index++] = highest_priority;
 | 
						|
					last_process = highest_priority;
 | 
						|
				}
 | 
						|
 | 
						|
				current_time += processes[highest_priority].bt;
 | 
						|
				processes[highest_priority].ct = current_time;
 | 
						|
				processes[highest_priority].bt = 0;
 | 
						|
				completed++;
 | 
						|
		}
 | 
						|
 | 
						|
			calculate_times(processes, n);
 | 
						|
 | 
						|
			float avg_ct, avg_tat, avg_wt, avg_rt;
 | 
						|
			calculate_averages(processes, n, &avg_ct, &avg_tat, &avg_wt, &avg_rt);
 | 
						|
 | 
						|
			printf("\nNon-Preemptive Priority Scheduling:\n");
 | 
						|
			display_table(processes, n);
 | 
						|
 | 
						|
			printf("\nAverage Completion Time: %.2f\n", avg_ct);
 | 
						|
			printf("Average Turnaround Time: %.2f\n", avg_tat);
 | 
						|
			printf("Average Waiting Time: %.2f\n", avg_wt);
 | 
						|
			printf("Average Response Time: %.2f\n", avg_rt);
 | 
						|
 | 
						|
			display_gantt_chart(processes, n, timeline, timeline_index);
 | 
						|
			free(timeline);
 | 
						|
	}
 | 
						|
 | 
						|
	int main() {
 | 
						|
			int n, choice, quantum;
 | 
						|
 | 
						|
			printf("Enter the number of processes: ");
 | 
						|
			scanf("%d", &n);
 | 
						|
 | 
						|
			Process processes[n];
 | 
						|
 | 
						|
		// Input process details
 | 
						|
		for (int i = 0; i < n; i++) {
 | 
						|
	printf("\nEnter details for process %d:\n", i + 1);
 | 
						|
 | 
						|
	printf("PID: ");
 | 
						|
	scanf("%s", processes[i].pid);
 | 
						|
 | 
						|
	printf("Arrival Time: ");
 | 
						|
			scanf("%d", &processes[i].at);
 | 
						|
 | 
						|
	printf("Burst Time: ");
 | 
						|
			scanf("%d", &processes[i].bt);
 | 
						|
 | 
						|
	printf("Priority (lower value = higher priority): ");
 | 
						|
			scanf("%d", &processes[i].priority);
 | 
						|
 | 
						|
	processes[i].rt = 0; // Initialize response time
 | 
						|
			processes[i].is_completed = 0; // Initialize completion flag
 | 
						|
		}
 | 
						|
 | 
						|
		// Display initial table
 | 
						|
			printf("\nInitial Process Table:\n");
 | 
						|
			printf("-----------------------\n");
 | 
						|
			printf("| PID   | AT  | BT  |\n");
 | 
						|
			printf("-----------------------\n");
 | 
						|
 | 
						|
			for (int i = 0; i < n; i++) {
 | 
						|
				printf("| %-5s | %-3d | %-3d |\n", processes[i].pid, processes[i].at, processes[i].bt);
 | 
						|
			}
 | 
						|
 | 
						|
	printf("-----------------------\n");
 | 
						|
 | 
						|
		// Algorithm Selection Menu with Loop and Exit
 | 
						|
			while (1) {
 | 
						|
				printf("\nChoose a scheduling algorithm:\n");
 | 
						|
				printf("1. Preemptive SJF\n");
 | 
						|
				printf("2. Round Robin\n");
 | 
						|
				printf("3. Non-Preemptive Priority\n");
 | 
						|
				printf("4. Exit\n");
 | 
						|
				printf("Enter your choice: ");
 | 
						|
 | 
						|
		scanf("%d", &choice);
 | 
						|
 | 
						|
		switch (choice) {
 | 
						|
				case 1:
 | 
						|
					preemptive_sjf(processes, n);
 | 
						|
					break;
 | 
						|
				case 2:
 | 
						|
					printf("Enter the time quantum: ");
 | 
						|
					scanf("%d", &quantum);
 | 
						|
					round_robin(processes, n, quantum);
 | 
						|
							break;
 | 
						|
						case 3:
 | 
						|
					non_preemptive_priority(processes, n);
 | 
						|
					break;
 | 
						|
						case 4:
 | 
						|
					printf("Exiting program.\n");
 | 
						|
					exit(0);
 | 
						|
						default:
 | 
						|
					printf("Invalid choice. Please try again.\n");
 | 
						|
				}
 | 
						|
		}
 | 
						|
 | 
						|
		return 0;
 | 
						|
	}
 |