1extern crate alloc;
8
9use alloc::collections::BTreeMap;
10use alloc::sync::Arc;
11use spin::Mutex;
12
13#[derive(Debug)]
23pub struct TaskNamespace {
24 id: usize,
26 next_task_id: Mutex<usize>,
28 local_to_global: Mutex<BTreeMap<usize, usize>>,
33 global_to_local: Mutex<BTreeMap<usize, usize>>,
35 parent: Option<Arc<TaskNamespace>>,
37 name: alloc::string::String,
39}
40
41impl TaskNamespace {
42 pub fn new_root(name: alloc::string::String) -> Arc<Self> {
50 Arc::new(TaskNamespace {
51 id: 0,
52 next_task_id: Mutex::new(1), local_to_global: Mutex::new(BTreeMap::new()),
54 global_to_local: Mutex::new(BTreeMap::new()),
55 parent: None,
56 name,
57 })
58 }
59
60 pub fn new_child(parent: Arc<TaskNamespace>, name: alloc::string::String) -> Arc<Self> {
69 static NEXT_NS_ID: Mutex<usize> = Mutex::new(1);
70 let ns_id = {
71 let mut id = NEXT_NS_ID.lock();
72 let current = *id;
73 *id += 1;
74 current
75 };
76
77 Arc::new(TaskNamespace {
78 id: ns_id,
79 next_task_id: Mutex::new(1),
80 local_to_global: Mutex::new(BTreeMap::new()),
81 global_to_local: Mutex::new(BTreeMap::new()),
82 parent: Some(parent),
83 name,
84 })
85 }
86
87 pub fn allocate_task_id(&self) -> usize {
92 let mut next_id = self.next_task_id.lock();
93 let id = *next_id;
94 *next_id += 1;
95 id
96 }
97
98 pub fn allocate_task_id_for(&self, global_task_id: usize) -> usize {
103 let local_id = self.allocate_task_id();
104 self.register_mapping(local_id, global_task_id);
105 local_id
106 }
107
108 pub fn register_mapping(&self, local_id: usize, global_task_id: usize) {
110 self.local_to_global.lock().insert(local_id, global_task_id);
111 self.global_to_local.lock().insert(global_task_id, local_id);
112 }
113
114 pub fn resolve_global_id(&self, local_id: usize) -> Option<usize> {
116 self.local_to_global.lock().get(&local_id).copied()
117 }
118
119 pub fn resolve_local_id(&self, global_task_id: usize) -> Option<usize> {
121 self.global_to_local.lock().get(&global_task_id).copied()
122 }
123
124 pub fn get_id(&self) -> usize {
126 self.id
127 }
128
129 pub fn get_parent(&self) -> Option<&Arc<TaskNamespace>> {
131 self.parent.as_ref()
132 }
133
134 pub fn get_name(&self) -> &str {
136 &self.name
137 }
138
139 pub fn is_root(&self) -> bool {
141 self.parent.is_none()
142 }
143}
144
145static ROOT_NAMESPACE: spin::Once<Arc<TaskNamespace>> = spin::Once::new();
150
151pub fn get_root_namespace() -> &'static Arc<TaskNamespace> {
153 ROOT_NAMESPACE.call_once(|| TaskNamespace::new_root("root".into()))
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159 use alloc::string::ToString;
160
161 #[test_case]
162 fn test_root_namespace_creation() {
163 let root = TaskNamespace::new_root("test_root".to_string());
164 assert_eq!(root.get_id(), 0);
165 assert_eq!(root.get_name(), "test_root");
166 assert!(root.is_root());
167 assert!(root.get_parent().is_none());
168 }
169
170 #[test_case]
171 fn test_child_namespace_creation() {
172 let root = TaskNamespace::new_root("root".to_string());
173 let child = TaskNamespace::new_child(root.clone(), "child".to_string());
174
175 assert_ne!(child.get_id(), 0);
176 assert_eq!(child.get_name(), "child");
177 assert!(!child.is_root());
178 assert!(child.get_parent().is_some());
179 }
180
181 #[test_case]
182 fn test_task_id_allocation() {
183 let ns = TaskNamespace::new_root("test".to_string());
184 let id1 = ns.allocate_task_id();
185 let id2 = ns.allocate_task_id();
186 let id3 = ns.allocate_task_id();
187
188 assert_eq!(id1, 1);
189 assert_eq!(id2, 2);
190 assert_eq!(id3, 3);
191 }
192
193 #[test_case]
194 fn test_separate_namespace_ids() {
195 let ns1 = TaskNamespace::new_root("ns1".to_string());
196 let ns2 = TaskNamespace::new_root("ns2".to_string());
197
198 let id1_1 = ns1.allocate_task_id();
199 let id2_1 = ns2.allocate_task_id();
200 let id1_2 = ns1.allocate_task_id();
201 let id2_2 = ns2.allocate_task_id();
202
203 assert_eq!(id1_1, 1);
205 assert_eq!(id2_1, 1);
206 assert_eq!(id1_2, 2);
207 assert_eq!(id2_2, 2);
208 }
209
210 #[test_case]
211 fn test_root_namespace_singleton() {
212 let root1 = get_root_namespace();
213 let root2 = get_root_namespace();
214
215 assert_eq!(Arc::as_ptr(root1), Arc::as_ptr(root2));
217 }
218}