/// <summary> /// Get an individual pcb from the scheduler by id /// </summary> /// <param name="id">Id of the pcb</param> /// <returns></returns> public ProcessControlBlock GetPcb(int id) { foreach (KeyValuePair <string, ExecutionQueue> item in _ioDictionary) { foreach (ProcessControlBlock pcb in item.Value.Pcbs) { if (pcb.PId == id) { //copy the pcb and remove it from the queue ProcessControlBlock p = pcb; item.Value.Pcbs.Remove(pcb); //remove the queue from the list if it is empty if (item.Value.IsEmpty()) { _ioDictionary.Remove(item.Key); } return(p); } } } return(null); }
/// <summary> /// Add a pcb to the queue. The order will depend on which scheduling algorithm is selected /// </summary> /// <param name="pcb">Pcb to be inserted</param> public void EnQueue(ProcessControlBlock pcb) { this.Pcbs.Add(pcb); if (IsShortestJobFirst) { this.Pcbs = this.Pcbs.OrderBy(p => p.TotalCyclesNeeded).ToList(); //OrderBy(o => o.OrderDate).ToList(); } }
/// <summary> /// Remove and return the pcb on the top of the queue /// </summary> /// <returns>Pcb next in line</returns> public ProcessControlBlock DeQueue() { ProcessControlBlock process = this.Pcbs[0]; this.Pcbs.RemoveAt(0); if (IsShortestJobFirst) { this.Pcbs = this.Pcbs.OrderBy(p => p.TotalCyclesNeeded).ToList(); } return(process); }
/// <summary> /// Add a new pcb to the os. Scheduler decides where to put it based on the currernt scheduling algorithm /// </summary> /// <param name="pcb"></param> public void AddNewPCB(ProcessControlBlock pcb) { JobCount++; this._os.Gui.UpdateTotalJobs(JobCount); if (this._os.Settings.SchedulingAlgorithm == SchedulingAlgorithm.RoundRobin || this._os.Settings.SchedulingAlgorithm == SchedulingAlgorithm.FirstComeFirstServe) { this.AddPcbRoundRobin(pcb); } else if (this._os.Settings.SchedulingAlgorithm == SchedulingAlgorithm.ShortestJobFirst) { this.AddPcbShortestJobFirst(pcb); } }
/// <summary> /// Checks if an individual pc is in the scheduler /// </summary> /// <param name="pcb"></param> /// <returns></returns> public bool IsInIoScheduler(ProcessControlBlock pcb) { foreach (KeyValuePair <string, ExecutionQueue> item in _ioDictionary) { foreach (ProcessControlBlock p in item.Value.Pcbs) { if (p.PId == pcb.PId) { return(true); } } } return(false); }
/// <summary> /// Adds a pcb to the system when using round robin scheduling /// </summary> /// <param name="pcb"></param> public void AddPcbRoundRobin(ProcessControlBlock pcb) { var canAdd = this.Memory.CanAllocate(pcb.MemoryRequirement); //add PCB to ready queue if (canAdd) { pcb.State = State.NEW; this.ReadyQueue.EnQueue(pcb); this.Memory.AssignMemory(pcb.MemoryRequirement); } else { // add PCB to waiting queue pcb.State = State.NEW; WaitingQueue.EnQueue(pcb); this._os.Gui.UpdateWaitingQueueLog(); } }
/// <summary> /// Handles events and makes takes the corresponding actions /// </summary> /// <param name="ecb"></param> public void HandleEvent(EventControlBlock ecb) { switch (ecb.Type) { case EventType.ReleaseIO: //get the pcb from the ioscheduler ProcessControlBlock pcb = this.IoScheduler.GetPcb(ecb.PcbId); //move it back to the ready queue this.Scheduler.ReadyQueue.EnQueue(pcb); this.Gui.UpdateIoQueueLog(); this.Gui.UpdateReadyQueueLog(); //updateUI = true; break; case EventType.ContextSwitch: this.Scheduler.ContextSwitch(); this.Scheduler.UpdateReadyQueue(); //this.gui.UpdateCurrentPCBTable(this.cpu.currentPcb.ToString()); this.Gui.UpdateReadyQueueLog(); this.Gui.UpdateAllocatedMemoryLabel(this.AllocatedMemory); this.Gui.UpdateAvgWaitTime(this.GetAvgWaitTimes(), this.Scheduler.FinishedPcbs.Count); break; case EventType.NewShortestFirstPCB: //check if anything in the waiting queue should be moved into the ready queue if (this.Scheduler.WaitingQueue.Size > 0) { var toCheck = this.Scheduler.WaitingQueue.DeQueue(); while (this.UpdateQueues(toCheck) && this.Scheduler.WaitingQueue.Size > 0) { toCheck = this.Scheduler.WaitingQueue.DeQueue(); } } this.Gui.UpdateWaitingQueueLog(); break; case EventType.Done: this.UserInterrupt = true; break; } }
/// <summary> /// Adds pcb to the appropriate device queue. If a queue doesnt exist for it create one. /// </summary> /// <param name="ioDevice"></param> /// <param name="pcb"></param> public void ScheduleIo(string ioDevice, ProcessControlBlock pcb) { //log the io request pcb.IoRequestsPerformed++; //add the io to its queue if it exists, else create a new queue and it if (_ioDictionary.ContainsKey(ioDevice)) { _ioDictionary[ioDevice].EnQueue(pcb); } else { ExecutionQueue newQ = new ExecutionQueue(); newQ.EnQueue(pcb); _ioDictionary.Add(ioDevice, newQ); } this._os.Gui.UpdateIoQueueLog(); }
/// <summary> /// Removes a pcb from the scheduler /// </summary> /// <param name="pcb"></param> /// <returns></returns> public ProcessControlBlock RemoveFromIoScheduler(ProcessControlBlock pcb) { ProcessControlBlock x; foreach (KeyValuePair <string, ExecutionQueue> item in _ioDictionary) { bool found = false; for (int i = 0; i < item.Value.Pcbs.Count; i++) { if (item.Value.Pcbs[i].PId == pcb.PId) { x = item.Value.Pcbs[i]; item.Value.Pcbs.RemoveAt(i); return(x); } } } throw new NullReferenceException(); }
/// <summary> /// Load the program in and assign it to whichever queue is appropriate /// </summary> /// <param name="filename">Name of the file(program) to load</param> /// <returns></returns> public async Task <ProcessControlBlock> LoadFile(string filename) { try { var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///program_files/" + filename)); using (var inputStream = await file.OpenReadAsync()) using (var classicStream = inputStream.AsStreamForRead()) using (var streamReader = new StreamReader(classicStream)) { var counter = 0; int memRequirement = 0; List <Operation> operations = new List <Operation>(); while (streamReader.Peek() >= 0) { if (counter == 0) { memRequirement = Convert.ToInt32(streamReader.ReadLine()); } else { operations.Add(convertLineToOperation(streamReader.ReadLine())); } counter++; } ProcessControlBlock newProcess = new ProcessControlBlock(State.NEW, memRequirement, operations); newProcess.PId = this._idCount; this._idCount++; return(newProcess); } } catch (System.IO.FileNotFoundException e) { Debug.WriteLine(e.Message); return(null); } }
/// <summary> /// Decides which queue a pcb goes in in shortest job first mode /// </summary> /// <param name="pcb"></param> /// <returns></returns> public bool UpdateQueues(ProcessControlBlock pcb) { // get a side list of all pcbs in memory List <ProcessControlBlock> allInMemory = new List <ProcessControlBlock>(); allInMemory.Add(pcb); //add anything in cpu to temp list if (this.Cpu.CurrentPcb != null) { allInMemory.Add(this.Cpu.CurrentPcb); } //add all pcbs in ready queue to temp list foreach (ProcessControlBlock p in this.Scheduler.ReadyQueue.Pcbs) { allInMemory.Add(p); } //add all io to temp list foreach (ProcessControlBlock p in this.IoScheduler.GetAllPcBs()) { allInMemory.Add(p); } //order everything in the list by number of cc's required allInMemory = allInMemory.OrderBy(p => p.TotalCyclesNeeded).ToList(); //remove everything below the new pcb in the queue and see if it would fit in memory List <ProcessControlBlock> removed = new List <ProcessControlBlock>(); while (pcb.PId != allInMemory[allInMemory.Count - 1].PId && this.Helper(allInMemory) > this.Settings.MemorySize) { removed.Add(allInMemory[allInMemory.Count - 1]); allInMemory.RemoveAt(allInMemory.Count - 1); } //add up the memory in the temp array int memory = 0; foreach (ProcessControlBlock block in allInMemory) { memory += block.MemoryRequirement; } //if the new pcb will fit in the queue actually do the stuff if (memory <= this.Settings.MemorySize && removed.Count > 0) { foreach (ProcessControlBlock block in removed) { //if the pcb to be removed was in the io scheduler move it to the waiting queue if (this.IoScheduler.IsInIoScheduler(block)) { ProcessControlBlock pcbFromIo = this.IoScheduler.RemoveFromIoScheduler(block); this.Scheduler.Memory.FreeMemory(pcbFromIo.MemoryRequirement); this.Scheduler.WaitingQueue.EnQueue(pcbFromIo); } //if the pcb to be removed is in the cpu move it to the waiting queue and create an event to switch context else if (this.Cpu.CurrentPcb != null && this.Cpu.CurrentPcb.PId == pcb.PId) { this.Scheduler.WaitingQueue.EnQueue(this.Cpu.CurrentPcb); this.Scheduler.Memory.FreeMemory(this.Cpu.CurrentPcb.MemoryRequirement); this.Cpu.CurrentPcb = null; this.InterruptProcessor.CreateAndAddEvent(EventType.ContextSwitch); } // the pcb has to be in the ready queue so move it to the waiting queue else { for (int j = 0; j < this.Scheduler.ReadyQueue.Pcbs.Count; j++) { if (this.Scheduler.ReadyQueue.Pcbs[j].PId == block.PId) { this.Scheduler.WaitingQueue.EnQueue(block); this.Scheduler.ReadyQueue.Pcbs.RemoveAt(j); this.Scheduler.Memory.FreeMemory(block.MemoryRequirement); } } } } //space has been freed up for the new pcb to be added this.Scheduler.ReadyQueue.EnQueue(pcb); this.Scheduler.Memory.AssignMemory(pcb.MemoryRequirement); this.Gui.UpdateIoQueueLog(); this.Gui.UpdateReadyQueueLog(); this.Gui.UpdateWaitingQueueLog(); return(true); } else if (memory <= this.Settings.MemorySize && removed.Count == 0) { this.Scheduler.ReadyQueue.EnQueue(pcb); this.Scheduler.Memory.AssignMemory(pcb.MemoryRequirement); this.Gui.UpdateReadyQueueLog(); return(true); } else { this.Scheduler.WaitingQueue.EnQueue(pcb); this.Gui.UpdateWaitingQueueLog(); return(false); } }
/// <summary> /// Executes current operation in the current pcb /// </summary> public void ExecuteOperation() { if (CurrentPcb == null) { return; } //if the program is new flag it as running since its in the cpu and about to be executed if (this.CurrentPcb.State == State.NEW) { this.CurrentPcb.State = State.RUN; } int remainingCycles = this.CurrentPcb.DecrementOperationClock(); switch (this.CurrentPcb.CurrentOperation.Type) { case OperationType.CALCULATE: //this.gui.PrintToLog("cpu executing calc"); //this.gui.PrintToLog(remainingCycles + " cycles remaing for calc"); if (this.CurrentPcb.CurrentOperation.Cycles == 0) { this.CurrentPcb.SetNextCommand(); } break; case OperationType.IO: if (this.CurrentPcb.State == State.RUN) { this.CurrentPcb.State = State.WAIT; this.CurrentPcb.CurrentOperation.Cycles++; //add the io cycle back since this cycle was wasted moving to io q this._os.IoScheduler.ScheduleIo(this.CurrentPcb.CurrentOperation.IoType, CurrentPcb); this.CurrentPcb = null; this._os.Gui.UpdateCurrentPCBTable(""); } else { this.CurrentPcb.SetNextCommand(); //put the pcb back in a run state this.CurrentPcb.State = State.RUN; } break; case OperationType.YIELD: this.CurrentPcb.SetNextCommand(); //if the yield is the last command discard it and create a cont switch event this._os.InterruptProcessor.CreateAndAddEvent(EventType.ContextSwitch); break; case OperationType.OUT: this._os.Gui.LogMessageToConsole(this.CurrentPcb.ToString()); this.CurrentPcb.SetNextCommand(); break; } //if the process is exiting create a context switch event to notify the scheduler to switch it out if (CurrentPcb != null && CurrentPcb.State == State.EXIT) { //remove from system and free memory this._os.Scheduler.Memory.FreeMemory(CurrentPcb.MemoryRequirement); this._os.Scheduler.FinishedPcbs.Add(CurrentPcb); //your journey is over little buddy. Live long and prosper... this.CurrentPcb = null; //discard currentpcb this._os.InterruptProcessor.CreateAndAddEvent(EventType.ContextSwitch); } }
/// <summary> /// Resets the cpu /// </summary> public void Reset() { this.Clock.Reset(); this.CurrentPcb = null; }
/// <summary> /// Adds a pcb to the system when using sjf scheduling /// </summary> /// <param name="pcb"></param> public void AddPcbShortestJobFirst(ProcessControlBlock pcb) { //add the pcb to the waiting queue and create an event to check if it should be moved into the ready queue this.WaitingQueue.EnQueue(pcb); this._os.InterruptProcessor.CreateAndAddEvent(EventType.NewShortestFirstPCB); }
public void InsertPCB(ProcessControlBlock pcb) { throw new NotImplementedException(); }