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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use core::nonzero::NonZero;
use process;
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub struct AppId {
idx: usize,
}
const KERNEL_APPID_BOUNDARY: usize = 100;
impl AppId {
pub fn new(idx: usize) -> AppId {
AppId { idx: idx }
}
pub const fn kernel_new(idx: usize) -> AppId {
AppId { idx: idx }
}
pub const fn is_kernel(self) -> bool {
self.idx >= KERNEL_APPID_BOUNDARY
}
pub const fn is_kernel_idx(idx: usize) -> bool {
idx >= KERNEL_APPID_BOUNDARY
}
pub fn idx(&self) -> usize {
self.idx
}
pub fn get_editable_flash_range(&self) -> (usize, usize) {
process::get_editable_flash_range(self.idx)
}
}
#[derive(Clone, Copy, Debug)]
pub enum RustOrRawFnPtr {
Raw {
ptr: NonZero<*mut ()>,
},
Rust {
func: fn(usize, usize, usize, usize),
},
}
#[derive(Clone, Copy, Debug)]
pub struct Callback {
app_id: AppId,
appdata: usize,
fn_ptr: RustOrRawFnPtr,
}
impl Callback {
pub fn new(appid: AppId, appdata: usize, fn_ptr: NonZero<*mut ()>) -> Callback {
Callback {
app_id: appid,
appdata: appdata,
fn_ptr: RustOrRawFnPtr::Raw { ptr: fn_ptr },
}
}
pub const fn kernel_new(appid: AppId, fn_ptr: fn(usize, usize, usize, usize)) -> Callback {
Callback {
app_id: appid,
appdata: 0,
fn_ptr: RustOrRawFnPtr::Rust { func: fn_ptr },
}
}
pub fn schedule(&mut self, r0: usize, r1: usize, r2: usize) -> bool {
if self.app_id.is_kernel() {
let fn_ptr = match self.fn_ptr {
RustOrRawFnPtr::Raw { ptr } => {
panic!("Attempt to rust_call a raw function pointer: ptr {:?}", ptr)
}
RustOrRawFnPtr::Rust { func } => func,
};
fn_ptr(r0, r1, r2, self.appdata);
true
} else {
let fn_ptr = match self.fn_ptr {
RustOrRawFnPtr::Raw { ptr } => ptr,
RustOrRawFnPtr::Rust { func } => {
panic!("Attempt to schedule rust function: func {:?}", func)
}
};
process::schedule(
process::FunctionCall {
r0: r0,
r1: r1,
r2: r2,
r3: self.appdata,
pc: fn_ptr.get() as usize,
},
self.app_id,
)
}
}
pub fn app_id(&self) -> AppId {
self.app_id
}
}