diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..27bb48f7a41b5c818394b28967a19b8232757f31 Binary files /dev/null and b/.DS_Store differ diff --git a/os-simulator/OSInput.txt.txt b/os-simulator/OSInput.txt.txt new file mode 100644 index 0000000000000000000000000000000000000000..1321be9ee2be0a2f6a6fc5225ac65fde4ed40b09 --- /dev/null +++ b/os-simulator/OSInput.txt.txt @@ -0,0 +1,4 @@ +1, A, 0, 4, 10 +2, B, 4, 50, 2 +3, C, 10, 4, 10 +4, D, 20, 2, 10 \ No newline at end of file diff --git a/os-simulator/src/.DS_Store b/os-simulator/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 Binary files /dev/null and b/os-simulator/src/.DS_Store differ diff --git a/os-simulator/src/main/.DS_Store b/os-simulator/src/main/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 Binary files /dev/null and b/os-simulator/src/main/.DS_Store differ diff --git a/os-simulator/src/main/java/com/com1032/assignment/Clock.java b/os-simulator/src/main/java/com/com1032/assignment/Clock.java new file mode 100644 index 0000000000000000000000000000000000000000..b9acd91cc01b1c287ab0459ba1e1c4141624422a --- /dev/null +++ b/os-simulator/src/main/java/com/com1032/assignment/Clock.java @@ -0,0 +1,21 @@ +/** + * + */ +package com.com1032.assignment; + +/** + * @author felipedabrantes + * + */ +public class Clock { + + public int time = 0; + + + + @Override + public String toString() { + return String.valueOf(this.time); + } + +} diff --git a/os-simulator/src/main/java/com/com1032/assignment/OS.java b/os-simulator/src/main/java/com/com1032/assignment/OS.java new file mode 100644 index 0000000000000000000000000000000000000000..8372bb98e699c8315c0c545368d85a5405704dc7 --- /dev/null +++ b/os-simulator/src/main/java/com/com1032/assignment/OS.java @@ -0,0 +1,103 @@ +/** + * OS.java + */ +package com.com1032.assignment; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +/** + * @author felipedabrantes + * + */ +public class OS { + + /**The global time of the OS.*/ + private Clock globalTime = new Clock(); + /**The class the handles the process scheduling.*/ + private ProcessSchedulerSimulator pss = null; + /**A list of processes of the OS.*/ + private List<Process> processes = new ArrayList<Process>(); + + + /** + * Constructor. Initialises fields. + */ + public OS() { + + this.pss = new ProcessSchedulerSimulator(this.globalTime); + } + + /** + * @param args + * @throws FileNotFoundException + * @throws IOException + */ + public static void main(String[] args) throws FileNotFoundException { + OS os = new OS(); + + os.addProcess("OSInput.txt"); + os.runProcessScheduling(); + + } + + + /** + * Used to a single process to OS. + * @param process + */ + public void addProcess(Process process) { + this.processes.add(process); + } + + + /** + * Used to add processes from a file to the OS. + * + * @param fileName of the processes file. + * + * @throws FileNotFoundException if no file is found. + */ + public void addProcess(String fileName){ + //Tries to open file. + try { + File file = new File(fileName); + Scanner fileReader = new Scanner(file); + + //Reads file line by line. + while (fileReader.hasNextLine()) { + //Splits process info to make a process object. + String[] data = fileReader.nextLine().split(", "); + this.processes.add(new Process( + Integer.valueOf(data[0]), + data[1], + Integer.valueOf(data[4]), + Integer.valueOf(data[3]), + Integer.valueOf(data[2]))); + } + + //Closes file. + fileReader.close(); + } + //Ran if no file is found. + catch(FileNotFoundException e) { + System.out.println("File not found."); + } + + } + + + /** + * Runs process scheduling simulation with processes in OS. + */ + public void runProcessScheduling() { + pss.addProcessToJob(this.processes); + pss.run(SchedulingAlgorithm.SPF, 3); + System.out.println(pss.getReport()); + } + +} diff --git a/os-simulator/src/main/java/com/com1032/assignment/Process.java b/os-simulator/src/main/java/com/com1032/assignment/Process.java new file mode 100644 index 0000000000000000000000000000000000000000..4efbf0631998bf2b3692fd53c41013996782b53c --- /dev/null +++ b/os-simulator/src/main/java/com/com1032/assignment/Process.java @@ -0,0 +1,173 @@ +/** + * Process.java + */ +package com.com1032.assignment; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author felipedabrantes + * + */ +public class Process { + /**The unique ID to identify the process.*/ + private int id = 0; + /**The name of the process.*/ + private String name = null; + /**The state of the process.*/ + private ProcessState state = ProcessState.NEW; + + //---Attributes for process scheduling. --- + /**States the importance of the process. Higher is more important.*/ + private int priority = 0; + /**Global time at which process arrives to ready queue.*/ + private int arrivalTime = 0; + /**Global time at which process completes its execution.*/ + private int completionTime = -1; + /**Time required for CPU execution.*/ + private final int burstTime; + /**Time remaining for process finished.*/ + private int remainingTime = 0; + + +// private List<Thread> threads = new ArrayList<Thread> (); + + + /** + * Constructor. Initialises fields. + * + * @param id + * @param state + * @param priority + * @param arrivalTime + * @param completionTime + * @param burstTime + */ + public Process(int id, String name, int priority, int burstTime, int arrivalTime) { + super(); + this.id = id; + this.name = name; + this.priority = priority; + this.arrivalTime = arrivalTime; + this.burstTime = burstTime; + this.remainingTime = burstTime; + } + + + /** + * @param id + */ + public void setId(int id) { + this.id = id; + } + + public void setState(ProcessState state) { + this.state = state; + } + + + /** + * @param completionTime + */ + public void setCompletionTime(int completionTime) { + this.completionTime = completionTime; + } + + + /** + * @param remainingTime + */ + public void setRemainingTime(int remainingTime) { + this.remainingTime = remainingTime; + } + + /** + * @param arrivalTime + */ + public void setArrivalTime(int arrivalTime) { + this.arrivalTime = arrivalTime; + } + + /** + * @return the id + */ + public int getId() { + return this.id; + } + + /** + * @return the name + */ + public String getName() { + return this.name; + } + + /** + * @return the state + */ + public ProcessState getState() { + return this.state; + } + + /** + * @return the priority + */ + public int getPriority() { + return this.priority; + } + + /** + * @return the arrivalTime + */ + public int getArrivalTime() { + return this.arrivalTime; + } + + /** + * @return the completionTime + */ + public int getCompletionTime() { + return this.completionTime; + } + + /** + * @return the burstTime + */ + public int getBurstTime() { + return this.burstTime; + } + + /** + * @return the burstTime + */ + public int getRemainingTime() { + return this.remainingTime; + } + + + + public String toString() { + + StringBuffer info = new StringBuffer(); + + info.append("\nProcess #"); + info.append(this.id); + info.append(" | Name: "); + info.append(this.name); + info.append(" | State: "); + info.append(this.state); + info.append(" | Arrival Time: "); + info.append(this.arrivalTime); + info.append(" | Burst Time: "); + info.append(this.burstTime); + info.append(" | Remaining Time: "); + info.append(this.remainingTime); + info.append(" | Completion Time: "); + info.append(this.completionTime); + + return info.toString(); + + } + +} diff --git a/os-simulator/src/main/java/com/com1032/assignment/ProcessSchedulerSimulator.java b/os-simulator/src/main/java/com/com1032/assignment/ProcessSchedulerSimulator.java new file mode 100644 index 0000000000000000000000000000000000000000..546e17530cfcd52f4a411c3f3d3297904d7e5905 --- /dev/null +++ b/os-simulator/src/main/java/com/com1032/assignment/ProcessSchedulerSimulator.java @@ -0,0 +1,331 @@ +/** + * ProcessScheduler.java + */ +package com.com1032.assignment; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author felipedabrantes + * + */ +public class ProcessSchedulerSimulator { + /**New processes added to the system.*/ + private List<Process> jobQueue = new ArrayList<Process> (); + /**Processes ready to be executed.*/ + private List<Process> readyQueue = new ArrayList<Process> (); + /**Processes waiting for I/O.*/ + private List<Process> waitingQueue = new ArrayList<Process> (); + /**Processes that have finished executing.*/ + private List<Process> terminatedQueue = new ArrayList<Process> (); + /**Processes that are using CPU.*/ + private List<Process> CPUQueue = new ArrayList<Process> (); + + /**The latest ran process.*/ + private Process scheduledProcess = null; + + /**The time spent running of the previous process.*/ + private int previousProcessTimeSpent = 0; + + /**The global time of the system.*/ + private Clock globalTime = null; + + /**The info report of the process scheduler.*/ + private StringBuffer report = new StringBuffer(); + + + /** + * Constructor. Sets global time. + * + * @param globalTime + */ + public ProcessSchedulerSimulator(Clock globalTime) { + this.globalTime = globalTime; + } + + + /** + * @return report of scheduler as string. + */ + public String getReport() { + return this.report.toString(); + } + + + /** + * Main function to run processes with the desired algorithm. + * + * Quantum is needed for specific algorithms. + * + * @param algorithm to use. + * + * @param quantum for round robin algorithm. + */ + public void run(SchedulingAlgorithm algorithm, int quantum) { + + //Adding configuration info. + this.report.insert(0, "---Process Scheduler---\n* Algorithm: " + algorithm + "\n* Quantum: " + quantum + "\n\n"); +// this.report.append("Process Scheduler"); +// this.report.append("\n* Algorithm: " + algorithm); +// this.report.append("\n* Quantum: " + quantum); + + + while(!this.jobQueue.isEmpty() || !this.readyQueue.isEmpty() || this.scheduledProcess != null) { + + //---Arrival--- + //Update ready queue to see if any processes are ready. + this.updateReadyQueue(); + + + //---Termination Check--- + //Checks if any processes have finished. + if(this.scheduledProcess != null) { + //Terminates process if process is done. + if(this.scheduledProcess.getRemainingTime() == 0) { + this.terminateProcess(this.scheduledProcess); + } + } + + //---Empty Ready Queue--- + //If no processes are ready yet, increase time by 1. + if(this.readyQueue.isEmpty()) { + + if(this.scheduledProcess != null) { + + //In case of round robin, resets the time spent when above quantum. + if(algorithm == SchedulingAlgorithm.RR && this.previousProcessTimeSpent >= quantum) { + this.previousProcessTimeSpent = 0; + } + + this.runProcess(this.scheduledProcess); + } + else { + this.globalTime.time++; + } + + continue; + } + + //---Scheduling--- + //Preemptive means processes can be interrupted. Constantly checked. + //Non-Preemptive means processes run until finished. + switch(algorithm) { + case FIFO: + runFIFO(); + break; + case SRTF: + runSRTF(); + break; + case SPF: + runSPF(); + break; + case RR: + runRR(quantum); + break; + } + + //---Running--- + //Run the scheduled process, if any. + if(this.scheduledProcess != null) { + this.runProcess(this.scheduledProcess); + } + + } + + } + + + /** + * Adds process to system (job queue). + * + * @param process to add to system. + */ + public void addProcessToJob(Process process) { + this.jobQueue.add(process); + this.report.append("\n- Added to Job Queue: " + process + "\n"); + } + + + /** + * Adds processes given in list to system (job queue). + * + * @param processes list to add to system. + */ + public void addProcessToJob(List<Process> processes) { + for(Process process: processes) { + this.jobQueue.add(process); + this.report.append("\n- Added to Job Queue @ " + this.globalTime.time + ":" + process + "\n"); + } + } + + + /** + * Function used to schedule a process to CPU. + * + * @param process to schedule. + */ + public void scheduleProcess(Process process) { + //Only schedules if not running already. + if(this.scheduledProcess != process) { + + this.previousProcessTimeSpent = 0; + + //Ran if there is already a process running. + if(this.scheduledProcess != null) { + this.contextSwitch(process); + } + + //Update scheduler attributes. + this.report.append("\n- Schedule @ " + this.globalTime.time + ":" + process + "\n"); + process.setState(ProcessState.RUNNING); + this.scheduledProcess = process; + this.readyQueue.remove(process); + } + } + + + /** + * Function used to run a process. + * + * @param process to run. + */ + public void runProcess(Process process) { + this.previousProcessTimeSpent++; + process.setRemainingTime(process.getRemainingTime() - 1); + this.globalTime.time++; + } + + + /** + * Function used when terminating a process. + * + * @param process to terminate. + */ + public void terminateProcess(Process process) { + //Update process properties. + process.setCompletionTime(this.globalTime.time); + process.setState(ProcessState.TERMINATED); + + //Update scheduler info. + this.scheduledProcess = null; + this.readyQueue.remove(process); + this.terminatedQueue.add(process); + this.report.append("\n- Terminated @ " + this.globalTime.time + ":" + process + "\n"); + } + + + /** + * Function used when suspending a process. + * + * @param process to suspend. + */ + public void contextSwitch(Process process) { + this.readyQueue.add(this.scheduledProcess); + this.report.append("\n- Suspending @ " + this.globalTime.time + ":" + this.scheduledProcess + "\n"); + this.scheduledProcess.setState(ProcessState.READY); + } + + + /** + * Updates ready queue by checking arrival times of processes in job queue. + * + * If arrival time equals global time add it to ready queue. + */ + public void updateReadyQueue() { + List<Process> updatedProcesses = new ArrayList<Process> (); + + for(Process process: this.jobQueue) { + if(process.getArrivalTime() == this.globalTime.time) { + updatedProcesses.add(process); + } + } + + for(Process process: updatedProcesses) { + process.setState(ProcessState.READY); + this.jobQueue.remove(process); + this.readyQueue.add(process); + + this.report.append("\n- Added to Ready Queue @ " + this.globalTime.time + ":" + process + "\n"); + } + } + + /** + * Runs the FIFO algorithm. + * + * First-In-First-Out. + */ + public void runFIFO() { + //Non-Preemptive, won't access new process from ready queue if one is already running. + if(this.scheduledProcess == null) { + Process currentProcess = this.readyQueue.get(0); + this.scheduleProcess(currentProcess); + } + else { + this.scheduleProcess(this.scheduledProcess); + } + + } + + + /** + * Runs the SPF algorithm. + * + * Shortest Process First. + */ + public void runSPF() { + //Non-Preemptive, won't access new process from ready queue if one is already running. + if(this.scheduledProcess == null) { + + //Find smallest burst time process. + Process currentProcess = this.readyQueue.get(0); + for(Process process: this.readyQueue) { + if(process.getBurstTime() < currentProcess.getBurstTime()) { + currentProcess = process; + } + } + + this.scheduleProcess(currentProcess); + } + else { + this.scheduleProcess(this.scheduledProcess); + } + + } + + + /** + * Runs the SRTF algorithm. + * + * Shortest Remaining Time First. + */ + public void runSRTF() { + //Find smallest remaining time process. + Process currentProcess = this.readyQueue.get(0); + for(Process process: this.readyQueue) { + if(process.getRemainingTime() < currentProcess.getRemainingTime()) { + currentProcess = process; + } + } + + this.scheduleProcess(currentProcess); + + } + + + /** + * Runs the RR algorithm with the given quantum.. + * + * Round Robin. + * + * @param quantum to use. + */ + public void runRR(int quantum) { + Process currentProcess = this.readyQueue.get(0); + + if(this.previousProcessTimeSpent >= quantum || this.scheduledProcess == null) { + this.scheduleProcess(currentProcess); + } + } + +} diff --git a/os-simulator/src/main/java/com/com1032/assignment/ProcessState.java b/os-simulator/src/main/java/com/com1032/assignment/ProcessState.java new file mode 100644 index 0000000000000000000000000000000000000000..06dd3ada400dddb31989910959ba9b9d2b9c4913 --- /dev/null +++ b/os-simulator/src/main/java/com/com1032/assignment/ProcessState.java @@ -0,0 +1,27 @@ +/** + * State.java + */ +package com.com1032.assignment; + +/** + * An enumeration to access all possible states of a process. + * + * @author felipedabrantes + * + */ +public enum ProcessState { + /**Process is being created.*/ + NEW, + + /**Process is being executed on a processor.*/ + RUNNING, + + /**Process can execute when a processor is available.*/ + READY, + + /**Process is waiting for event to occur.*/ + BLOCKED, + + /**Process has finished execution.*/ + TERMINATED +} \ No newline at end of file diff --git a/os-simulator/src/main/java/com/com1032/assignment/SchedulingAlgorithm.java b/os-simulator/src/main/java/com/com1032/assignment/SchedulingAlgorithm.java new file mode 100644 index 0000000000000000000000000000000000000000..2e74a2d57356dda98a028199717e3e62608dcc5c --- /dev/null +++ b/os-simulator/src/main/java/com/com1032/assignment/SchedulingAlgorithm.java @@ -0,0 +1,48 @@ +/** + * SchedulingAlgorithm.java + */ +package com.com1032.assignment; + +/** + * Enumeration of scheduling algorithms. + * + * Preemptive: Might temporarily interrupt the process scheduled to resume it later. + * + * Non-Preemptive: Process scheduled does not stop until it is completed. + * + * @author felipedabrantes + * + */ +public enum SchedulingAlgorithm { + + /**First-In-First-Out.*/ + FIFO(false), + /**Shortest Process First.*/ + SPF(false), + /**Shortest Remaining Time First.*/ + SRTF(true), + /**Round Robin.*/ + RR(true); + + + /**True if algorithm is preemptive.*/ + private boolean preemptive; + + + /** + * Constructor. + * + * @param preemptive or not. + */ + private SchedulingAlgorithm(boolean preemptive) { + this.preemptive = preemptive; + } + + + /** + * @return preemptive or not. + */ + public boolean getPreemptive() { + return this.preemptive; + } +}