added process scheduling algorithms
This commit is contained in:
		
							
								
								
									
										20
									
								
								process-scheduling/algorithms/fcfs.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								process-scheduling/algorithms/fcfs.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| #import "utils.typ": * | ||||
|  | ||||
| #let FCFS(tasks) = { | ||||
|   let (processes, tasks) = _prepare-tasks(tasks) | ||||
|  | ||||
|   let cur-time = 0 | ||||
|   for task in tasks { | ||||
|     let proc = processes.at(task.id) | ||||
|     if task.arrival < cur-time { | ||||
|       proc.events.push((READY, task.arrival)) | ||||
|     } | ||||
|     let wait-time = calc.max(0, cur-time - task.arrival) | ||||
|     proc.events.push((RUNNING, task.arrival + wait-time)) | ||||
|     cur-time = task.arrival + task.duration + wait-time | ||||
|     proc.events.push((TERMINATED, cur-time)) | ||||
|     processes.at(task.id) = proc | ||||
|   } | ||||
|  | ||||
|   return _prepare-output(processes) | ||||
| } | ||||
							
								
								
									
										149
									
								
								process-scheduling/algorithms/pr.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								process-scheduling/algorithms/pr.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| #import "utils.typ": * | ||||
|  | ||||
| #let prio-add(list, task) = { | ||||
|   let left-i = list.rev() | ||||
|                    .position(t => t.priority > task.priority) | ||||
|    | ||||
|   if left-i == none { | ||||
|     left-i = list.rev() | ||||
|                  .position(t => t.arrival > task.arrival) | ||||
|   } | ||||
|  | ||||
|   let i = if left-i == none { | ||||
|     0 | ||||
|   } else { | ||||
|     list.len() - left-i | ||||
|   } | ||||
|   if task.pid == 7 { | ||||
|     let dbg = (list, task, i) | ||||
|   } | ||||
|   list.insert(i, task) | ||||
|   return list | ||||
| } | ||||
|  | ||||
| #let Pr(tasks, ctx-switch: 1) = { | ||||
|   let (processes, tasks) = _prepare-tasks(tasks) | ||||
|   tasks = tasks.rev() | ||||
|  | ||||
|   let n-tasks = tasks.len() | ||||
|   let cur-time = 0 | ||||
|   let current = none | ||||
|   let finished = 0 | ||||
|   let prio-list = () | ||||
|   let logs = () | ||||
|   while finished != n-tasks { | ||||
|     let log = "Current time: " + str(cur-time) + " / " | ||||
|     if (current != none) { | ||||
|         log += "Current: " + str(current.pid) + " / " | ||||
|     } else { | ||||
|         log += "Current: none / " | ||||
|     } | ||||
|     if (tasks.len() != 0) { | ||||
|         log += "Next: " + str(tasks.last().pid) | ||||
|     } else { | ||||
|         log += "Next: none" | ||||
|     } | ||||
|     logs.push(log) | ||||
|  | ||||
|     if current == none { | ||||
|       current = tasks.pop() | ||||
|       logs.push("No running process: running " + str(current.pid)) | ||||
|       current.state = RUNNING | ||||
|       processes.at(current.id).events.push((RUNNING, current.arrival)) | ||||
|  | ||||
|     } else if tasks.len() != 0 { | ||||
|       logs.push(log-list(prio-list)) | ||||
|       logs.push("Processing next process (" + str(tasks.last().pid) + ")") | ||||
|       tasks.last().state = READY | ||||
|  | ||||
|       while current != none and cur-time + current.remaining <= tasks.last().arrival { | ||||
|         logs.push("  Process " + str(current.pid) + " finished before next") | ||||
|         if current.state != RUNNING { | ||||
|           processes.at(current.id).events.push((RUNNING, cur-time)) | ||||
|         } | ||||
|         current.state = TERMINATED | ||||
|         cur-time += current.remaining | ||||
|         current.remaining = 0 | ||||
|         processes.at(current.id).events.push((TERMINATED, cur-time)) | ||||
|         finished += 1 | ||||
|         if prio-list.len() != 0 { | ||||
|           current = prio-list.pop() | ||||
|         } else { | ||||
|           current = none | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if current != none { | ||||
|         logs.push("Removing time from current process") | ||||
|         if current.state != RUNNING and tasks.last().arrival > cur-time { | ||||
|           processes.at(current.id).events.push((RUNNING, cur-time)) | ||||
|           current.state = RUNNING | ||||
|           //processes.at(current.id).events.push((READY, tasks.last().arrival)) | ||||
|         } | ||||
|         current.remaining -= tasks.last().arrival - cur-time | ||||
|       } | ||||
|       if tasks.last().arrival > cur-time { | ||||
|         cur-time = tasks.last().arrival | ||||
|       } | ||||
|       tasks.last().state = READY | ||||
|  | ||||
|       if current == none { | ||||
|         current = tasks.pop() | ||||
|         logs.push("Queue is empty, running next process " + str(current.pid)) | ||||
|         current.state = RUNNING | ||||
|         processes.at(current.id).events.push((RUNNING, cur-time)) | ||||
|       } else if tasks.last().priority < current.priority { | ||||
|         logs.push("Next process (" + str(tasks.last().pid) + ") has higher priority") | ||||
|         if current.state != READY { | ||||
|           processes.at(current.id).events.push((READY, cur-time)) | ||||
|         } | ||||
|         if current.state == RUNNING { | ||||
|           logs.push("  Preempting current process (" + str(current.pid) +")") | ||||
|           processes.at(tasks.last().id).events.push((READY, cur-time)) | ||||
|           cur-time += ctx-switch | ||||
|         } | ||||
|         if current.state == RUNNING { | ||||
|           current.state = READY | ||||
|           prio-list = prio-add(prio-list, current) | ||||
|         } else { | ||||
|           prio-list.push(current) | ||||
|         } | ||||
|  | ||||
|         current = tasks.pop() | ||||
|  | ||||
|         current.state = RUNNING | ||||
|         processes.at(current.id).events.push((RUNNING, cur-time)) | ||||
|       } else { | ||||
|         logs.push("Adding next process (" + str(tasks.last().pid) + ") to list") | ||||
|         processes.at(tasks.last().id).events.push((READY, cur-time)) | ||||
|         prio-list = prio-add(prio-list, tasks.pop()) | ||||
|       } | ||||
|       if current != none { | ||||
|         if current.state != RUNNING { | ||||
|           processes.at(current.id).events.push((RUNNING, cur-time)) | ||||
|         } | ||||
|         current.state = RUNNING | ||||
|       } | ||||
|     } else { | ||||
|       logs.push("No new processes, emptying queue") | ||||
|       logs.push(log-list(prio-list)) | ||||
|       while current != none { | ||||
|         logs.push("Completing process " + str(current.pid)) | ||||
|         current.state = TERMINATED | ||||
|         cur-time += current.remaining | ||||
|         current.remaining = 0 | ||||
|         processes.at(current.id).events.push((TERMINATED, cur-time)) | ||||
|         finished += 1 | ||||
|         if prio-list.len() != 0 { | ||||
|           current = prio-list.pop() | ||||
|           current.state = RUNNING | ||||
|           processes.at(current.id).events.push((RUNNING, cur-time)) | ||||
|         } else { | ||||
|           current = none | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return _prepare-output(processes) | ||||
| } | ||||
							
								
								
									
										81
									
								
								process-scheduling/algorithms/rr.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								process-scheduling/algorithms/rr.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| #import "utils.typ": * | ||||
|  | ||||
| #let RR(tasks, quantum: 2, ctx-switch: 1) = { | ||||
|   let (processes, tasks) = _prepare-tasks(tasks) | ||||
|  | ||||
|   let n-tasks = tasks.len() | ||||
|   let cur-time = 0 | ||||
|   let current = none | ||||
|   let finished = 0 | ||||
|   let running = 0 | ||||
|   let last-running = none | ||||
|   let logs = () | ||||
|   let failsafe = 0 | ||||
|  | ||||
|   while (failsafe < 160 and finished < n-tasks) { | ||||
|     failsafe += 1 | ||||
|     for (i, p) in tasks.enumerate() { | ||||
|       if p.state == TERMINATED { | ||||
|         continue | ||||
|       } | ||||
|       logs.push("Current time: " + str(cur-time) + ", pid: " + str(p.pid)) | ||||
|  | ||||
|       if p.state == UNBORN { | ||||
|         if p.arrival <= cur-time { | ||||
|           p.state = READY | ||||
|           if running == 0 { | ||||
|             processes.at(p.id).events.push((RUNNING, p.arrival)) | ||||
|           } else { | ||||
|             processes.at(p.id).events.push((READY, p.arrival)) | ||||
|           } | ||||
|           running += 1 | ||||
|           if last-running != none { | ||||
|             logs.push("Preempting last running process (current time: " + str(cur-time) + ", pid: " + str(last-running.pid) + ")") | ||||
|             processes.at(last-running.id).events.push((READY, cur-time)) | ||||
|             cur-time += ctx-switch | ||||
|           } | ||||
|           logs.push("Process " + str(p.pid) + " is now ready") | ||||
|           logs.push("Running processes: " + str(running)) | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if p.state == READY { | ||||
|         //if running > 1 { | ||||
|         if last-running == none or last-running.pid != p.pid { | ||||
|           processes.at(p.id).events.push((RUNNING, cur-time)) | ||||
|         } | ||||
|         p.remaining -= quantum | ||||
|         cur-time += quantum | ||||
|         last-running = p | ||||
|         logs.push("Executing quantum for process " + str(p.pid) + ", remaining time " + str(p.remaining)) | ||||
|  | ||||
|         if p.remaining <= 0 { | ||||
|           logs.push("  Process has finished") | ||||
|           processes.at(p.id).events.push((TERMINATED, cur-time + p.remaining)) | ||||
|           p.remaining = 0 | ||||
|           p.state = TERMINATED | ||||
|           last-running = none | ||||
|           finished += 1 | ||||
|           running -= 1 | ||||
|          | ||||
|         } else if running > 1 { | ||||
|           logs.push("  Preempting process (current time: " + str(cur-time) + ", pid: " + str(p.pid) + ")") | ||||
|           last-running = none | ||||
|           processes.at(p.id).events.push((READY, cur-time)) | ||||
|           cur-time += ctx-switch | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       tasks.at(i) = p | ||||
|     } | ||||
|     if finished < n-tasks and running == 0 { | ||||
|       cur-time += 1 | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   let f = failsafe | ||||
|  | ||||
|   //let logs2 = logs.slice(-60) | ||||
|  | ||||
|   return _prepare-output(processes) | ||||
| } | ||||
							
								
								
									
										155
									
								
								process-scheduling/algorithms/srtf.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								process-scheduling/algorithms/srtf.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | ||||
| #import "utils.typ": * | ||||
|  | ||||
| #let remtime-add(list, task) = { | ||||
|   let left-i = list.rev() | ||||
|                    .position(t => t.remaining > task.remaining) | ||||
|    | ||||
|   if left-i == none { | ||||
|     left-i = list.rev() | ||||
|                  .position(t => t.arrival > task.arrival) | ||||
|   } | ||||
|  | ||||
|   let i = if left-i == none { | ||||
|     0 | ||||
|   } else { | ||||
|     list.len() - left-i | ||||
|   } | ||||
|   if task.pid == 7 { | ||||
|     let dbg = (list, task, i) | ||||
|   } | ||||
|   list.insert(i, task) | ||||
|   return list | ||||
| } | ||||
|  | ||||
| #let SRTF(tasks, ctx-switch: 1) = { | ||||
|   let (processes, tasks) = _prepare-tasks(tasks) | ||||
|   tasks = tasks.rev() | ||||
|  | ||||
|   let n-tasks = tasks.len() | ||||
|   let cur-time = 0 | ||||
|   let current = none | ||||
|   let finished = 0 | ||||
|   let remtime-list = () | ||||
|   let logs = () | ||||
|  | ||||
|   while finished != n-tasks { | ||||
|     let log = "Current time: " + str(cur-time) + " / " | ||||
|     if (current != none) { | ||||
|         log += "Current: " + str(current.pid) + " / " | ||||
|     } else { | ||||
|         log += "Current: none / " | ||||
|     } | ||||
|     if (tasks.len() != 0) { | ||||
|         log += "Next: " + str(tasks.last().pid) | ||||
|     } else { | ||||
|         log += "Next: none" | ||||
|     } | ||||
|     logs.push(log) | ||||
|  | ||||
|     if current == none { | ||||
|       current = tasks.pop() | ||||
|       logs.push("No running process: running " + str(current.pid)) | ||||
|       current.state = RUNNING | ||||
|       processes.at(current.id).events.push((RUNNING, current.arrival)) | ||||
|  | ||||
|     } else if tasks.len() != 0 { | ||||
|       logs.push(log-list(remtime-list)) | ||||
|       logs.push("Processing next process (" + str(tasks.last().pid) + ")") | ||||
|       tasks.last().state = READY | ||||
|       let delta = tasks.last().arrival - cur-time | ||||
|  | ||||
|       while current != none and current.remaining <= delta { | ||||
|         logs.push("  Process " + str(current.pid) + " finished before next") | ||||
|         if current.state != RUNNING { | ||||
|           processes.at(current.id).events.push((RUNNING, cur-time)) | ||||
|         } | ||||
|         current.state = TERMINATED | ||||
|         cur-time += current.remaining | ||||
|         delta = tasks.last().arrival - cur-time | ||||
|         current.remaining = 0 | ||||
|         processes.at(current.id).events.push((TERMINATED, cur-time)) | ||||
|         finished += 1 | ||||
|         if remtime-list.len() != 0 { | ||||
|           current = remtime-list.pop() | ||||
|         } else { | ||||
|           current = none | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if current != none { | ||||
|         logs.push("Removing time from current process") | ||||
|         if current.state != RUNNING and tasks.last().arrival > cur-time { | ||||
|           processes.at(current.id).events.push((RUNNING, cur-time)) | ||||
|           current.state = RUNNING | ||||
|           //processes.at(current.id).events.push((READY, tasks.last().arrival)) | ||||
|         } | ||||
|         current.remaining -= delta | ||||
|         logs.push("  New remaining time " + str(current.remaining)) | ||||
|       } | ||||
|       if tasks.last().arrival > cur-time { | ||||
|         cur-time = tasks.last().arrival | ||||
|       } | ||||
|       tasks.last().state = READY | ||||
|  | ||||
|       if current == none { | ||||
|         current = tasks.pop() | ||||
|         logs.push("Queue is empty, running next process " + str(current.pid)) | ||||
|         current.state = RUNNING | ||||
|         processes.at(current.id).events.push((RUNNING, cur-time)) | ||||
|        | ||||
|       } else if tasks.last().remaining < current.remaining { | ||||
|         logs.push("Next process (" + str(tasks.last().pid) + ") has shorter remaining time") | ||||
|         if current.state != READY { | ||||
|           processes.at(current.id).events.push((READY, cur-time)) | ||||
|         } | ||||
|         if current.state == RUNNING { | ||||
|           logs.push("  Preempting current process (" + str(current.pid) +")") | ||||
|           current.remaining -= tasks.last().arrival - cur-time | ||||
|           processes.at(tasks.last().id).events.push((READY, cur-time)) | ||||
|           cur-time += ctx-switch | ||||
|         } | ||||
|         if current.state == RUNNING { | ||||
|           current.state = READY | ||||
|           remtime-list = remtime-add(remtime-list, current) | ||||
|         } else { | ||||
|           remtime-list.push(current) | ||||
|         } | ||||
|  | ||||
|         current = tasks.pop() | ||||
|  | ||||
|         current.state = RUNNING | ||||
|         processes.at(current.id).events.push((RUNNING, cur-time)) | ||||
|       } else { | ||||
|         logs.push("Adding next process (" + str(tasks.last().pid) + ") to list") | ||||
|         processes.at(tasks.last().id).events.push((READY, cur-time)) | ||||
|         remtime-list = remtime-add(remtime-list, tasks.pop()) | ||||
|       } | ||||
|       if current != none { | ||||
|         if current.state != RUNNING { | ||||
|           processes.at(current.id).events.push((RUNNING, cur-time)) | ||||
|         } | ||||
|         current.state = RUNNING | ||||
|       } | ||||
|     } else { | ||||
|       logs.push("No new processes, emptying queue") | ||||
|       logs.push(log-list(remtime-list)) | ||||
|       while current != none { | ||||
|         logs.push("Completing process " + str(current.pid)) | ||||
|         current.state = TERMINATED | ||||
|         cur-time += current.remaining | ||||
|         current.remaining = 0 | ||||
|         processes.at(current.id).events.push((TERMINATED, cur-time)) | ||||
|         finished += 1 | ||||
|         if remtime-list.len() != 0 { | ||||
|           current = remtime-list.pop() | ||||
|           current.state = RUNNING | ||||
|           processes.at(current.id).events.push((RUNNING, cur-time)) | ||||
|         } else { | ||||
|           current = none | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return _prepare-output(processes) | ||||
| } | ||||
							
								
								
									
										30
									
								
								process-scheduling/algorithms/utils.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								process-scheduling/algorithms/utils.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| #import "../utils.typ": UNBORN, READY, RUNNING, TERMINATED | ||||
|  | ||||
| #let _prepare-tasks(tasks) = { | ||||
|   let processes = (:) | ||||
|   for (i, task) in tasks.enumerate() { | ||||
|     let id = str(i) | ||||
|     task.insert("id", id) | ||||
|     task.insert("state", UNBORN) | ||||
|     processes.insert(id, (task: task, events: ())) | ||||
|     tasks.at(i) = task | ||||
|   } | ||||
|   return (processes, tasks) | ||||
| } | ||||
|  | ||||
| #let _prepare-output(processes) = { | ||||
|   return processes.values() | ||||
|                   .map(p => ( | ||||
|                     pid: p.task.pid, | ||||
|                     priority: p.task.priority, | ||||
|                     events: p.events | ||||
|                   )) | ||||
|                   .sorted(key: t => t.pid) | ||||
| } | ||||
|  | ||||
| #let log-list(list) = { | ||||
|   if list == none or list.len() == 0 { | ||||
|     return "queue:" | ||||
|   } | ||||
|   return "queue: " + list.map(t => str(t.pid)).join(", ") | ||||
| } | ||||
		Reference in New Issue
	
	Block a user