#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) }