Skip to content

Commit b4b5942

Browse files
author
Sven Van Asbroeck
committed
BENCHMARK ONLY: Rust binder: use Boxed versions of {Mutex, CondVar}
Replace all Mutexes and CondVars in Binder with their Boxed flavours, for the purpose of running Wedson's Binder benchmark. Note that this should allow elimination of many `Pin`ned structs in Binder. But I have not attempted that, as unnecessary `Pin`ning should not influence benchmark performance. Signed-off-by: Sven Van Asbroeck <[email protected]>
1 parent cdc5556 commit b4b5942

File tree

6 files changed

+61
-47
lines changed

6 files changed

+61
-47
lines changed

drivers/android/context.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ extern crate alloc;
44

55
use alloc::sync::Arc;
66
use core::pin::Pin;
7-
use kernel::{bindings, prelude::*, sync::Mutex, Error};
7+
use kernel::boxed_mutex;
8+
use kernel::{bindings, prelude::*, sync::BoxedMutex, Error};
89

910
use crate::{
1011
node::NodeRef,
@@ -17,28 +18,23 @@ struct Manager {
1718
}
1819

1920
pub(crate) struct Context {
20-
manager: Mutex<Manager>,
21+
manager: BoxedMutex<Manager>,
2122
}
2223

2324
unsafe impl Send for Context {}
2425
unsafe impl Sync for Context {}
2526

2627
impl Context {
2728
pub(crate) fn new() -> Result<Pin<Arc<Self>>> {
28-
let mut ctx_ref = Arc::try_new(Self {
29-
// SAFETY: Init is called below.
30-
manager: unsafe {
31-
Mutex::new(Manager {
29+
let ctx_ref = Arc::try_new(Self {
30+
manager: boxed_mutex!(
31+
Manager {
3232
node: None,
3333
uid: None,
34-
})
35-
},
34+
},
35+
"Context::manager"
36+
)?,
3637
})?;
37-
let ctx = Arc::get_mut(&mut ctx_ref).unwrap();
38-
39-
// SAFETY: `manager` is also pinned when `ctx` is.
40-
let manager = unsafe { Pin::new_unchecked(&ctx.manager) };
41-
kernel::mutex_init!(manager, "Context::manager");
4238

4339
// SAFETY: `ctx_ref` is pinned behind the `Arc` reference.
4440
Ok(unsafe { Pin::new_unchecked(ctx_ref) })

drivers/android/node.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use kernel::{
99
io_buffer::IoBufferWriter,
1010
linked_list::{GetLinks, Links, List},
1111
prelude::*,
12-
sync::{Guard, LockedBy, Mutex, Ref, SpinLock},
12+
sync::{BoxedMutex, Guard, LockedBy, Ref, SpinLock},
1313
user_ptr::UserSlicePtrWriter,
1414
};
1515

@@ -216,7 +216,7 @@ pub(crate) struct Node {
216216
cookie: usize,
217217
pub(crate) flags: u32,
218218
pub(crate) owner: Ref<Process>,
219-
inner: LockedBy<NodeInner, Mutex<ProcessInner>>,
219+
inner: LockedBy<NodeInner, BoxedMutex<ProcessInner>>,
220220
links: Links<dyn DeliverToRead>,
221221
}
222222

@@ -248,12 +248,16 @@ impl Node {
248248

249249
pub(crate) fn next_death(
250250
&self,
251-
guard: &mut Guard<Mutex<ProcessInner>>,
251+
guard: &mut Guard<BoxedMutex<ProcessInner>>,
252252
) -> Option<Arc<NodeDeath>> {
253253
self.inner.access_mut(guard).death_list.pop_front()
254254
}
255255

256-
pub(crate) fn add_death(&self, death: Arc<NodeDeath>, guard: &mut Guard<Mutex<ProcessInner>>) {
256+
pub(crate) fn add_death(
257+
&self,
258+
death: Arc<NodeDeath>,
259+
guard: &mut Guard<BoxedMutex<ProcessInner>>,
260+
) {
257261
self.inner.access_mut(guard).death_list.push_back(death);
258262
}
259263

@@ -306,7 +310,7 @@ impl Node {
306310
pub(crate) fn populate_counts(
307311
&self,
308312
out: &mut BinderNodeInfoForRef,
309-
guard: &Guard<Mutex<ProcessInner>>,
313+
guard: &Guard<BoxedMutex<ProcessInner>>,
310314
) {
311315
let inner = self.inner.access(guard);
312316
out.strong_count = inner.strong.count as _;
@@ -316,7 +320,7 @@ impl Node {
316320
pub(crate) fn populate_debug_info(
317321
&self,
318322
out: &mut BinderNodeDebugInfo,
319-
guard: &Guard<Mutex<ProcessInner>>,
323+
guard: &Guard<BoxedMutex<ProcessInner>>,
320324
) {
321325
out.ptr = self.ptr as _;
322326
out.cookie = self.cookie as _;
@@ -329,7 +333,7 @@ impl Node {
329333
}
330334
}
331335

332-
pub(crate) fn force_has_count(&self, guard: &mut Guard<Mutex<ProcessInner>>) {
336+
pub(crate) fn force_has_count(&self, guard: &mut Guard<BoxedMutex<ProcessInner>>) {
333337
let inner = self.inner.access_mut(guard);
334338
inner.strong.has_count = true;
335339
inner.weak.has_count = true;

drivers/android/process.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ use core::{
77
pin::Pin,
88
};
99
use kernel::{
10-
bindings, c_types,
10+
bindings, boxed_mutex, c_types,
1111
file::File,
1212
file_operations::{FileOpener, FileOperations, IoctlCommand, IoctlHandler, PollTable},
1313
io_buffer::{IoBufferReader, IoBufferWriter},
1414
linked_list::List,
1515
pages::Pages,
1616
prelude::*,
17-
sync::{Guard, Mutex, Ref, RefCount, RefCounted},
17+
sync::{BoxedMutex, Guard, Ref, RefCount, RefCounted},
1818
user_ptr::{UserSlicePtr, UserSlicePtrReader},
1919
Error,
2020
};
@@ -281,33 +281,25 @@ pub(crate) struct Process {
281281
// holding the lock. We may want to split up the process state at some point to use a spin lock
282282
// for the other fields; we can also get rid of allocations in BTreeMap once we replace it.
283283
// TODO: Make this private again.
284-
pub(crate) inner: Mutex<ProcessInner>,
284+
pub(crate) inner: BoxedMutex<ProcessInner>,
285285

286286
// References are in a different mutex to avoid recursive acquisition when
287287
// incrementing/decrementing a node in another process.
288-
node_refs: Mutex<ProcessNodeRefs>,
288+
node_refs: BoxedMutex<ProcessNodeRefs>,
289289
}
290290

291291
unsafe impl Send for Process {}
292292
unsafe impl Sync for Process {}
293293

294294
impl Process {
295295
fn new(ctx: Arc<Context>) -> Result<Ref<Self>> {
296-
let mut proc_ref = Ref::try_new(Self {
296+
let proc_ref = Ref::try_new(Self {
297297
ref_count: RefCount::new(),
298298
ctx,
299-
// SAFETY: `inner` is initialised in the call to `mutex_init` below.
300-
inner: unsafe { Mutex::new(ProcessInner::new()) },
299+
inner: boxed_mutex!(ProcessInner::new(), "Process::inner")?,
301300
// SAFETY: `node_refs` is initialised in the call to `mutex_init` below.
302-
node_refs: unsafe { Mutex::new(ProcessNodeRefs::new()) },
301+
node_refs: boxed_mutex!(ProcessNodeRefs::new(), "Process::node_refs")?,
303302
})?;
304-
let process = Ref::get_mut(&mut proc_ref).ok_or(Error::EINVAL)?;
305-
// SAFETY: `inner` is pinned behind the `Arc` reference.
306-
let pinned = unsafe { Pin::new_unchecked(&process.inner) };
307-
kernel::mutex_init!(pinned, "Process::inner");
308-
// SAFETY: `node_refs` is pinned behind the `Arc` reference.
309-
let pinned = unsafe { Pin::new_unchecked(&process.node_refs) };
310-
kernel::mutex_init!(pinned, "Process::node_refs");
311303
Ok(proc_ref)
312304
}
313305

@@ -931,7 +923,7 @@ impl<'a> Registration<'a> {
931923
fn new(
932924
process: &'a Process,
933925
thread: &'a Arc<Thread>,
934-
guard: &mut Guard<Mutex<ProcessInner>>,
926+
guard: &mut Guard<BoxedMutex<ProcessInner>>,
935927
) -> Self {
936928
guard.ready_threads.push_back(thread.clone());
937929
Self { process, thread }

drivers/android/thread.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
use alloc::sync::Arc;
44
use core::{alloc::AllocError, mem::size_of, pin::Pin};
55
use kernel::{
6-
bindings,
6+
bindings, boxed_condvar,
77
file::File,
88
file_operations::PollTable,
99
io_buffer::{IoBufferReader, IoBufferWriter},
1010
linked_list::{GetLinks, Links, List},
1111
prelude::*,
12-
sync::{CondVar, Ref, SpinLock},
12+
sync::{BoxedCondVar, Ref, SpinLock},
1313
user_ptr::{UserSlicePtr, UserSlicePtrWriter},
1414
Error,
1515
};
@@ -228,7 +228,7 @@ pub(crate) struct Thread {
228228
pub(crate) id: i32,
229229
pub(crate) process: Ref<Process>,
230230
inner: SpinLock<InnerThread>,
231-
work_condvar: CondVar,
231+
work_condvar: BoxedCondVar,
232232
links: Links<Thread>,
233233
}
234234

@@ -241,15 +241,13 @@ impl Thread {
241241
process,
242242
// SAFETY: `inner` is initialised in the call to `spinlock_init` below.
243243
inner: unsafe { SpinLock::new(InnerThread::new()) },
244-
// SAFETY: `work_condvar` is initalised in the call to `condvar_init` below.
245-
work_condvar: unsafe { CondVar::new() },
244+
work_condvar: boxed_condvar!("Thread::work_condvar")?,
246245
links: Links::new(),
247246
})?;
248247
let thread = Arc::get_mut(&mut arc).unwrap();
249248
// SAFETY: `inner` is pinned behind the `Arc` reference.
250249
let inner = unsafe { Pin::new_unchecked(&thread.inner) };
251250
kernel::spinlock_init!(inner, "Thread::inner");
252-
kernel::condvar_init!(thread.pinned_condvar(), "Thread::work_condvar");
253251
{
254252
let mut inner = arc.inner.lock();
255253
inner.set_reply_work(reply_work);
@@ -258,8 +256,8 @@ impl Thread {
258256
Ok(arc)
259257
}
260258

261-
fn pinned_condvar(&self) -> Pin<&CondVar> {
262-
unsafe { Pin::new_unchecked(&self.work_condvar) }
259+
fn pinned_condvar(&self) -> &BoxedCondVar {
260+
&self.work_condvar
263261
}
264262

265263
pub(crate) fn set_current_transaction(&self, transaction: Arc<Transaction>) {
@@ -754,7 +752,7 @@ impl Thread {
754752

755753
pub(crate) fn poll(&self, file: &File, table: &PollTable) -> (bool, u32) {
756754
// SAFETY: `free_waiters` is called on release.
757-
unsafe { table.register_wait(file, &self.work_condvar) };
755+
unsafe { table.register_wait2(file, &self.work_condvar) };
758756
let mut inner = self.inner.lock();
759757
(inner.should_use_process_work_queue(), inner.poll())
760758
}

rust/kernel/file_operations.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::{
1616
from_kernel_result,
1717
io_buffer::{IoBufferReader, IoBufferWriter},
1818
iov_iter::IovIter,
19-
sync::CondVar,
19+
sync::{BoxedCondVar, CondVar},
2020
types::PointerWrapper,
2121
user_ptr::{UserSlicePtr, UserSlicePtrReader, UserSlicePtrWriter},
2222
};
@@ -63,6 +63,30 @@ impl PollTable {
6363
unsafe { proc(file.ptr as _, cv.wait_list.get(), self.ptr) }
6464
}
6565
}
66+
67+
/// Associates the given file and condition variable to this poll table. It means notifying the
68+
/// condition variable will notify the poll table as well; additionally, the association
69+
/// between the condition variable and the file will automatically be undone by the kernel when
70+
/// the file is destructed. To unilaterally remove the association before then, one can call
71+
/// [`CondVar::free_waiters`].
72+
///
73+
/// # Safety
74+
///
75+
/// If the condition variable is destroyed before the file, then [`CondVar::free_waiters`] must
76+
/// be called to ensure that all waiters are flushed out.
77+
pub unsafe fn register_wait2<'a>(&self, file: &'a File, cv: &'a BoxedCondVar) {
78+
if self.ptr.is_null() {
79+
return;
80+
}
81+
82+
// SAFETY: `PollTable::ptr` is guaranteed to be valid by the type invariants and the null
83+
// check above.
84+
let table = unsafe { &*self.ptr };
85+
if let Some(proc) = table._qproc {
86+
// SAFETY: All pointers are known to be valid.
87+
unsafe { proc(file.ptr as _, cv.wait_list.get(), self.ptr) }
88+
}
89+
}
6690
}
6791

6892
/// Equivalent to [`std::io::SeekFrom`].

rust/kernel/sync/condvar.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ pub struct BoxedCondVar {
153153
/// It contains a [`struct list_head`] that is self-referential, so
154154
/// it cannot be safely moved once it is initialised.
155155
/// We guarantee that it will never move, as per the invariant above.
156-
wait_list: Box<UnsafeCell<bindings::wait_queue_head>>,
156+
pub(crate) wait_list: Box<UnsafeCell<bindings::wait_queue_head>>,
157157
}
158158

159159
// SAFETY: `CondVar` only uses a `struct wait_queue_head`, which is safe to use on any thread.

0 commit comments

Comments
 (0)