1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use crate::collections::list::{List, ListLink, ListNode};
use crate::kernel::{Kernel, StoppedExecutingReason};
use crate::platform::chip::Chip;
use crate::process::Process;
use crate::scheduler::{Scheduler, SchedulingDecision};
pub struct CoopProcessNode<'a> {
proc: &'static Option<&'static dyn Process>,
next: ListLink<'a, CoopProcessNode<'a>>,
}
impl<'a> CoopProcessNode<'a> {
pub fn new(proc: &'static Option<&'static dyn Process>) -> CoopProcessNode<'a> {
CoopProcessNode {
proc,
next: ListLink::empty(),
}
}
}
impl<'a> ListNode<'a, CoopProcessNode<'a>> for CoopProcessNode<'a> {
fn next(&'a self) -> &'a ListLink<'a, CoopProcessNode> {
&self.next
}
}
pub struct CooperativeSched<'a> {
pub processes: List<'a, CoopProcessNode<'a>>,
}
impl<'a> CooperativeSched<'a> {
pub const fn new() -> CooperativeSched<'a> {
CooperativeSched {
processes: List::new(),
}
}
}
impl<'a, C: Chip> Scheduler<C> for CooperativeSched<'a> {
fn next(&self, kernel: &Kernel) -> SchedulingDecision {
if kernel.processes_blocked() {
SchedulingDecision::TrySleep
} else {
let mut next = None;
for node in self.processes.iter() {
match node.proc {
Some(proc) => {
if proc.ready() {
next = Some(proc.processid());
break;
}
self.processes.push_tail(self.processes.pop_head().unwrap());
}
None => {
self.processes.push_tail(self.processes.pop_head().unwrap());
}
}
}
SchedulingDecision::RunProcess((next.unwrap(), None))
}
}
fn result(&self, result: StoppedExecutingReason, _: Option<u32>) {
let reschedule = match result {
StoppedExecutingReason::KernelPreemption => true,
_ => false,
};
if !reschedule {
self.processes.push_tail(self.processes.pop_head().unwrap());
}
}
}