pudding_kernel/
system.rs

1use crate::task::*;
2use crate::*;
3
4struct SystemControlBlock {
5    interrupt: bool,
6    cpu_lock: bool,
7    dispatch_disable: bool,
8    dispatch_reserve: bool,
9}
10
11static mut SYSCB: SystemControlBlock = SystemControlBlock {
12    interrupt: false,
13    cpu_lock: false,
14    dispatch_disable: false,
15    dispatch_reserve: false,
16};
17
18pub(crate) fn test_interrupt_flag() -> bool {
19    unsafe { SYSCB.interrupt }
20}
21
22pub(crate) fn set_interrupt_flag() {
23    unsafe {
24        SYSCB.interrupt = true;
25    }
26}
27
28pub(crate) fn clear_interrupt_flag() {
29    unsafe {
30        SYSCB.interrupt = false;
31    }
32}
33
34pub(crate) fn test_cpu_lock_flag() -> bool {
35    unsafe { SYSCB.cpu_lock }
36}
37
38pub(crate) fn set_cpu_lock_flag() {
39    unsafe {
40        SYSCB.cpu_lock = true;
41    }
42}
43
44pub(crate) fn clear_cpu_lock_flag() {
45    unsafe {
46        SYSCB.cpu_lock = false;
47    }
48}
49
50pub(crate) fn test_dispatch_disable_flag() -> bool {
51    unsafe { SYSCB.dispatch_disable }
52}
53
54pub(crate) fn set_dispatch_disable_flag() {
55    unsafe {
56        SYSCB.dispatch_disable = true;
57    }
58}
59
60pub(crate) fn clear_dispatch_disable_flag() {
61    unsafe {
62        SYSCB.dispatch_disable = false;
63    }
64}
65
66pub(crate) fn test_dispatch_reserve_flag() -> bool {
67    unsafe { SYSCB.dispatch_reserve }
68}
69
70pub(crate) fn set_dispatch_reserve_flag() {
71    unsafe {
72        SYSCB.dispatch_reserve = true;
73    }
74}
75
76pub(crate) fn clear_dispatch_reserve_flag() {
77    unsafe {
78        SYSCB.dispatch_reserve = false;
79    }
80}
81
82// System Call
83
84pub(crate) unsafe fn enter_system_call() {
85    cpu_lock();
86    // (注) もしマルチプロセッサやる場合はここにメモリバリアも入れる
87}
88
89pub(crate) unsafe fn leave_system_call() {
90    if test_dispatch_reserve_flag()
91        && !test_interrupt_flag()
92        && !test_dispatch_disable_flag()
93        && !test_cpu_lock_flag()
94    // (注) もしマルチプロセッサやる場合はここにメモリバリアも入れる
95    {
96        clear_dispatch_reserve_flag();
97        task_switch();
98    }
99
100    if !test_cpu_lock_flag() {
101        cpu_unlock();
102    }
103}
104
105pub(crate) struct SystemCall {}
106
107impl SystemCall {
108    pub(crate) fn new() -> Self {
109        unsafe {
110            enter_system_call();
111            Self {}
112        }
113    }
114}
115
116impl Drop for SystemCall {
117    fn drop(&mut self) {
118        unsafe {
119            leave_system_call();
120        }
121    }
122}
123
124pub fn lock_cpu() {
125    let _sc = SystemCall::new();
126    set_cpu_lock_flag();
127}
128
129pub fn unlock_cpu() {
130    let _sc = SystemCall::new();
131    clear_cpu_lock_flag();
132}
133
134pub fn is_cpu_locked() -> bool {
135    let _sc = SystemCall::new();
136    test_cpu_lock_flag()
137}
138
139pub fn disable_dispatch() {
140    let _sc = SystemCall::new();
141    set_dispatch_disable_flag();
142}
143
144pub fn enable_dispatch() {
145    let _sc = SystemCall::new();
146    clear_dispatch_disable_flag();
147}
148
149pub fn is_dispatch_disabled() -> bool {
150    let _sc = SystemCall::new();
151    test_dispatch_disable_flag()
152}
153
154pub fn is_dispatch_pending_state() -> bool {
155    let _sc = SystemCall::new();
156    test_cpu_lock_flag() || test_dispatch_disable_flag()
157}
158
159pub fn is_interrupt_state() -> bool {
160    test_interrupt_flag()
161}
162
163pub fn idle_loop() -> ! {
164    loop {
165        unsafe {
166            cpu_halt();
167        }
168    }
169}