1use core::borrow::Borrow;
3use core::fmt::Display;
4use core::num::NonZero;
5
6use envparse::parse_env;
7
8use hal::stack::Stacklike;
9
10use crate::error::Result;
11use crate::mem;
12use crate::sched::{ThreadMap, thread};
13use crate::types::list;
14
15use crate::mem::vmm::AddressSpacelike;
16use crate::types::traits::ToIndex;
17
18pub struct Defaults {
19 pub stack_pages: usize,
20}
21
22const DEFAULTS: Defaults = Defaults {
23 stack_pages: parse_env!("OSIRIS_STACKPAGES" as usize),
24};
25
26pub const KERNEL_TASK: UId = UId { uid: 0 };
27
28#[proc_macros::fmt]
30#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
31pub struct UId {
32 uid: usize,
33}
34
35impl UId {
36 pub fn new(uid: usize) -> Self {
37 Self { uid }
38 }
39
40 pub fn is_kernel(&self) -> bool {
41 self.uid == 0
42 }
43}
44
45impl ToIndex for UId {
46 fn to_index<Q: Borrow<Self>>(idx: Option<Q>) -> usize {
47 idx.as_ref().map_or(0, |uid| uid.borrow().uid)
48 }
49}
50
51impl Display for UId {
52 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
53 write!(f, "{}", self.uid)
54 }
55}
56
57#[allow(dead_code)]
58pub struct Attributes {
59 pub resrv_pgs: Option<NonZero<usize>>,
60 pub address_space: Option<mem::vmm::AddressSpace>,
61}
62
63pub struct Task {
65 pub id: UId,
67 tid_cntr: usize,
69 address_space: mem::vmm::AddressSpace,
71 threads: list::List<thread::ThreadList, thread::UId>,
73}
74
75impl Task {
76 pub fn new(id: UId, attrs: Attributes) -> Result<Self> {
77 let address_space = match attrs.address_space {
78 Some(addr_space) => addr_space,
79 None => {
80 let resrv_pgs = attrs.resrv_pgs.ok_or(kerr!(InvalidArgument))?;
81 mem::vmm::AddressSpace::new(resrv_pgs.get())?
82 }
83 };
84
85 Ok(Self {
86 id,
87 address_space,
88 tid_cntr: 0,
89 threads: list::List::new(),
90 })
91 }
92
93 pub fn allocate_tid(&mut self) -> thread::Id {
94 let tid = self.tid_cntr;
95 self.tid_cntr += 1;
96 thread::Id::new(tid, self.id)
97 }
98
99 pub fn allocate_stack(&mut self, attrs: &thread::Attributes) -> Result<hal::Stack> {
100 let size = DEFAULTS.stack_pages * mem::pfa::PAGE_SIZE;
101 let region = mem::vmm::Region::new(
102 None,
103 size,
104 mem::vmm::Backing::Uninit,
105 mem::vmm::Perms::Read | mem::vmm::Perms::Write,
106 );
107 let pa = self.address_space.map(region)?;
108
109 Ok(unsafe {
110 hal::Stack::new(hal::stack::Descriptor {
111 top: pa + size,
112 size: NonZero::new(size).unwrap(),
113 entry: attrs.entry,
114 fin: attrs.fin,
115 })?
116 })
117 }
118
119 pub fn register_thread<const N: usize>(
120 &mut self,
121 uid: thread::UId,
122 storage: &mut ThreadMap<N>,
123 ) -> Result<()> {
124 self.threads.push_back(uid, storage)
125 }
126
127 #[allow(dead_code)]
128 pub fn tid_cntr(&self) -> usize {
129 self.tid_cntr
130 }
131
132 pub fn threads_mut(&mut self) -> &mut list::List<thread::ThreadList, thread::UId> {
133 &mut self.threads
134 }
135
136 pub fn threads(&self) -> &list::List<thread::ThreadList, thread::UId> {
137 &self.threads
138 }
139}