kernel/
proc.rs

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    // # Safety: must be called with interrupts disabled,
64    // to prevent race with process being moved to a different CPU.
65    #[inline]
66    pub unsafe fn get_id() -> usize {
67        tp::read()
68    }
69
70    // Safety: must be called with interrupts disabled,
71    // to prevent race with process being moved to a different CPU.
72    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    // callee-saved
107    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
160// Per-process state
161pub struct Proc {
162    lock: SpinLock,
163
164    state: ProcState,
165    chan: (),
166    killed: bool,
167    xstate: isize,
168    pid: PID,
169    // parent: *const Self,
170    // TODO
171}
172
173pub fn sleep(chan: usize, lock: SpinLock) {
174    let mut proc = Cpus::myproc().unwrap();
175    // let mut proc_lock = proc.lock.acquire();
176
177    // p.lock.acquire();
178}