xref: /linux/drivers/android/binder/range_alloc/mod.rs (revision eafedbc7c050c44744fbdf80bdf3315e860b7513)
1*eafedbc7SAlice Ryhl // SPDX-License-Identifier: GPL-2.0
2*eafedbc7SAlice Ryhl 
3*eafedbc7SAlice Ryhl // Copyright (C) 2025 Google LLC.
4*eafedbc7SAlice Ryhl 
5*eafedbc7SAlice Ryhl use kernel::{page::PAGE_SIZE, prelude::*, seq_file::SeqFile, task::Pid};
6*eafedbc7SAlice Ryhl 
7*eafedbc7SAlice Ryhl mod tree;
8*eafedbc7SAlice Ryhl use self::tree::{FromArrayAllocs, ReserveNewTreeAlloc, TreeRangeAllocator};
9*eafedbc7SAlice Ryhl 
10*eafedbc7SAlice Ryhl mod array;
11*eafedbc7SAlice Ryhl use self::array::{ArrayRangeAllocator, EmptyArrayAlloc};
12*eafedbc7SAlice Ryhl 
13*eafedbc7SAlice Ryhl enum DescriptorState<T> {
14*eafedbc7SAlice Ryhl     Reserved(Reservation),
15*eafedbc7SAlice Ryhl     Allocated(Allocation<T>),
16*eafedbc7SAlice Ryhl }
17*eafedbc7SAlice Ryhl 
18*eafedbc7SAlice Ryhl impl<T> DescriptorState<T> {
19*eafedbc7SAlice Ryhl     fn new(is_oneway: bool, debug_id: usize, pid: Pid) -> Self {
20*eafedbc7SAlice Ryhl         DescriptorState::Reserved(Reservation {
21*eafedbc7SAlice Ryhl             debug_id,
22*eafedbc7SAlice Ryhl             is_oneway,
23*eafedbc7SAlice Ryhl             pid,
24*eafedbc7SAlice Ryhl         })
25*eafedbc7SAlice Ryhl     }
26*eafedbc7SAlice Ryhl 
27*eafedbc7SAlice Ryhl     fn pid(&self) -> Pid {
28*eafedbc7SAlice Ryhl         match self {
29*eafedbc7SAlice Ryhl             DescriptorState::Reserved(inner) => inner.pid,
30*eafedbc7SAlice Ryhl             DescriptorState::Allocated(inner) => inner.reservation.pid,
31*eafedbc7SAlice Ryhl         }
32*eafedbc7SAlice Ryhl     }
33*eafedbc7SAlice Ryhl 
34*eafedbc7SAlice Ryhl     fn is_oneway(&self) -> bool {
35*eafedbc7SAlice Ryhl         match self {
36*eafedbc7SAlice Ryhl             DescriptorState::Reserved(inner) => inner.is_oneway,
37*eafedbc7SAlice Ryhl             DescriptorState::Allocated(inner) => inner.reservation.is_oneway,
38*eafedbc7SAlice Ryhl         }
39*eafedbc7SAlice Ryhl     }
40*eafedbc7SAlice Ryhl }
41*eafedbc7SAlice Ryhl 
42*eafedbc7SAlice Ryhl #[derive(Clone)]
43*eafedbc7SAlice Ryhl struct Reservation {
44*eafedbc7SAlice Ryhl     debug_id: usize,
45*eafedbc7SAlice Ryhl     is_oneway: bool,
46*eafedbc7SAlice Ryhl     pid: Pid,
47*eafedbc7SAlice Ryhl }
48*eafedbc7SAlice Ryhl 
49*eafedbc7SAlice Ryhl impl Reservation {
50*eafedbc7SAlice Ryhl     fn allocate<T>(self, data: Option<T>) -> Allocation<T> {
51*eafedbc7SAlice Ryhl         Allocation {
52*eafedbc7SAlice Ryhl             data,
53*eafedbc7SAlice Ryhl             reservation: self,
54*eafedbc7SAlice Ryhl         }
55*eafedbc7SAlice Ryhl     }
56*eafedbc7SAlice Ryhl }
57*eafedbc7SAlice Ryhl 
58*eafedbc7SAlice Ryhl struct Allocation<T> {
59*eafedbc7SAlice Ryhl     reservation: Reservation,
60*eafedbc7SAlice Ryhl     data: Option<T>,
61*eafedbc7SAlice Ryhl }
62*eafedbc7SAlice Ryhl 
63*eafedbc7SAlice Ryhl impl<T> Allocation<T> {
64*eafedbc7SAlice Ryhl     fn deallocate(self) -> (Reservation, Option<T>) {
65*eafedbc7SAlice Ryhl         (self.reservation, self.data)
66*eafedbc7SAlice Ryhl     }
67*eafedbc7SAlice Ryhl 
68*eafedbc7SAlice Ryhl     fn debug_id(&self) -> usize {
69*eafedbc7SAlice Ryhl         self.reservation.debug_id
70*eafedbc7SAlice Ryhl     }
71*eafedbc7SAlice Ryhl 
72*eafedbc7SAlice Ryhl     fn take(&mut self) -> Option<T> {
73*eafedbc7SAlice Ryhl         self.data.take()
74*eafedbc7SAlice Ryhl     }
75*eafedbc7SAlice Ryhl }
76*eafedbc7SAlice Ryhl 
77*eafedbc7SAlice Ryhl /// The array implementation must switch to the tree if it wants to go beyond this number of
78*eafedbc7SAlice Ryhl /// ranges.
79*eafedbc7SAlice Ryhl const TREE_THRESHOLD: usize = 8;
80*eafedbc7SAlice Ryhl 
81*eafedbc7SAlice Ryhl /// Represents a range of pages that have just become completely free.
82*eafedbc7SAlice Ryhl #[derive(Copy, Clone)]
83*eafedbc7SAlice Ryhl pub(crate) struct FreedRange {
84*eafedbc7SAlice Ryhl     pub(crate) start_page_idx: usize,
85*eafedbc7SAlice Ryhl     pub(crate) end_page_idx: usize,
86*eafedbc7SAlice Ryhl }
87*eafedbc7SAlice Ryhl 
88*eafedbc7SAlice Ryhl impl FreedRange {
89*eafedbc7SAlice Ryhl     fn interior_pages(offset: usize, size: usize) -> FreedRange {
90*eafedbc7SAlice Ryhl         FreedRange {
91*eafedbc7SAlice Ryhl             // Divide round up
92*eafedbc7SAlice Ryhl             start_page_idx: offset.div_ceil(PAGE_SIZE),
93*eafedbc7SAlice Ryhl             // Divide round down
94*eafedbc7SAlice Ryhl             end_page_idx: (offset + size) / PAGE_SIZE,
95*eafedbc7SAlice Ryhl         }
96*eafedbc7SAlice Ryhl     }
97*eafedbc7SAlice Ryhl }
98*eafedbc7SAlice Ryhl 
99*eafedbc7SAlice Ryhl struct Range<T> {
100*eafedbc7SAlice Ryhl     offset: usize,
101*eafedbc7SAlice Ryhl     size: usize,
102*eafedbc7SAlice Ryhl     state: DescriptorState<T>,
103*eafedbc7SAlice Ryhl }
104*eafedbc7SAlice Ryhl 
105*eafedbc7SAlice Ryhl impl<T> Range<T> {
106*eafedbc7SAlice Ryhl     fn endpoint(&self) -> usize {
107*eafedbc7SAlice Ryhl         self.offset + self.size
108*eafedbc7SAlice Ryhl     }
109*eafedbc7SAlice Ryhl }
110*eafedbc7SAlice Ryhl 
111*eafedbc7SAlice Ryhl pub(crate) struct RangeAllocator<T> {
112*eafedbc7SAlice Ryhl     inner: Impl<T>,
113*eafedbc7SAlice Ryhl }
114*eafedbc7SAlice Ryhl 
115*eafedbc7SAlice Ryhl enum Impl<T> {
116*eafedbc7SAlice Ryhl     Empty(usize),
117*eafedbc7SAlice Ryhl     Array(ArrayRangeAllocator<T>),
118*eafedbc7SAlice Ryhl     Tree(TreeRangeAllocator<T>),
119*eafedbc7SAlice Ryhl }
120*eafedbc7SAlice Ryhl 
121*eafedbc7SAlice Ryhl impl<T> RangeAllocator<T> {
122*eafedbc7SAlice Ryhl     pub(crate) fn new(size: usize) -> Self {
123*eafedbc7SAlice Ryhl         Self {
124*eafedbc7SAlice Ryhl             inner: Impl::Empty(size),
125*eafedbc7SAlice Ryhl         }
126*eafedbc7SAlice Ryhl     }
127*eafedbc7SAlice Ryhl 
128*eafedbc7SAlice Ryhl     pub(crate) fn free_oneway_space(&self) -> usize {
129*eafedbc7SAlice Ryhl         match &self.inner {
130*eafedbc7SAlice Ryhl             Impl::Empty(size) => size / 2,
131*eafedbc7SAlice Ryhl             Impl::Array(array) => array.free_oneway_space(),
132*eafedbc7SAlice Ryhl             Impl::Tree(tree) => tree.free_oneway_space(),
133*eafedbc7SAlice Ryhl         }
134*eafedbc7SAlice Ryhl     }
135*eafedbc7SAlice Ryhl 
136*eafedbc7SAlice Ryhl     pub(crate) fn count_buffers(&self) -> usize {
137*eafedbc7SAlice Ryhl         match &self.inner {
138*eafedbc7SAlice Ryhl             Impl::Empty(_size) => 0,
139*eafedbc7SAlice Ryhl             Impl::Array(array) => array.count_buffers(),
140*eafedbc7SAlice Ryhl             Impl::Tree(tree) => tree.count_buffers(),
141*eafedbc7SAlice Ryhl         }
142*eafedbc7SAlice Ryhl     }
143*eafedbc7SAlice Ryhl 
144*eafedbc7SAlice Ryhl     pub(crate) fn debug_print(&self, m: &SeqFile) -> Result<()> {
145*eafedbc7SAlice Ryhl         match &self.inner {
146*eafedbc7SAlice Ryhl             Impl::Empty(_size) => Ok(()),
147*eafedbc7SAlice Ryhl             Impl::Array(array) => array.debug_print(m),
148*eafedbc7SAlice Ryhl             Impl::Tree(tree) => tree.debug_print(m),
149*eafedbc7SAlice Ryhl         }
150*eafedbc7SAlice Ryhl     }
151*eafedbc7SAlice Ryhl 
152*eafedbc7SAlice Ryhl     /// Try to reserve a new buffer, using the provided allocation if necessary.
153*eafedbc7SAlice Ryhl     pub(crate) fn reserve_new(&mut self, mut args: ReserveNewArgs<T>) -> Result<ReserveNew<T>> {
154*eafedbc7SAlice Ryhl         match &mut self.inner {
155*eafedbc7SAlice Ryhl             Impl::Empty(size) => {
156*eafedbc7SAlice Ryhl                 let empty_array = match args.empty_array_alloc.take() {
157*eafedbc7SAlice Ryhl                     Some(empty_array) => ArrayRangeAllocator::new(*size, empty_array),
158*eafedbc7SAlice Ryhl                     None => {
159*eafedbc7SAlice Ryhl                         return Ok(ReserveNew::NeedAlloc(ReserveNewNeedAlloc {
160*eafedbc7SAlice Ryhl                             args,
161*eafedbc7SAlice Ryhl                             need_empty_array_alloc: true,
162*eafedbc7SAlice Ryhl                             need_new_tree_alloc: false,
163*eafedbc7SAlice Ryhl                             need_tree_alloc: false,
164*eafedbc7SAlice Ryhl                         }))
165*eafedbc7SAlice Ryhl                     }
166*eafedbc7SAlice Ryhl                 };
167*eafedbc7SAlice Ryhl 
168*eafedbc7SAlice Ryhl                 self.inner = Impl::Array(empty_array);
169*eafedbc7SAlice Ryhl                 self.reserve_new(args)
170*eafedbc7SAlice Ryhl             }
171*eafedbc7SAlice Ryhl             Impl::Array(array) if array.is_full() => {
172*eafedbc7SAlice Ryhl                 let allocs = match args.new_tree_alloc {
173*eafedbc7SAlice Ryhl                     Some(ref mut allocs) => allocs,
174*eafedbc7SAlice Ryhl                     None => {
175*eafedbc7SAlice Ryhl                         return Ok(ReserveNew::NeedAlloc(ReserveNewNeedAlloc {
176*eafedbc7SAlice Ryhl                             args,
177*eafedbc7SAlice Ryhl                             need_empty_array_alloc: false,
178*eafedbc7SAlice Ryhl                             need_new_tree_alloc: true,
179*eafedbc7SAlice Ryhl                             need_tree_alloc: true,
180*eafedbc7SAlice Ryhl                         }))
181*eafedbc7SAlice Ryhl                     }
182*eafedbc7SAlice Ryhl                 };
183*eafedbc7SAlice Ryhl 
184*eafedbc7SAlice Ryhl                 let new_tree =
185*eafedbc7SAlice Ryhl                     TreeRangeAllocator::from_array(array.total_size(), &mut array.ranges, allocs);
186*eafedbc7SAlice Ryhl 
187*eafedbc7SAlice Ryhl                 self.inner = Impl::Tree(new_tree);
188*eafedbc7SAlice Ryhl                 self.reserve_new(args)
189*eafedbc7SAlice Ryhl             }
190*eafedbc7SAlice Ryhl             Impl::Array(array) => {
191*eafedbc7SAlice Ryhl                 let offset =
192*eafedbc7SAlice Ryhl                     array.reserve_new(args.debug_id, args.size, args.is_oneway, args.pid)?;
193*eafedbc7SAlice Ryhl                 Ok(ReserveNew::Success(ReserveNewSuccess {
194*eafedbc7SAlice Ryhl                     offset,
195*eafedbc7SAlice Ryhl                     oneway_spam_detected: false,
196*eafedbc7SAlice Ryhl                     _empty_array_alloc: args.empty_array_alloc,
197*eafedbc7SAlice Ryhl                     _new_tree_alloc: args.new_tree_alloc,
198*eafedbc7SAlice Ryhl                     _tree_alloc: args.tree_alloc,
199*eafedbc7SAlice Ryhl                 }))
200*eafedbc7SAlice Ryhl             }
201*eafedbc7SAlice Ryhl             Impl::Tree(tree) => {
202*eafedbc7SAlice Ryhl                 let alloc = match args.tree_alloc {
203*eafedbc7SAlice Ryhl                     Some(alloc) => alloc,
204*eafedbc7SAlice Ryhl                     None => {
205*eafedbc7SAlice Ryhl                         return Ok(ReserveNew::NeedAlloc(ReserveNewNeedAlloc {
206*eafedbc7SAlice Ryhl                             args,
207*eafedbc7SAlice Ryhl                             need_empty_array_alloc: false,
208*eafedbc7SAlice Ryhl                             need_new_tree_alloc: false,
209*eafedbc7SAlice Ryhl                             need_tree_alloc: true,
210*eafedbc7SAlice Ryhl                         }));
211*eafedbc7SAlice Ryhl                     }
212*eafedbc7SAlice Ryhl                 };
213*eafedbc7SAlice Ryhl                 let (offset, oneway_spam_detected) =
214*eafedbc7SAlice Ryhl                     tree.reserve_new(args.debug_id, args.size, args.is_oneway, args.pid, alloc)?;
215*eafedbc7SAlice Ryhl                 Ok(ReserveNew::Success(ReserveNewSuccess {
216*eafedbc7SAlice Ryhl                     offset,
217*eafedbc7SAlice Ryhl                     oneway_spam_detected,
218*eafedbc7SAlice Ryhl                     _empty_array_alloc: args.empty_array_alloc,
219*eafedbc7SAlice Ryhl                     _new_tree_alloc: args.new_tree_alloc,
220*eafedbc7SAlice Ryhl                     _tree_alloc: None,
221*eafedbc7SAlice Ryhl                 }))
222*eafedbc7SAlice Ryhl             }
223*eafedbc7SAlice Ryhl         }
224*eafedbc7SAlice Ryhl     }
225*eafedbc7SAlice Ryhl 
226*eafedbc7SAlice Ryhl     /// Deletes the allocations at `offset`.
227*eafedbc7SAlice Ryhl     pub(crate) fn reservation_abort(&mut self, offset: usize) -> Result<FreedRange> {
228*eafedbc7SAlice Ryhl         match &mut self.inner {
229*eafedbc7SAlice Ryhl             Impl::Empty(_size) => Err(EINVAL),
230*eafedbc7SAlice Ryhl             Impl::Array(array) => array.reservation_abort(offset),
231*eafedbc7SAlice Ryhl             Impl::Tree(tree) => {
232*eafedbc7SAlice Ryhl                 let freed_range = tree.reservation_abort(offset)?;
233*eafedbc7SAlice Ryhl                 if tree.is_empty() {
234*eafedbc7SAlice Ryhl                     self.inner = Impl::Empty(tree.total_size());
235*eafedbc7SAlice Ryhl                 }
236*eafedbc7SAlice Ryhl                 Ok(freed_range)
237*eafedbc7SAlice Ryhl             }
238*eafedbc7SAlice Ryhl         }
239*eafedbc7SAlice Ryhl     }
240*eafedbc7SAlice Ryhl 
241*eafedbc7SAlice Ryhl     /// Called when an allocation is no longer in use by the kernel.
242*eafedbc7SAlice Ryhl     ///
243*eafedbc7SAlice Ryhl     /// The value in `data` will be stored, if any. A mutable reference is used to avoid dropping
244*eafedbc7SAlice Ryhl     /// the `T` when an error is returned.
245*eafedbc7SAlice Ryhl     pub(crate) fn reservation_commit(&mut self, offset: usize, data: &mut Option<T>) -> Result {
246*eafedbc7SAlice Ryhl         match &mut self.inner {
247*eafedbc7SAlice Ryhl             Impl::Empty(_size) => Err(EINVAL),
248*eafedbc7SAlice Ryhl             Impl::Array(array) => array.reservation_commit(offset, data),
249*eafedbc7SAlice Ryhl             Impl::Tree(tree) => tree.reservation_commit(offset, data),
250*eafedbc7SAlice Ryhl         }
251*eafedbc7SAlice Ryhl     }
252*eafedbc7SAlice Ryhl 
253*eafedbc7SAlice Ryhl     /// Called when the kernel starts using an allocation.
254*eafedbc7SAlice Ryhl     ///
255*eafedbc7SAlice Ryhl     /// Returns the size of the existing entry and the data associated with it.
256*eafedbc7SAlice Ryhl     pub(crate) fn reserve_existing(&mut self, offset: usize) -> Result<(usize, usize, Option<T>)> {
257*eafedbc7SAlice Ryhl         match &mut self.inner {
258*eafedbc7SAlice Ryhl             Impl::Empty(_size) => Err(EINVAL),
259*eafedbc7SAlice Ryhl             Impl::Array(array) => array.reserve_existing(offset),
260*eafedbc7SAlice Ryhl             Impl::Tree(tree) => tree.reserve_existing(offset),
261*eafedbc7SAlice Ryhl         }
262*eafedbc7SAlice Ryhl     }
263*eafedbc7SAlice Ryhl 
264*eafedbc7SAlice Ryhl     /// Call the provided callback at every allocated region.
265*eafedbc7SAlice Ryhl     ///
266*eafedbc7SAlice Ryhl     /// This destroys the range allocator. Used only during shutdown.
267*eafedbc7SAlice Ryhl     pub(crate) fn take_for_each<F: Fn(usize, usize, usize, Option<T>)>(&mut self, callback: F) {
268*eafedbc7SAlice Ryhl         match &mut self.inner {
269*eafedbc7SAlice Ryhl             Impl::Empty(_size) => {}
270*eafedbc7SAlice Ryhl             Impl::Array(array) => array.take_for_each(callback),
271*eafedbc7SAlice Ryhl             Impl::Tree(tree) => tree.take_for_each(callback),
272*eafedbc7SAlice Ryhl         }
273*eafedbc7SAlice Ryhl     }
274*eafedbc7SAlice Ryhl }
275*eafedbc7SAlice Ryhl 
276*eafedbc7SAlice Ryhl /// The arguments for `reserve_new`.
277*eafedbc7SAlice Ryhl #[derive(Default)]
278*eafedbc7SAlice Ryhl pub(crate) struct ReserveNewArgs<T> {
279*eafedbc7SAlice Ryhl     pub(crate) size: usize,
280*eafedbc7SAlice Ryhl     pub(crate) is_oneway: bool,
281*eafedbc7SAlice Ryhl     pub(crate) debug_id: usize,
282*eafedbc7SAlice Ryhl     pub(crate) pid: Pid,
283*eafedbc7SAlice Ryhl     pub(crate) empty_array_alloc: Option<EmptyArrayAlloc<T>>,
284*eafedbc7SAlice Ryhl     pub(crate) new_tree_alloc: Option<FromArrayAllocs<T>>,
285*eafedbc7SAlice Ryhl     pub(crate) tree_alloc: Option<ReserveNewTreeAlloc<T>>,
286*eafedbc7SAlice Ryhl }
287*eafedbc7SAlice Ryhl 
288*eafedbc7SAlice Ryhl /// The return type of `ReserveNew`.
289*eafedbc7SAlice Ryhl pub(crate) enum ReserveNew<T> {
290*eafedbc7SAlice Ryhl     Success(ReserveNewSuccess<T>),
291*eafedbc7SAlice Ryhl     NeedAlloc(ReserveNewNeedAlloc<T>),
292*eafedbc7SAlice Ryhl }
293*eafedbc7SAlice Ryhl 
294*eafedbc7SAlice Ryhl /// Returned by `reserve_new` when the reservation was successul.
295*eafedbc7SAlice Ryhl pub(crate) struct ReserveNewSuccess<T> {
296*eafedbc7SAlice Ryhl     pub(crate) offset: usize,
297*eafedbc7SAlice Ryhl     pub(crate) oneway_spam_detected: bool,
298*eafedbc7SAlice Ryhl 
299*eafedbc7SAlice Ryhl     // If the user supplied an allocation that we did not end up using, then we return it here.
300*eafedbc7SAlice Ryhl     // The caller will kfree it outside of the lock.
301*eafedbc7SAlice Ryhl     _empty_array_alloc: Option<EmptyArrayAlloc<T>>,
302*eafedbc7SAlice Ryhl     _new_tree_alloc: Option<FromArrayAllocs<T>>,
303*eafedbc7SAlice Ryhl     _tree_alloc: Option<ReserveNewTreeAlloc<T>>,
304*eafedbc7SAlice Ryhl }
305*eafedbc7SAlice Ryhl 
306*eafedbc7SAlice Ryhl /// Returned by `reserve_new` to request the caller to make an allocation before calling the method
307*eafedbc7SAlice Ryhl /// again.
308*eafedbc7SAlice Ryhl pub(crate) struct ReserveNewNeedAlloc<T> {
309*eafedbc7SAlice Ryhl     args: ReserveNewArgs<T>,
310*eafedbc7SAlice Ryhl     need_empty_array_alloc: bool,
311*eafedbc7SAlice Ryhl     need_new_tree_alloc: bool,
312*eafedbc7SAlice Ryhl     need_tree_alloc: bool,
313*eafedbc7SAlice Ryhl }
314*eafedbc7SAlice Ryhl 
315*eafedbc7SAlice Ryhl impl<T> ReserveNewNeedAlloc<T> {
316*eafedbc7SAlice Ryhl     /// Make the necessary allocations for another call to `reserve_new`.
317*eafedbc7SAlice Ryhl     pub(crate) fn make_alloc(mut self) -> Result<ReserveNewArgs<T>> {
318*eafedbc7SAlice Ryhl         if self.need_empty_array_alloc && self.args.empty_array_alloc.is_none() {
319*eafedbc7SAlice Ryhl             self.args.empty_array_alloc = Some(EmptyArrayAlloc::try_new(TREE_THRESHOLD)?);
320*eafedbc7SAlice Ryhl         }
321*eafedbc7SAlice Ryhl         if self.need_new_tree_alloc && self.args.new_tree_alloc.is_none() {
322*eafedbc7SAlice Ryhl             self.args.new_tree_alloc = Some(FromArrayAllocs::try_new(TREE_THRESHOLD)?);
323*eafedbc7SAlice Ryhl         }
324*eafedbc7SAlice Ryhl         if self.need_tree_alloc && self.args.tree_alloc.is_none() {
325*eafedbc7SAlice Ryhl             self.args.tree_alloc = Some(ReserveNewTreeAlloc::try_new()?);
326*eafedbc7SAlice Ryhl         }
327*eafedbc7SAlice Ryhl         Ok(self.args)
328*eafedbc7SAlice Ryhl     }
329*eafedbc7SAlice Ryhl }
330