commonlibsse_ng\re\b/
BSSmallBlockAllocator.rs

1use crate::re::{BSAtomic::BSCriticalSection, IMemoryStore::IMemoryStore};
2use core::ptr::NonNull;
3
4/// Represents a free block in the small block allocator.
5#[repr(C)]
6#[derive(Debug)]
7pub struct FreeBlock {
8    pub next: *mut FreeBlock, // 0x00
9}
10
11const _: () = {
12    assert!(std::mem::size_of::<FreeBlock>() == 0x8);
13};
14
15impl Default for FreeBlock {
16    #[inline]
17    fn default() -> Self {
18        unsafe { core::mem::zeroed() }
19    }
20}
21
22/// Represents a block page used by the allocator.
23#[repr(C)]
24#[derive(Debug)]
25pub struct BlockPage {
26    pub left: *mut BlockPage,   // 0x00
27    pub right: *mut BlockPage,  // 0x08
28    pub blocks: *mut FreeBlock, // 0x10
29    pub totalElem: u16,         // 0x18
30    pub freeElem: u16,          // 0x1A
31    pub pad1C: u32,             // 0x1C
32}
33
34const _: () = {
35    assert!(std::mem::size_of::<BlockPage>() == 0x20);
36};
37
38impl Default for BlockPage {
39    #[inline]
40    fn default() -> Self {
41        unsafe { core::mem::zeroed() }
42    }
43}
44
45/// Represents an internal block page.
46#[repr(C)]
47#[derive(Debug, Clone, Copy, PartialEq)]
48pub struct BlockPageInternal {
49    pub left: *mut BlockPageInternal,  // 0x00
50    pub right: *mut BlockPageInternal, // 0x08
51    pub blocks: *mut FreeBlock,        // 0x10
52    pub totalElem: u16,                // 0x18
53    pub freeElem: u16,                 // 0x1A
54    pub elemSize: u16,                 // 0x1C
55    pub check: u16,                    // 0x1E
56}
57const _: () = {
58    assert!(std::mem::size_of::<BlockPageInternal>() == 0x20);
59};
60
61impl Default for BlockPageInternal {
62    #[inline]
63    fn default() -> Self {
64        unsafe { core::mem::zeroed() }
65    }
66}
67
68/// Represents a pool for memory allocation.
69#[repr(C)]
70#[derive(Debug, Clone, PartialEq)]
71pub struct Pool {
72    pub pageList: *mut BlockPage,  // 0x00
73    pub currAlloc: *mut BlockPage, // 0x08
74    pub totalFreeBlocks: u32,      // 0x10
75    pub totalAllocatedBlocks: u32, // 0x14
76    pub totalBytes: u32,           // 0x18
77    pub elementSize: u32,          // 0x1C
78    pub lock: BSCriticalSection,   // 0x20
79}
80const _: () = {
81    assert!(std::mem::size_of::<Pool>() == 0x48);
82};
83impl Default for Pool {
84    #[inline]
85    fn default() -> Self {
86        unsafe { core::mem::zeroed() }
87    }
88}
89
90/// Represents a mega block page.
91#[repr(C)]
92#[derive(Debug)]
93pub struct MegaBlockPage {
94    pub mem: [u8; 0x1FE000],                   // 0x000000 - Raw memory block
95    pub blockPages: [BlockPageInternal; 255],  // 0x1FE000
96    pub left: Option<NonNull<MegaBlockPage>>,  // 0x1FFFE0
97    pub right: Option<NonNull<MegaBlockPage>>, // 0x1FFFE8
98    pub freeBlockPages: *mut BlockPage,        // 0x1FFFF0
99    pub numFreeBlockPages: u16,                // 0x1FFFF8
100    pub nextBlockPageAlloc: u16,               // 0x1FFFFA
101    pub decommitted: bool,                     // 0x1FFFFC
102    pub pad1FFFFD: u8,                         // 0x1FFFFD
103    pub pad1FFFFE: u16,                        // 0x1FFFFE
104}
105const _: () = {
106    assert!(core::mem::size_of::<MegaBlockPage>() == 0x200000); // 2MiB
107};
108
109impl MegaBlockPage {
110    /// # Safety
111    #[inline]
112    pub unsafe fn alloc_zeroed() -> Option<NonNull<Self>> {
113        const SELF_ALIGN: usize = core::mem::align_of::<MegaBlockPage>();
114        const SELF_SIZE: usize = core::mem::size_of::<MegaBlockPage>();
115
116        // Validate Layout at compile time.
117        const _: () = {
118            assert!(SELF_ALIGN != 0);
119            assert!(SELF_ALIGN % 2 == 0);
120            assert!(SELF_SIZE <= (isize::MAX as usize));
121        };
122
123        unsafe {
124            let layout = core::alloc::Layout::from_size_align_unchecked(SELF_SIZE, SELF_ALIGN);
125            NonNull::new(std::alloc::alloc_zeroed(layout).cast::<Self>())
126        }
127    }
128}
129
130/// The main small block allocator struct.
131#[repr(C)]
132#[derive(Debug, Clone, PartialEq)]
133pub struct BSSmallBlockAllocator {
134    pub __base: IMemoryStore,                   // 0x0000
135    pub pools: [Pool; 64],                      // 0x0008
136    pub lock: BSCriticalSection,                // 0x1208
137    pub addressSpaceSize: u32,                  // 0x1230
138    pub pad1234: u32,                           // 0x1234
139    pub allocBase: *mut u8,                     // 0x1238
140    pub blockPageCommitMin: *mut u8,            // 0x1240
141    pub blockPageCommit: *mut u8,               // 0x1248
142    pub megaBlockPageList: *mut MegaBlockPage,  // 0x1250
143    pub megaBlockCurrAlloc: *mut MegaBlockPage, // 0x1258
144    pub totalFreeBlockPages: u32,               // 0x1260
145    pub allowDecommits: bool,                   // 0x1264
146    pub pad1265: u8,                            // 0x1265
147    pub pad1266: u16,                           // 0x1266
148}
149
150const _: () = {
151    assert!(std::mem::size_of::<BSSmallBlockAllocator>() == 0x1268);
152};
153
154impl Default for BSSmallBlockAllocator {
155    #[inline]
156    fn default() -> Self {
157        unsafe { core::mem::zeroed() }
158    }
159}
160
161/// Virtual table for `BSSmallBlockAllocator` to simulate the C++ vtable.
162#[repr(C)]
163pub struct BSSmallBlockAllocatorVtbl {
164    /// C++ `virtual ~BSSmallBlockAllocator()`
165    pub CxxDrop: unsafe extern "C" fn(this: &mut BSSmallBlockAllocator),
166
167    pub Size: unsafe extern "C" fn(this: &BSSmallBlockAllocator, block: *const u8) -> usize,
168    pub GetMemoryStats: unsafe extern "C" fn(this: &BSSmallBlockAllocator, stats: *mut ()) -> (),
169    pub ContainsBlockImpl:
170        unsafe extern "C" fn(this: &BSSmallBlockAllocator, block: *const u8) -> bool,
171    pub AllocateAlignImpl:
172        unsafe extern "C" fn(this: &mut BSSmallBlockAllocator, size: usize, align: u32) -> *mut u8,
173    pub DeallocateAlignImpl:
174        unsafe extern "C" fn(this: &mut BSSmallBlockAllocator, free_block: *mut *mut u8),
175    pub TryAllocateImpl:
176        unsafe extern "C" fn(this: &mut BSSmallBlockAllocator, size: usize, align: u32) -> *mut u8,
177}