implement RFCs 147 and 155, etc.

This commit:

- Implements RFC 147: "all functions must be safe"

- Implements RFC 155: "explicit Context parameter"

- Implements the pending breaking change #141: reject assign syntax in `init`
  (which was used to initialize late resources)

- Refactors code generation to make it more readable -- there are no more random
  identifiers in the output -- and align it with the book description of RTFM
  internals.

- Makes the framework hard depend on `core::mem::MaybeUninit` and thus will
  require nightly until that API is stabilized.

- Fixes a ceiling analysis bug where the priority of the system timer was not
  considered in the analysis.

- Shrinks the size of all the internal queues by turning `AtomicUsize` indices
  into `AtomicU8`s.

- Removes the integration with `owned_singleton`.
This commit is contained in:
Jorge Aparicio 2019-04-21 20:02:59 +02:00
parent e6fb2f216f
commit a452700628
11 changed files with 2491 additions and 2331 deletions

View file

@ -190,19 +190,20 @@ pub fn app(app: &App) -> Analysis {
}
// Ceiling analysis of free queues (consumer end point) -- first pass
// Ceiling analysis of ready queues (producer end point)
// Ceiling analysis of ready queues (producer end point) -- first pass
// Also compute more Send-ness requirements
let mut free_queues: HashMap<_, _> = app.tasks.keys().map(|task| (task.clone(), 0)).collect();
let mut ready_queues: HashMap<_, _> = dispatchers.keys().map(|level| (*level, 0)).collect();
let mut free_queues = HashMap::new();
let mut ready_queues = HashMap::new();
for (priority, task) in app.spawn_calls() {
if let Some(priority) = priority {
// Users of `spawn` contend for the to-be-spawned task FREE_QUEUE
let c = free_queues.get_mut(task).expect("BUG: free_queue.get_mut");
// Users of `spawn` contend for the spawnee FREE_QUEUE
let c = free_queues.entry(task.clone()).or_default();
*c = cmp::max(*c, priority);
// Users of `spawn` contend for the spawnee's dispatcher READY_QUEUE
let c = ready_queues
.get_mut(&app.tasks[task].args.priority)
.expect("BUG: ready_queues.get_mut");
.entry(app.tasks[task].args.priority)
.or_default();
*c = cmp::max(*c, priority);
// Send is required when sending messages from a task whose priority doesn't match the
@ -215,16 +216,23 @@ pub fn app(app: &App) -> Analysis {
}
}
// Ceiling analysis of ready queues (producer end point) -- second pass
// Ceiling analysis of free queues (consumer end point) -- second pass
// Ceiling analysis of the timer queue
let mut tq_ceiling = tq_priority;
for (priority, task) in app.schedule_calls() {
// the system timer handler contends for the spawnee's dispatcher READY_QUEUE
let c = ready_queues
.entry(app.tasks[task].args.priority)
.or_default();
*c = cmp::max(*c, tq_priority);
if let Some(priority) = priority {
// Users of `schedule` contend for the to-be-spawned task FREE_QUEUE (consumer end point)
let c = free_queues.get_mut(task).expect("BUG: free_queue.get_mut");
// Users of `schedule` contend for the spawnee task FREE_QUEUE
let c = free_queues.entry(task.clone()).or_default();
*c = cmp::max(*c, priority);
// Users of `schedule` contend for the timer queu
// Users of `schedule` contend for the timer queue
tq_ceiling = cmp::max(tq_ceiling, priority);
} else {
// spawns from `init` are excluded from the ceiling analysis