1use alloc::sync::Arc;
2use core::cell::UnsafeCell;
3use core::mem::{transmute, MaybeUninit};
4use core::sync::atomic::{AtomicUsize, Ordering};
5
6use crate::param::NCPU;
7use crate::riscv::interrupts;
8use crate::riscv::registers::tp;
9use crate::spinlock::SpinLock;
10
11pub static CPUS: Cpus = Cpus::new();
12
13pub struct Cpus([UnsafeCell<Cpu>; NCPU]);
14unsafe impl Sync for Cpus {}
15
16pub struct Cpu {
17 pub proc: Option<Arc<Proc>>,
18 pub context: Context,
19 pub num_off: isize,
20 pub interrupt_enabled: bool,
21}
22
23impl Cpu {
24 const fn new() -> Self {
25 Self {
26 proc: None,
27 context: Context::new(),
28 num_off: 0,
29 interrupt_enabled: false,
30 }
31 }
32
33 fn lock(&mut self, old_state: bool) -> InterruptLock {
34 if self.num_off == 0 {
35 self.interrupt_enabled = old_state;
36 }
37 self.num_off += 1;
38 InterruptLock {}
39 }
40
41 fn unlock(&mut self) {
42 assert!(!interrupts::get(), "cpu unlock - interruptible");
43 assert!(self.num_off >= 1, "cpu unlock");
44
45 self.num_off -= 1;
46 if self.num_off == 0 && self.interrupt_enabled {
47 interrupts::enable();
48 }
49 }
50}
51
52impl Cpus {
53 const fn new() -> Self {
54 let mut array: [MaybeUninit<_>; NCPU] = unsafe { MaybeUninit::uninit().assume_init() };
55 let mut i = 0;
56 while i < NCPU {
57 array[i] = MaybeUninit::new(UnsafeCell::new(Cpu::new()));
58 i += 1;
59 }
60 unsafe { transmute(array) }
61 }
62
63 #[inline]
66 pub unsafe fn get_id() -> usize {
67 tp::read()
68 }
69
70 pub unsafe fn mycpu() -> *mut Cpu {
73 assert!(!interrupts::get(), "mycpu interrupts enabled");
74 let id = Self::get_id();
75 CPUS.0[id].get()
76 }
77
78 pub fn lock_mycpu() -> InterruptLock {
79 let old_state = interrupts::get();
80 interrupts::disable();
81
82 unsafe { (*Self::mycpu()).lock(old_state) }
83 }
84
85 pub fn myproc() -> Option<Arc<Proc>> {
86 let _lock = Self::lock_mycpu();
87
88 let cpu = unsafe { &*Self::mycpu() };
89 cpu.proc.as_ref().map(Arc::clone)
90 }
91}
92
93pub struct InterruptLock {}
94
95impl Drop for InterruptLock {
96 fn drop(&mut self) {
97 unsafe { (*Cpus::mycpu()).unlock() }
98 }
99}
100
101#[repr(C)]
102pub struct Context {
103 pub ra: usize,
104 pub sp: usize,
105
106 pub s0: usize,
108 pub s1: usize,
109 pub s2: usize,
110 pub s3: usize,
111 pub s4: usize,
112 pub s5: usize,
113 pub s6: usize,
114 pub s7: usize,
115 pub s8: usize,
116 pub s9: usize,
117 pub s10: usize,
118 pub s11: usize,
119}
120
121impl Context {
122 pub const fn new() -> Self {
123 Self {
124 ra: 0,
125 sp: 0,
126 s0: 0,
127 s1: 0,
128 s2: 0,
129 s3: 0,
130 s4: 0,
131 s5: 0,
132 s6: 0,
133 s7: 0,
134 s8: 0,
135 s9: 0,
136 s10: 0,
137 s11: 0,
138 }
139 }
140}
141
142pub struct PID(usize);
143
144impl PID {
145 pub fn new() -> Self {
146 static PID_COUNT: AtomicUsize = AtomicUsize::new(0);
147 PID(PID_COUNT.fetch_add(1, Ordering::Relaxed))
148 }
149}
150
151pub enum ProcState {
152 Unused,
153 Used,
154 Sleeping,
155 Runnable,
156 Running,
157 Zombie,
158}
159
160pub struct Proc {
162 lock: SpinLock,
163
164 state: ProcState,
165 chan: (),
166 killed: bool,
167 xstate: isize,
168 pid: PID,
169 }
172
173pub fn sleep(chan: usize, lock: SpinLock) {
174 let mut proc = Cpus::myproc().unwrap();
175 }