Skip to content

Commit 5743fea

Browse files
committed
rust: update Ref to use the kernel's refcount_t.
`Ref` now has an interface similar to that of `Arc` but is backed by the kernel's `refcount_t` type. Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
1 parent a5a22ed commit 5743fea

File tree

6 files changed

+205
-148
lines changed

6 files changed

+205
-148
lines changed

Diff for: drivers/android/process.rs

+43-41
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use kernel::{
1414
linked_list::List,
1515
pages::Pages,
1616
prelude::*,
17-
sync::{Guard, Mutex, Ref, RefCount, RefCounted},
17+
sync::{Guard, Mutex, Ref},
1818
user_ptr::{UserSlicePtr, UserSlicePtrReader},
1919
Error,
2020
};
@@ -275,7 +275,6 @@ impl ProcessNodeRefs {
275275

276276
pub(crate) struct Process {
277277
ctx: Arc<Context>,
278-
ref_count: RefCount,
279278

280279
// TODO: For now this a mutex because we have allocations in BTreeMap and RangeAllocator while
281280
// holding the lock. We may want to split up the process state at some point to use a spin lock
@@ -293,22 +292,23 @@ unsafe impl Sync for Process {}
293292

294293
impl Process {
295294
fn new(ctx: Arc<Context>) -> Result<Ref<Self>> {
296-
let mut proc_ref = Ref::try_new(Self {
297-
ref_count: RefCount::new(),
298-
ctx,
299-
// SAFETY: `inner` is initialised in the call to `mutex_init` below.
300-
inner: unsafe { Mutex::new(ProcessInner::new()) },
301-
// SAFETY: `node_refs` is initialised in the call to `mutex_init` below.
302-
node_refs: unsafe { Mutex::new(ProcessNodeRefs::new()) },
303-
})?;
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");
311-
Ok(proc_ref)
295+
Ref::try_new_and_init(
296+
Self {
297+
ctx,
298+
// SAFETY: `inner` is initialised in the call to `mutex_init` below.
299+
inner: unsafe { Mutex::new(ProcessInner::new()) },
300+
// SAFETY: `node_refs` is initialised in the call to `mutex_init` below.
301+
node_refs: unsafe { Mutex::new(ProcessNodeRefs::new()) },
302+
},
303+
|process| {
304+
// SAFETY: `inner` is pinned behind the `Ref` reference.
305+
let pinned = unsafe { Pin::new_unchecked(&process.inner) };
306+
kernel::mutex_init!(pinned, "Process::inner");
307+
// SAFETY: `node_refs` is pinned behind the `Ref` reference.
308+
let pinned = unsafe { Pin::new_unchecked(&process.node_refs) };
309+
kernel::mutex_init!(pinned, "Process::node_refs");
310+
},
311+
)
312312
}
313313

314314
/// Attemps to fetch a work item from the process queue.
@@ -337,7 +337,7 @@ impl Process {
337337
Either::Right(Registration::new(self, thread, &mut inner))
338338
}
339339

340-
fn get_thread(&self, id: i32) -> Result<Arc<Thread>> {
340+
fn get_thread(self: &Ref<Self>, id: i32) -> Result<Arc<Thread>> {
341341
// TODO: Consider using read/write locks here instead.
342342
{
343343
let inner = self.inner.lock();
@@ -347,7 +347,7 @@ impl Process {
347347
}
348348

349349
// Allocate a new `Thread` without holding any locks.
350-
let ta = Thread::new(id, Ref::new_from(self))?;
350+
let ta = Thread::new(id, self.clone())?;
351351

352352
let mut inner = self.inner.lock();
353353

@@ -366,7 +366,7 @@ impl Process {
366366
self.inner.lock().push_work(work)
367367
}
368368

369-
fn set_as_manager(&self, info: Option<FlatBinderObject>, thread: &Thread) -> Result {
369+
fn set_as_manager(self: &Ref<Self>, info: Option<FlatBinderObject>, thread: &Thread) -> Result {
370370
let (ptr, cookie, flags) = if let Some(obj) = info {
371371
(
372372
// SAFETY: The object type for this ioctl is implicitly `BINDER_TYPE_BINDER`, so it
@@ -390,7 +390,7 @@ impl Process {
390390
}
391391

392392
pub(crate) fn get_node(
393-
&self,
393+
self: &Ref<Self>,
394394
ptr: usize,
395395
cookie: usize,
396396
flags: u32,
@@ -406,7 +406,7 @@ impl Process {
406406
}
407407

408408
// Allocate the node before reacquiring the lock.
409-
let node = Arc::try_new(Node::new(ptr, cookie, flags, Ref::new_from(self)))?;
409+
let node = Arc::try_new(Node::new(ptr, cookie, flags, self.clone()))?;
410410

411411
let mut inner = self.inner.lock();
412412
if let Some(node) = inner.get_existing_node_ref(ptr, cookie, strong, thread)? {
@@ -693,7 +693,11 @@ impl Process {
693693
ret
694694
}
695695

696-
pub(crate) fn request_death(&self, reader: &mut UserSlicePtrReader, thread: &Thread) -> Result {
696+
pub(crate) fn request_death(
697+
self: &Ref<Self>,
698+
reader: &mut UserSlicePtrReader,
699+
thread: &Thread,
700+
) -> Result {
697701
let handle: u32 = reader.read()?;
698702
let cookie: usize = reader.read()?;
699703

@@ -716,9 +720,8 @@ impl Process {
716720
}
717721

718722
// SAFETY: `init` is called below.
719-
let death = death.commit(unsafe {
720-
NodeDeath::new(info.node_ref.node.clone(), Ref::new_from(self), cookie)
721-
});
723+
let death = death
724+
.commit(unsafe { NodeDeath::new(info.node_ref.node.clone(), self.clone(), cookie) });
722725
// SAFETY: `death` is pinned behind the `Arc` reference.
723726
unsafe { Pin::new_unchecked(death.as_ref()) }.init();
724727
info.death = Some(death.clone());
@@ -766,9 +769,14 @@ impl Process {
766769
}
767770

768771
impl IoctlHandler for Process {
769-
type Target = Self;
770-
771-
fn write(this: &Self, _file: &File, cmd: u32, reader: &mut UserSlicePtrReader) -> Result<i32> {
772+
type Target = Ref<Process>;
773+
774+
fn write(
775+
this: &Ref<Process>,
776+
_file: &File,
777+
cmd: u32,
778+
reader: &mut UserSlicePtrReader,
779+
) -> Result<i32> {
772780
let thread = this.get_thread(unsafe { rust_helper_current_pid() })?;
773781
match cmd {
774782
bindings::BINDER_SET_MAX_THREADS => this.set_max_threads(reader.read()?),
@@ -782,7 +790,7 @@ impl IoctlHandler for Process {
782790
Ok(0)
783791
}
784792

785-
fn read_write(this: &Self, file: &File, cmd: u32, data: UserSlicePtr) -> Result<i32> {
793+
fn read_write(this: &Ref<Process>, file: &File, cmd: u32, data: UserSlicePtr) -> Result<i32> {
786794
let thread = this.get_thread(unsafe { rust_helper_current_pid() })?;
787795
match cmd {
788796
bindings::BINDER_WRITE_READ => thread.write_read(data, file.is_blocking())?,
@@ -795,12 +803,6 @@ impl IoctlHandler for Process {
795803
}
796804
}
797805

798-
unsafe impl RefCounted for Process {
799-
fn get_count(&self) -> &RefCount {
800-
&self.ref_count
801-
}
802-
}
803-
804806
impl FileOpener<Arc<Context>> for Process {
805807
fn open(ctx: &Arc<Context>) -> Result<Self::Wrapper> {
806808
let process = Self::new(ctx.clone())?;
@@ -893,15 +895,15 @@ impl FileOperations for Process {
893895
}
894896
}
895897

896-
fn ioctl(this: &Process, file: &File, cmd: &mut IoctlCommand) -> Result<i32> {
898+
fn ioctl(this: &Ref<Process>, file: &File, cmd: &mut IoctlCommand) -> Result<i32> {
897899
cmd.dispatch::<Self>(this, file)
898900
}
899901

900-
fn compat_ioctl(this: &Process, file: &File, cmd: &mut IoctlCommand) -> Result<i32> {
902+
fn compat_ioctl(this: &Ref<Process>, file: &File, cmd: &mut IoctlCommand) -> Result<i32> {
901903
cmd.dispatch::<Self>(this, file)
902904
}
903905

904-
fn mmap(this: &Process, _file: &File, vma: &mut bindings::vm_area_struct) -> Result {
906+
fn mmap(this: &Ref<Process>, _file: &File, vma: &mut bindings::vm_area_struct) -> Result {
905907
// TODO: Only group leader is allowed to create mappings.
906908

907909
if vma.vm_start == 0 {
@@ -919,7 +921,7 @@ impl FileOperations for Process {
919921
this.create_mapping(vma)
920922
}
921923

922-
fn poll(this: &Process, file: &File, table: &PollTable) -> Result<u32> {
924+
fn poll(this: &Ref<Process>, file: &File, table: &PollTable) -> Result<u32> {
923925
let thread = this.get_thread(unsafe { rust_helper_current_pid() })?;
924926
let (from_proc, mut mask) = thread.poll(file, table);
925927
if mask == 0 && from_proc && !this.inner.lock().work.is_empty() {

Diff for: rust/helpers.c

+18
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,24 @@ rust_helper_platform_set_drvdata(struct platform_device *pdev,
146146
}
147147
EXPORT_SYMBOL_GPL(rust_helper_platform_set_drvdata);
148148

149+
refcount_t rust_helper_refcount_new(void)
150+
{
151+
return (refcount_t)REFCOUNT_INIT(1);
152+
}
153+
EXPORT_SYMBOL_GPL(rust_helper_refcount_new);
154+
155+
void rust_helper_refcount_inc(refcount_t *r)
156+
{
157+
refcount_inc(r);
158+
}
159+
EXPORT_SYMBOL_GPL(rust_helper_refcount_inc);
160+
161+
bool rust_helper_refcount_dec_and_test(refcount_t *r)
162+
{
163+
return refcount_dec_and_test(r);
164+
}
165+
EXPORT_SYMBOL_GPL(rust_helper_refcount_dec_and_test);
166+
149167
/* We use bindgen's --size_t-is-usize option to bind the C size_t type
150168
* as the Rust usize type, so we can use it in contexts where Rust
151169
* expects a usize like slice (array) indices. usize is defined to be

Diff for: rust/kernel/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
const_panic,
2222
const_raw_ptr_deref,
2323
const_unreachable_unchecked,
24+
receiver_trait,
2425
try_reserve
2526
)]
2627
#![deny(clippy::complexity)]

0 commit comments

Comments
 (0)