///|
pub(all) suberror ModelError {
InvalidModel
ResourceLimit
}
// Array order is decreasing priority. All times use one caller-chosen unit.
///|
pub(all) struct Task {
name : String
cost : Int32
period : Int32
deadline : Int32
jitter : Int32
blocking : Int32
}
///|
pub(all) struct Response {
name : String
bound : Int64
meets_deadline : Bool
iterations : Array[Int64]
}
///|
fn validate(tasks : Array[Task]) -> Unit raise ModelError {
if tasks.is_empty() || tasks.length() > 64 {
raise InvalidModel
}
for i in 0.. 1000000 ||
t.deadline <= 0 ||
t.deadline > t.period ||
t.jitter < 0 ||
t.jitter > t.deadline ||
t.blocking < 0 ||
t.blocking > 1000000 {
raise InvalidModel
}
if t.cost > 1000000 {
raise InvalidModel
}
for j in 0.. Array[Response] raise ModelError {
validate(tasks)
let out : Array[Response] = []
for i in 0.. task.deadline.to_int64() {
break
}
let mut next = base
for j in 0.. DemandWitness? raise ModelError {
validate(tasks)
if horizon <= 0 || horizon > 1000000 {
raise ResourceLimit
}
for t in tasks {
if t.jitter != 0 || t.blocking != 0 {
raise InvalidModel
}
}
for time in 1..<(horizon + 1) {
let mut demand = 0L
for t in tasks {
if time >= t.deadline {
demand += ((time - t.deadline) / t.period + 1).to_int64() *
t.cost.to_int64()
}
}
if demand > time.to_int64() {
return Some({ interval: time, demand, })
}
}
None
}
///|
pub(all) struct Tick {
time : Int32
task : Int32 // -1 means idle
}
///|
pub(all) struct Simulation {
ticks : Array[Tick]
missed_tasks : Array[Int32]
}
// Synchronous periodic releases, fixed priority, no jitter/blocking.
// This is a concrete finite trace, never an all-time schedulability proof.
///|
pub fn simulate(
tasks : Array[Task],
horizon : Int32,
) -> Simulation raise ModelError {
validate(tasks)
if horizon <= 0 || horizon > 100000 {
raise ResourceLimit
}
for t in tasks {
if t.jitter != 0 || t.blocking != 0 {
raise InvalidModel
}
}
let remaining = Array::make(tasks.length(), 0)
let due = Array::make(tasks.length(), 0)
let misses : Array[Int32] = []
let ticks : Array[Tick] = []
for time in 0..<(horizon + 1) {
for i in 0.. 0 && due[i] == time && !misses.contains(i) {
misses.push(i)
}
}
if time == horizon {
break
}
for i in 0.. 0 {
return { ticks, missed_tasks: misses, }
}
remaining[i] = tasks[i].cost
due[i] = time + tasks[i].deadline
}
}
let mut chosen = -1
for i in 0.. 0 {
chosen = i
break
}
}
if chosen >= 0 {
remaining[chosen] -= 1
}
ticks.push({ time, task: chosen, })
}
{ ticks, missed_tasks: misses, }
}