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
#![allow(unused)]

use core::fmt;

use crate::arch::context::*;

/// The Thread is an object used by the scheduler.
pub struct Thread {
    /// Thread id, each thread should have a different one
    pub id: usize,
    /// Saved registers
    pub registers: Registers,
    /// Kernel stack
    kernel_stack: &'static mut [u32],
    /// If this thread has been killed
    pub exited: bool,
    /// Function pointer
    action: extern "C" fn() -> !,
}

impl fmt::Debug for Thread {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Thread")
            .field("id", &self.id)
            .field("registers", &self.registers)
            .field("kernel_stack", &self.kernel_stack())
            .field("exited", &self.exited)
            .finish_non_exhaustive()
    }
}

impl Thread {
    /// Creates a new thread with the given action.
    ///
    /// If the `user_stack` is null, it is set up with the action as entry point.
    pub fn new(action: extern "C" fn() -> !) -> Self {
        Self {
            id: 0,
            registers: Registers::new(),
            kernel_stack: &mut [],
            exited: false,
            action,
        }
    }

    pub fn init(&mut self, _kernel_stack: &'static mut [u32]) {
        // Setup stack
        todo!("BSB A4")
    }

    /// Returns the top of the kernel stack pointer.
    pub fn kernel_stack(&self) -> *mut () {
        self.kernel_stack.as_ptr_range().end.cast_mut().cast()
    }

    /// Kickoff function that is called in kernel mode.
    ///
    /// If the thread was configured with a user stack, `user_kickoff` is called in user mode.
    /// Otherwise the `action` is executed directly in the kernel.
    extern "C" fn kernel_kickoff(_action: extern "C" fn()) {
        todo!("BSB A4")
    }

    /// Switches from the currently running thread to the `next` one.
    ///
    /// The values currently present in the callee-saved registers will be
    /// stored in this threads context-structure, the corresponding values
    /// belonging to `next` thread will be loaded.
    pub fn resume(&mut self, _next: &Self) {
        todo!("BSB A4")
    }

    /// Activates the first thread on this CPU.
    ///
    /// Calling the method starts the first thread on the calling CPU.
    /// From then on, [Thread::resume] must be used all subsequent context
    /// switches.
    pub fn go(&self) {
        todo!("BSB A4")
    }
}