1use core::{
7 mem::ManuallyDrop,
8 ops::{Deref, DerefMut},
9};
10
11#[cfg(feature = "alloc")]
12extern crate alloc;
13
14#[cfg(feature = "alloc")]
15use alloc::sync::Arc;
16#[cfg(feature = "alloc")]
17use alloc::vec::Vec;
18
19#[cfg(not(feature = "alloc"))]
21struct Vec<T> {
22 _phantom: core::marker::PhantomData<T>,
23}
24
25#[cfg(not(feature = "alloc"))]
26impl<T> Vec<T> {
27 fn len(&self) -> usize {
28 0
29 }
30 fn clone(&self) -> Self {
31 Self {
32 _phantom: core::marker::PhantomData,
33 }
34 }
35}
36
37use spin::{Mutex, MutexGuard};
38
39#[allow(unused_imports)]
40use crate::{
41 cap::{CapabilityId, CapabilitySpace},
42 mm::{frame_allocator::FrameAllocator, PhysicalFrame},
43 println,
44 process::ProcessId,
45};
46
47pub struct FrameGuard {
51 frame: PhysicalFrame,
52 allocator: &'static FrameAllocator,
53}
54
55impl FrameGuard {
56 pub fn new(frame: PhysicalFrame, allocator: &'static FrameAllocator) -> Self {
58 Self { frame, allocator }
59 }
60
61 pub fn addr(&self) -> usize {
63 self.frame.addr()
64 }
65
66 pub fn leak(self) -> PhysicalFrame {
68 let frame = self.frame;
69 core::mem::forget(self);
70 frame
71 }
72}
73
74impl Drop for FrameGuard {
75 fn drop(&mut self) {
76 unsafe {
82 self.allocator.free_frame(self.frame);
83 }
84 println!("[RAII] Released frame at {:#x}", self.frame.addr());
85 }
86}
87
88impl Deref for FrameGuard {
89 type Target = PhysicalFrame;
90
91 fn deref(&self) -> &Self::Target {
92 &self.frame
93 }
94}
95
96pub struct FramesGuard {
98 frames: Vec<PhysicalFrame>,
99 #[allow(dead_code)] count: usize,
101 allocator: &'static FrameAllocator,
102}
103
104impl FramesGuard {
105 pub fn new(frames: Vec<PhysicalFrame>, allocator: &'static FrameAllocator) -> Self {
107 let count = frames.len();
108 Self {
109 frames,
110 count,
111 allocator,
112 }
113 }
114
115 pub fn leak(self) -> Vec<PhysicalFrame> {
117 let frames = self.frames.clone();
118 core::mem::forget(self);
119 frames
120 }
121}
122
123impl Drop for FramesGuard {
124 fn drop(&mut self) {
125 for frame in &self.frames {
127 unsafe {
131 self.allocator.free_frame(*frame);
132 }
133 }
134 println!("[RAII] Released {} frames", self.count);
135 }
136}
137
138pub struct MappedRegion {
140 virt_addr: usize,
141 size: usize,
142 process_id: ProcessId,
143}
144
145impl MappedRegion {
146 pub fn new(virt_addr: usize, size: usize, process_id: ProcessId) -> Self {
148 Self {
149 virt_addr,
150 size,
151 process_id,
152 }
153 }
154
155 pub fn addr(&self) -> usize {
157 self.virt_addr
158 }
159
160 pub fn size(&self) -> usize {
162 self.size
163 }
164}
165
166impl Drop for MappedRegion {
167 fn drop(&mut self) {
168 if let Some(process) = crate::process::find_process(self.process_id) {
170 let memory_space = process.memory_space.lock();
171 if let Err(_e) = memory_space.unmap(self.virt_addr, self.size) {
172 println!(
173 "[RAII] Warning: Failed to unmap region at {:#x}: {:?}",
174 self.virt_addr, _e
175 );
176 } else {
177 println!(
178 "[RAII] Unmapped region at {:#x} (size: {:#x})",
179 self.virt_addr, self.size
180 );
181 }
182 }
183 }
184}
185
186pub struct CapabilityGuard {
188 cap_id: CapabilityId,
189 space: Arc<Mutex<CapabilitySpace>>,
190}
191
192impl CapabilityGuard {
193 pub fn new(cap_id: CapabilityId, space: Arc<Mutex<CapabilitySpace>>) -> Self {
195 Self { cap_id, space }
196 }
197
198 pub fn id(&self) -> CapabilityId {
200 self.cap_id
201 }
202
203 pub fn leak(self) -> CapabilityId {
205 let id = self.cap_id;
206 core::mem::forget(self);
207 id
208 }
209}
210
211impl Drop for CapabilityGuard {
212 fn drop(&mut self) {
213 let mut space = self.space.lock();
215 if let Err(_e) = space.revoke(self.cap_id) {
216 println!(
217 "[RAII] Warning: Failed to revoke capability {}: {:?}",
218 self.cap_id, _e
219 );
220 } else {
221 println!("[RAII] Revoked capability {}", self.cap_id);
222 }
223 }
224}
225
226#[cfg(feature = "alloc")]
230pub struct ProcessResources {
231 pid: ProcessId,
232 threads: ManuallyDrop<Vec<crate::process::ThreadId>>,
234 capabilities: ManuallyDrop<Arc<Mutex<CapabilitySpace>>>,
235 memory_space: ManuallyDrop<Arc<Mutex<crate::mm::VirtualAddressSpace>>>,
236}
237
238#[cfg(feature = "alloc")]
239impl ProcessResources {
240 pub fn new(
242 pid: ProcessId,
243 threads: Vec<crate::process::ThreadId>,
244 capabilities: Arc<Mutex<CapabilitySpace>>,
245 memory_space: Arc<Mutex<crate::mm::VirtualAddressSpace>>,
246 ) -> Self {
247 Self {
248 pid,
249 threads: ManuallyDrop::new(threads),
250 capabilities: ManuallyDrop::new(capabilities),
251 memory_space: ManuallyDrop::new(memory_space),
252 }
253 }
254}
255
256#[cfg(feature = "alloc")]
257impl Drop for ProcessResources {
258 fn drop(&mut self) {
259 println!("[RAII] Cleaning up resources for process {}", self.pid);
260
261 for &thread_id in self.threads.iter() {
263 if let Err(_e) = crate::process::terminate_thread(self.pid, thread_id) {
264 println!(
265 "[RAII] Warning: Failed to terminate thread {:?}: {:?}",
266 thread_id, _e
267 );
268 }
269 }
270
271 unsafe {
277 let capabilities = ManuallyDrop::take(&mut self.capabilities);
278 let mut cap_space = capabilities.lock();
279 cap_space.revoke_all();
280 }
281
282 unsafe {
288 let memory_space = ManuallyDrop::take(&mut self.memory_space);
289 let mut mem_space = memory_space.lock();
290 mem_space.destroy();
291 }
292
293 println!("[RAII] Process {} resources cleaned up", self.pid);
294 }
295}
296
297pub struct TrackedMutexGuard<'a, T> {
299 guard: MutexGuard<'a, T>,
300 #[allow(dead_code)] name: &'static str,
302}
303
304impl<'a, T> TrackedMutexGuard<'a, T> {
305 pub fn new(guard: MutexGuard<'a, T>, name: &'static str) -> Self {
307 println!("[RAII] Acquired lock: {}", name);
308 Self { guard, name }
309 }
310}
311
312impl<T> Drop for TrackedMutexGuard<'_, T> {
313 fn drop(&mut self) {
314 println!("[RAII] Released lock: {}", self.name);
315 }
316}
317
318impl<T> Deref for TrackedMutexGuard<'_, T> {
319 type Target = T;
320
321 fn deref(&self) -> &Self::Target {
322 &self.guard
323 }
324}
325
326impl<T> DerefMut for TrackedMutexGuard<'_, T> {
327 fn deref_mut(&mut self) -> &mut Self::Target {
328 &mut self.guard
329 }
330}
331
332pub struct ChannelGuard {
334 channel_id: u64,
335}
336
337impl ChannelGuard {
338 pub fn new(channel_id: u64) -> Self {
340 Self { channel_id }
341 }
342
343 pub fn id(&self) -> u64 {
345 self.channel_id
346 }
347
348 pub fn leak(self) -> u64 {
350 let id = self.channel_id;
351 core::mem::forget(self);
352 id
353 }
354}
355
356impl Drop for ChannelGuard {
357 fn drop(&mut self) {
358 if let Err(_e) = crate::ipc::registry::remove_channel(self.channel_id) {
360 println!(
361 "[RAII] Warning: Failed to remove channel {}: {:?}",
362 self.channel_id, _e
363 );
364 } else {
365 println!("[RAII] Removed channel {} from registry", self.channel_id);
366 }
367 }
368}
369
370#[macro_export]
372macro_rules! defer {
373 ($e:expr) => {
374 let _guard = $crate::raii::ScopeGuard::new(|| $e);
375 };
376}
377
378pub struct ScopeGuard<F: FnOnce()> {
380 cleanup: Option<F>,
381}
382
383impl<F: FnOnce()> ScopeGuard<F> {
384 pub fn new(cleanup: F) -> Self {
386 Self {
387 cleanup: Some(cleanup),
388 }
389 }
390
391 pub fn cancel(mut self) {
393 self.cleanup = None;
394 }
395}
396
397impl<F: FnOnce()> Drop for ScopeGuard<F> {
398 fn drop(&mut self) {
399 if let Some(cleanup) = self.cleanup.take() {
400 cleanup();
401 }
402 }
403}
404
405#[cfg(test)]
406mod tests {
407 use super::*;
408
409 #[test]
410 fn test_scope_guard() {
411 let mut cleaned = false;
412 {
413 let _guard = ScopeGuard::new(|| {
414 cleaned = true;
415 });
416 }
417 assert!(cleaned);
418 }
419
420 #[test]
421 fn test_scope_guard_cancel() {
422 let mut cleaned = false;
423 {
424 let guard = ScopeGuard::new(|| {
425 cleaned = true;
426 });
427 guard.cancel();
428 }
429 assert!(!cleaned);
430 }
431}