obkrnl/uma/
slab.rs

1use super::{UmaFlags, UmaKeg};
2use alloc::sync::Arc;
3
4/// Implementation of `uma_slab` and `uma_slab_refcnt`.
5///
6/// We use slightly different mechanism here but has the same memory layout.
7///
8/// # Safety
9/// Adding more fields into this struct without knowing how it work can cause undefined behavior in
10/// some places.
11#[repr(C)]
12pub struct Slab<I> {
13    pub hdr: SlabHdr<I>, // us_head
14    pub free: [I],       // us_freelist
15}
16
17impl<I> Slab<I> {
18    /// See `slab_alloc_item` on the Orbis for a reference.
19    ///
20    /// # Reference offsets
21    /// | Version | Offset |
22    /// |---------|--------|
23    /// |PS4 11.00|0x141FE0|
24    pub fn alloc_item(&mut self) -> *mut u8 {
25        self.hdr.free_count -= 1;
26
27        if self.hdr.free_count != 0 {
28            let off = self.hdr.first_free * self.hdr.keg.allocated_size();
29
30            return unsafe { self.hdr.items.add(off) };
31        }
32
33        todo!()
34    }
35}
36
37/// Implementation of `uma_slab_head`.
38pub struct SlabHdr<I> {
39    pub keg: Arc<UmaKeg<I>>, // us_keg
40    pub free_count: usize,   // us_freecount
41    pub first_free: usize,   // us_firstfree
42    pub items: *mut u8,      // us_data
43}
44
45/// Item in [Slab::free] to represents `uma_slab` structure.
46#[repr(C)]
47pub struct StdFree {
48    pub item: u8, // us_item
49}
50
51unsafe impl FreeItem for StdFree {
52    fn new(idx: usize) -> Self {
53        Self {
54            item: (idx + 1).try_into().unwrap(),
55        }
56    }
57
58    fn flags() -> UmaFlags {
59        UmaFlags::zeroed()
60    }
61}
62
63/// Item in [Slab::free] to represents `uma_slab_refcnt` structure.
64#[repr(C)]
65#[allow(dead_code)] // TODO: Remove this.
66pub struct RefFree {
67    pub item: u8,  // us_item
68    pub refs: u32, // us_refcnt
69}
70
71unsafe impl FreeItem for RefFree {
72    fn new(idx: usize) -> Self {
73        Self {
74            item: (idx + 1).try_into().unwrap(),
75            refs: 0,
76        }
77    }
78
79    fn flags() -> UmaFlags {
80        UmaFlags::VToSlab.into()
81    }
82}
83
84/// Each item in [Slab::free].
85///
86/// # Safety
87/// Wrong flags from [Self::flags()] can cause undefined behavior in some places.
88pub unsafe trait FreeItem: Sized {
89    fn new(idx: usize) -> Self;
90    fn flags() -> UmaFlags;
91}