Skip to content

Commit dfaa42f

Browse files
authored
Merge pull request #403 from wedsonaf/remove-btreemap
Replace all usages of `BTreeMap` with `RBTree`.
2 parents 2b9530d + e3b5b78 commit dfaa42f

File tree

2 files changed

+48
-29
lines changed

2 files changed

+48
-29
lines changed

drivers/android/process.rs

+42-28
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// SPDX-License-Identifier: GPL-2.0
22

3-
use alloc::{collections::btree_map::BTreeMap, sync::Arc, vec::Vec};
3+
use alloc::{sync::Arc, vec::Vec};
44
use core::{
5-
mem::{swap, MaybeUninit},
5+
mem::{take, MaybeUninit},
66
ops::Range,
77
pin::Pin,
88
};
@@ -14,6 +14,7 @@ use kernel::{
1414
linked_list::List,
1515
pages::Pages,
1616
prelude::*,
17+
rbtree::RBTree,
1718
sync::{Guard, Mutex, Ref},
1819
user_ptr::{UserSlicePtr, UserSlicePtrReader},
1920
Error,
@@ -62,11 +63,11 @@ impl Mapping {
6263
pub(crate) struct ProcessInner {
6364
is_manager: bool,
6465
is_dead: bool,
65-
threads: BTreeMap<i32, Arc<Thread>>,
66+
threads: RBTree<i32, Arc<Thread>>,
6667
ready_threads: List<Arc<Thread>>,
6768
work: List<DeliverToReadListAdapter>,
6869
mapping: Option<Mapping>,
69-
nodes: BTreeMap<usize, Arc<Node>>,
70+
nodes: RBTree<usize, Arc<Node>>,
7071

7172
delivered_deaths: List<Arc<NodeDeath>>,
7273

@@ -85,11 +86,11 @@ impl ProcessInner {
8586
Self {
8687
is_manager: false,
8788
is_dead: false,
88-
threads: BTreeMap::new(),
89+
threads: RBTree::new(),
8990
ready_threads: List::new(),
9091
work: List::new(),
9192
mapping: None,
92-
nodes: BTreeMap::new(),
93+
nodes: RBTree::new(),
9394
requested_thread_count: 0,
9495
max_threads: 0,
9596
started_thread_count: 0,
@@ -260,25 +261,25 @@ impl NodeRefInfo {
260261
}
261262

262263
struct ProcessNodeRefs {
263-
by_handle: BTreeMap<u32, NodeRefInfo>,
264-
by_global_id: BTreeMap<u64, u32>,
264+
by_handle: RBTree<u32, NodeRefInfo>,
265+
by_global_id: RBTree<u64, u32>,
265266
}
266267

267268
impl ProcessNodeRefs {
268269
fn new() -> Self {
269270
Self {
270-
by_handle: BTreeMap::new(),
271-
by_global_id: BTreeMap::new(),
271+
by_handle: RBTree::new(),
272+
by_global_id: RBTree::new(),
272273
}
273274
}
274275
}
275276

276277
pub(crate) struct Process {
277278
ctx: Ref<Context>,
278279

279-
// TODO: For now this a mutex because we have allocations in BTreeMap and RangeAllocator while
280-
// holding the lock. We may want to split up the process state at some point to use a spin lock
281-
// for the other fields; we can also get rid of allocations in BTreeMap once we replace it.
280+
// TODO: For now this a mutex because we have allocations in RangeAllocator while holding the
281+
// lock. We may want to split up the process state at some point to use a spin lock for the
282+
// other fields.
282283
// TODO: Make this private again.
283284
pub(crate) inner: Mutex<ProcessInner>,
284285

@@ -348,6 +349,7 @@ impl Process {
348349

349350
// Allocate a new `Thread` without holding any locks.
350351
let ta = Thread::new(id, self.clone())?;
352+
let node = RBTree::try_allocate_node(id, ta.clone())?;
351353

352354
let mut inner = self.inner.lock();
353355

@@ -356,9 +358,7 @@ impl Process {
356358
return Ok(thread.clone());
357359
}
358360

359-
// TODO: We need a better solution here. Since this allocates, we cannot do it while
360-
// holding a spinlock because it could block. It could panic too.
361-
inner.threads.insert(id, ta.clone());
361+
inner.threads.insert(node);
362362
Ok(ta)
363363
}
364364

@@ -407,14 +407,14 @@ impl Process {
407407

408408
// Allocate the node before reacquiring the lock.
409409
let node = Arc::try_new(Node::new(ptr, cookie, flags, self.clone()))?;
410+
let rbnode = RBTree::try_allocate_node(ptr, node.clone())?;
410411

411412
let mut inner = self.inner.lock();
412413
if let Some(node) = inner.get_existing_node_ref(ptr, cookie, strong, thread)? {
413414
return Ok(node);
414415
}
415416

416-
// TODO: Avoid allocation while holding lock.
417-
inner.nodes.insert(ptr, node.clone());
417+
inner.nodes.insert(rbnode);
418418
Ok(inner.new_node_ref(node, strong, thread))
419419
}
420420

@@ -423,9 +423,25 @@ impl Process {
423423
node_ref: NodeRef,
424424
is_mananger: bool,
425425
) -> Result<u32> {
426+
{
427+
let mut refs = self.node_refs.lock();
428+
429+
// Do a lookup before inserting.
430+
if let Some(handle_ref) = refs.by_global_id.get(&node_ref.node.global_id) {
431+
let handle = *handle_ref;
432+
let info = refs.by_handle.get_mut(&handle).unwrap();
433+
info.node_ref.absorb(node_ref);
434+
return Ok(handle);
435+
}
436+
}
437+
438+
// Reserve memory for tree nodes.
439+
let reserve1 = RBTree::try_reserve_node()?;
440+
let reserve2 = RBTree::try_reserve_node()?;
441+
426442
let mut refs = self.node_refs.lock();
427443

428-
// Do a lookup before inserting.
444+
// Do a lookup again as node may have been inserted before the lock was reacquired.
429445
if let Some(handle_ref) = refs.by_global_id.get(&node_ref.node.global_id) {
430446
let handle = *handle_ref;
431447
let info = refs.by_handle.get_mut(&handle).unwrap();
@@ -449,9 +465,10 @@ impl Process {
449465
if inner.is_dead {
450466
return Err(Error::ESRCH);
451467
}
452-
// TODO: Two allocations below.
453-
refs.by_global_id.insert(node_ref.node.global_id, target);
454-
refs.by_handle.insert(target, NodeRefInfo::new(node_ref));
468+
refs.by_global_id
469+
.insert(reserve1.into_node(node_ref.node.global_id, target));
470+
refs.by_handle
471+
.insert(reserve2.into_node(target, NodeRefInfo::new(node_ref)));
455472
Ok(target)
456473
}
457474

@@ -853,8 +870,7 @@ impl FileOperations for Process {
853870
// Drop all references. We do this dance with `swap` to avoid destroying the references
854871
// while holding the lock.
855872
let mut refs = obj.node_refs.lock();
856-
let mut node_refs = BTreeMap::new();
857-
swap(&mut refs.by_handle, &mut node_refs);
873+
let mut node_refs = take(&mut refs.by_handle);
858874
drop(refs);
859875

860876
// Remove all death notifications from the nodes (that belong to a different process).
@@ -870,10 +886,8 @@ impl FileOperations for Process {
870886

871887
// Do similar dance for the state lock.
872888
let mut inner = obj.inner.lock();
873-
let mut threads = BTreeMap::new();
874-
let mut nodes = BTreeMap::new();
875-
swap(&mut inner.threads, &mut threads);
876-
swap(&mut inner.nodes, &mut nodes);
889+
let threads = take(&mut inner.threads);
890+
let nodes = take(&mut inner.nodes);
877891
drop(inner);
878892

879893
// Release all threads.

rust/kernel/rbtree.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,6 @@ struct Node<K, V> {
197197
/// Ok(())
198198
/// }
199199
/// ```
200-
#[derive(Default)]
201200
pub struct RBTree<K, V> {
202201
root: bindings::rb_root,
203202
_p: PhantomData<Node<K, V>>,
@@ -407,6 +406,12 @@ impl<K, V> RBTree<K, V> {
407406
}
408407
}
409408

409+
impl<K, V> Default for RBTree<K, V> {
410+
fn default() -> Self {
411+
Self::new()
412+
}
413+
}
414+
410415
impl<K, V> Drop for RBTree<K, V> {
411416
fn drop(&mut self) {
412417
// SAFETY: `root` is valid as it's embedded in `self` and we have a valid `self`.

0 commit comments

Comments
 (0)