aboutsummaryrefslogtreecommitdiff
path: root/macros/src/analyze.rs
blob: 65d98e69606f89c1bd3c3e6957b995509d799cb1 (plain) (blame)
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
use std::cmp;
use std::collections::HashMap;

use syn::Ident;

use check::App;

pub type Ownerships = HashMap<Ident, Ownership>;

pub enum Ownership {
    /// Owned or co-owned by tasks that run at the same priority
    Owned { priority: u8 },
    /// Shared by tasks that run at different priorities.
    ///
    /// `ceiling` is the maximum value across all the task priorities
    Shared { ceiling: u8 },
}

impl Ownership {
    pub fn ceiling(&self) -> u8 {
        match *self {
            Ownership::Owned { priority } => priority,
            Ownership::Shared { ceiling } => ceiling,
        }
    }

    pub fn is_owned(&self) -> bool {
        match *self {
            Ownership::Owned { .. } => true,
            _ => false,
        }
    }
}

pub fn app(app: &App) -> Ownerships {
    let mut ownerships = HashMap::new();

    for resource in &app.idle.resources {
        ownerships.insert(resource.clone(), Ownership::Owned { priority: 0 });
    }

    for task in app.tasks.values() {
        for resource in &task.resources {
            if let Some(ownership) = ownerships.get_mut(resource) {
                match *ownership {
                    Ownership::Owned { priority } => {
                        if priority == task.priority {
                            *ownership = Ownership::Owned { priority };
                        } else {
                            *ownership = Ownership::Shared {
                                ceiling: cmp::max(priority, task.priority),
                            };
                        }
                    }
                    Ownership::Shared { ceiling } => {
                        if task.priority > ceiling {
                            *ownership = Ownership::Shared {
                                ceiling: task.priority,
                            };
                        }
                    }
                }

                continue;
            }

            ownerships.insert(
                resource.clone(),
                Ownership::Owned {
                    priority: task.priority,
                },
            );
        }
    }

    ownerships
}