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 UmaFlags::Bucket | UmaFlags::Internal,
76 ));
77
78 while ki <= size {
79 bucket_keys.push(si);
80 ki += 1 << Self::BUCKET_SHIFT;
81 }
82 }
83
84 Arc::new(Self {
85 vm,
86 bucket_enable,
87 bucket_keys: Arc::new(bucket_keys),
88 bucket_zones: Arc::new(bucket_zones),
89 })
90 }
91
92 pub fn create_zone(
99 &self,
100 name: impl Into<String>,
101 size: NonZero<usize>,
102 align: Option<usize>,
103 flags: impl Into<UmaFlags>,
104 ) -> UmaZone {
105 UmaZone::new(
108 self.vm.clone(),
109 self.bucket_enable.clone(),
110 self.bucket_keys.clone(),
111 self.bucket_zones.clone(),
112 name,
113 None,
114 size,
115 align,
116 flags,
117 )
118 }
119}
120
121#[bitflag(u32)]
123pub enum UmaFlags {
124 ZInit = 0x2,
126 Offpage = 0x8,
128 Malloc = 0x10,
130 MtxClass = 0x40,
132 Vm = 0x80,
134 Hash = 0x100,
136 Secondary = 0x200,
138 RefCnt = 0x400,
140 MaxBucket = 0x800,
142 CacheSpread = 0x1000,
144 VToSlab = 0x2000,
146 Bucket = 0x2000000,
148 Internal = 0x20000000,
150 CacheOnly = 0x80000000,
152}
153
154#[bitflag(u32)]
156pub enum Alloc {
157 NoWait = 0x1,
159 Wait = 0x2,
161 Zero = 0x100,
163 NoVm = 0x200,
165}