added process scheduling algorithms
This commit is contained in:
parent
fe957e03d1
commit
32473b67bc
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)
|
||||||
|
})
|
Loading…
x
Reference in New Issue
Block a user