Skip to main content

obkrnl/uma/
slab.rs

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