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
82pub(crate) unsafe fn enter_system_call() {
85 cpu_lock();
86 }
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 {
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}