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