added process scheduling algorithms
This commit is contained in:
		
							
								
								
									
										4
									
								
								process-scheduling/algorithms.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								process-scheduling/algorithms.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| #import "algorithms/fcfs.typ": FCFS | ||||
| #import "algorithms/pr.typ": Pr | ||||
| #import "algorithms/srtf.typ": SRTF | ||||
| #import "algorithms/rr.typ": RR | ||||
							
								
								
									
										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(", ") | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								process-scheduling/main.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								process-scheduling/main.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										40
									
								
								process-scheduling/main.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								process-scheduling/main.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| #import "utils.typ": task, display-processes, RUNNING | ||||
| #import "algorithms.typ": FCFS, Pr, SRTF, RR | ||||
|  | ||||
| #set document(title: "Process scheduling algorithms") | ||||
| #set page(height: auto) | ||||
| #set text(font: "Source Sans 3") | ||||
|  | ||||
| #let tasks = { | ||||
|   task(1, 0, 10, 3) | ||||
|   task(2, 20, 40, 2) | ||||
|   task(3, 30, 20, 2) | ||||
|   task(4, 60, 10, 3) | ||||
|   task(5, 80, 30, 1) | ||||
|   task(6, 90, 20, 1) | ||||
|   task(7, 100, 50, 3) | ||||
|   task(8, 130, 30, 2) | ||||
|   task(9, 180, 10, 3) | ||||
|   task(10, 200, 60, 1) | ||||
| } | ||||
|  | ||||
| #text(size: 1.2em)[*Process scheduling algorithms*] | ||||
| #figure( | ||||
|   display-processes(..FCFS(tasks)), | ||||
|   caption: [Process scheduling: FCFS] | ||||
| ) | ||||
| #pagebreak() | ||||
| #figure( | ||||
|   display-processes(..Pr(tasks), display-priorities: true), | ||||
|   caption: [Process scheduling: Pr] | ||||
| ) | ||||
| #pagebreak() | ||||
| #figure( | ||||
|   display-processes(..SRTF(tasks), display-durations: (RUNNING,)), | ||||
|   caption: [Process scheduling: SRTF] | ||||
| ) | ||||
| #pagebreak() | ||||
| #figure( | ||||
|   display-processes(..RR(tasks)), | ||||
|   caption: [Process scheduling: RR] | ||||
| ) | ||||
							
								
								
									
										155
									
								
								process-scheduling/utils.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								process-scheduling/utils.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | ||||
| #import "@preview/cetz:0.3.1": canvas, draw | ||||
|  | ||||
|  | ||||
| #let UNBORN = 0 | ||||
| #let READY = 1 | ||||
| #let RUNNING = 2 | ||||
| #let TERMINATED = 3 | ||||
|  | ||||
| #let colors = ( | ||||
|   none, | ||||
|   gray, | ||||
|   green, | ||||
|   blue.lighten(50%) | ||||
| ) | ||||
|  | ||||
| #let task(pid, arrival, duration, priority) = { | ||||
|   return (( | ||||
|     pid: pid, | ||||
|     arrival: arrival, | ||||
|     duration: duration, | ||||
|     remaining: duration, | ||||
|     priority: priority | ||||
|   ),) | ||||
| } | ||||
|  | ||||
| #let display-processes(width: auto, display-durations: none, display-priorities: false, ..args) = layout(size => { | ||||
|   let processes = args.pos() | ||||
|   processes = processes.map(p => if type(p) == dictionary {p} else {( | ||||
|     pid: p.first(), | ||||
|     priority: if display-priorities {p.at(1)} else {0}, | ||||
|     events: p.slice(if display-priorities {2} else {1}) | ||||
|   )}) | ||||
|   let max-t = calc.max( | ||||
|     ..processes.map( | ||||
|       p => calc.max( | ||||
|         ..p.events.map( | ||||
|           e => e.last() | ||||
|         ) | ||||
|       ) | ||||
|     ) | ||||
|   ) | ||||
|  | ||||
|   let display-durations = if display-durations == none { | ||||
|     () | ||||
|   } else if type(display-durations) == array { | ||||
|     display-durations | ||||
|   } else { | ||||
|     (display-durations,) | ||||
|   } | ||||
|  | ||||
|   let shapes = () | ||||
|   let width = width | ||||
|   if (width == auto) { | ||||
|     width = size.width | ||||
|   } | ||||
|   let y = 0 | ||||
|   for proc in processes { | ||||
|     proc.events.push((TERMINATED, max-t)) | ||||
|     shapes += draw.content( | ||||
|       (0, y - .25), | ||||
|       str(proc.pid), | ||||
|       anchor: "east", | ||||
|       padding: 5pt | ||||
|     ) | ||||
|      | ||||
|     for i in range(proc.events.len() - 1) { | ||||
|       let (state1, t1) = proc.events.at(i) | ||||
|       let (state2, t2) = proc.events.at(i+1) | ||||
|       let x1 = t1 / max-t * width | ||||
|       let x2 = t2 / max-t * width | ||||
|       let y1 = y | ||||
|       let y2 = y - .5 | ||||
|       if (state1 == TERMINATED) { | ||||
|         y1 = y - .2 | ||||
|         y2 = y - .3 | ||||
|       } | ||||
|        | ||||
|       shapes += draw.rect( | ||||
|         (x1, y1), | ||||
|         (x2, y2), | ||||
|         fill: colors.at(state1) | ||||
|       ) | ||||
|  | ||||
|       if i == 0 and display-priorities { | ||||
|         shapes += draw.content( | ||||
|           ((x1 + x2) / 2, (y1 + y2) / 2), | ||||
|           strong(str(proc.priority)), | ||||
|           anchor: "center" | ||||
|         ) | ||||
|       } | ||||
|       if state1 in display-durations { | ||||
|         shapes += draw.content( | ||||
|           ((x1 + x2) / 2, (y1 + y2) / 2), | ||||
|           strong(str(t2 - t1)), | ||||
|           anchor: "center" | ||||
|         ) | ||||
|       } | ||||
|  | ||||
|       if state1 == RUNNING and state2 == READY { | ||||
|         shapes += draw.on-layer(1, draw.circle( | ||||
|           (x2, (y1 + y2)/2), | ||||
|           radius: .1, | ||||
|           fill: red | ||||
|         )) | ||||
|       } | ||||
|     } | ||||
|     y -= 0.5 | ||||
|   } | ||||
|  | ||||
|   let step = calc.pow( | ||||
|     10, | ||||
|     calc.max( | ||||
|       0, | ||||
|       calc.floor( | ||||
|         calc.log( | ||||
|           base: 10, | ||||
|           max-t | ||||
|         ) - 1 | ||||
|       ) | ||||
|     ) | ||||
|   ) | ||||
|   let n-steps = calc.floor(max-t / step) + 1 | ||||
|   for i in range(n-steps) { | ||||
|     let t = i * step | ||||
|     let x = t / max-t * width | ||||
|     shapes += draw.line( | ||||
|       (x, 0), | ||||
|       (x, if calc.rem(i, 2) == 0 {.5} else {.3}), | ||||
|       stroke: black | ||||
|     ) | ||||
|     shapes += draw.on-layer(-1, draw.line( | ||||
|       (x, 0), | ||||
|       (x, -processes.len() * .5), | ||||
|       stroke: ( | ||||
|         dash: (6pt, 4pt), | ||||
|         thickness: 1pt, | ||||
|         paint: gray | ||||
|       ) | ||||
|     )) | ||||
|     if calc.rem(i, 2) == 0 { | ||||
|       shapes += draw.content( | ||||
|         (x, .5), | ||||
|         str(t), | ||||
|         anchor: "south", | ||||
|         padding: 5pt | ||||
|       ) | ||||
|     } | ||||
|   } | ||||
|   shapes += draw.rect( | ||||
|     (0, 0), | ||||
|     (width, -processes.len() * .5) | ||||
|   ) | ||||
|  | ||||
|   canvas(shapes) | ||||
| }) | ||||
		Reference in New Issue
	
	Block a user