1pub use self::boxed::*;
2pub use self::slab::StdFree;
3pub use self::zone::*;
4
5pub(self) use self::keg::*;
6pub(self) use self::slab::{FreeItem, Slab, SlabHdr};
7
8use self::bucket::{BucketItem, UmaBucket};
9use crate::config::PAGE_SIZE;
10use crate::vm::Vm;
11use alloc::format;
12use alloc::string::String;
13use alloc::sync::Arc;
14use alloc::vec::Vec;
15use core::alloc::Layout;
16use core::num::NonZero;
17use core::sync::atomic::AtomicBool;
18use macros::bitflag;
19
20#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
21#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
22mod arch;
23mod boxed;
24mod bucket;
25mod keg;
26mod slab;
27mod zone;
28
29pub struct Uma {
31 vm: Arc<Vm>,
32 bucket_enable: Arc<AtomicBool>,
33 bucket_keys: Arc<Vec<usize>>, bucket_zones: Arc<Vec<UmaZone<StdFree>>>, }
36
37impl Uma {
38 const SMALLEST_UNIT: NonZero<usize> = NonZero::new(PAGE_SIZE.get() / 256).unwrap();
40
41 const MAX_WASTE: NonZero<usize> = NonZero::new(PAGE_SIZE.get() / 10).unwrap();
43 const BUCKET_MAX: usize = 128;
44 const BUCKET_SHIFT: usize = 4;
45
46 const BUCKET_SIZES: [usize; 4] = [16, 32, 64, 128];
48
49 pub fn new(vm: Arc<Vm>) -> Arc<Self> {
56 let bucket_enable = Arc::new(AtomicBool::new(true)); let mut bucket_keys = Vec::new();
58 let mut bucket_zones = Vec::with_capacity(Self::BUCKET_SIZES.len());
59 let mut ki = 0;
60
61 for (si, size) in Self::BUCKET_SIZES.into_iter().enumerate() {
63 let items = Layout::array::<BucketItem>(size).unwrap();
64 let layout = Layout::new::<UmaBucket<()>>()
65 .extend(items)
66 .unwrap()
67 .0
68 .pad_to_align();
69
70 bucket_zones.push(UmaZone::new(
71 vm.clone(),
72 bucket_enable.clone(),
73 Arc::default(),
74 Arc::default(),
75 format!("{size} Bucket"),
76 None,
77 layout.size().try_into().unwrap(),
78 Some(layout.align() - 1),
79 None,
80 UmaFlags::Bucket | UmaFlags::Internal,
81 ));
82
83 while ki <= size {
84 bucket_keys.push(si);
85 ki += 1 << Self::BUCKET_SHIFT;
86 }
87 }
88
89 Arc::new(Self {
90 vm,
91 bucket_enable,
92 bucket_keys: Arc::new(bucket_keys),
93 bucket_zones: Arc::new(bucket_zones),
94 })
95 }
96
97 pub fn create_zone<T: FreeItem>(
104 &self,
105 name: impl Into<String>,
106 size: NonZero<usize>,
107 align: Option<usize>,
108 init: Option<fn()>,
109 flags: impl Into<UmaFlags>,
110 ) -> UmaZone<T> {
111 UmaZone::new(
114 self.vm.clone(),
115 self.bucket_enable.clone(),
116 self.bucket_keys.clone(),
117 self.bucket_zones.clone(),
118 name,
119 None,
120 size,
121 align,
122 init,
123 flags,
124 )
125 }
126}
127
128#[bitflag(u32)]
130pub enum UmaFlags {
131 ZInit = 0x2,
133 Offpage = 0x8,
135 Malloc = 0x10,
137 MtxClass = 0x40,
139 Vm = 0x80,
141 Hash = 0x100,
143 Secondary = 0x200,
145 MaxBucket = 0x800,
147 CacheSpread = 0x1000,
149 VToSlab = 0x2000,
151 Bucket = 0x2000000,
153 Internal = 0x20000000,
155 CacheOnly = 0x80000000,
157}
158
159#[bitflag(u32)]
161pub enum Alloc {
162 NoWait = 0x1,
164 Wait = 0x2,
166 Zero = 0x100,
168 NoVm = 0x200,
170}