summaryrefslogtreecommitdiff
path: root/drivers/android/binder
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/android/binder')
-rw-r--r--drivers/android/binder/Makefile4
-rw-r--r--drivers/android/binder/allocation.rs10
-rw-r--r--drivers/android/binder/defs.rs3
-rw-r--r--drivers/android/binder/freeze.rs11
-rw-r--r--drivers/android/binder/node.rs30
-rw-r--r--drivers/android/binder/node/wrapper.rs36
-rw-r--r--drivers/android/binder/page_range.rs6
-rw-r--r--drivers/android/binder/process.rs21
-rw-r--r--drivers/android/binder/range_alloc/array.rs2
-rw-r--r--drivers/android/binder/range_alloc/mod.rs2
-rw-r--r--drivers/android/binder/range_alloc/tree.rs2
-rw-r--r--drivers/android/binder/rust_binder_main.rs14
-rw-r--r--drivers/android/binder/rust_binderfs.c10
-rw-r--r--drivers/android/binder/thread.rs66
-rw-r--r--drivers/android/binder/transaction.rs3
15 files changed, 157 insertions, 63 deletions
diff --git a/drivers/android/binder/Makefile b/drivers/android/binder/Makefile
index 7e0cd9782a8b..fe474628a94e 100644
--- a/drivers/android/binder/Makefile
+++ b/drivers/android/binder/Makefile
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only
ccflags-y += -I$(src) # needed for trace events
-obj-$(CONFIG_ANDROID_BINDER_IPC_RUST) += rust_binder.o
-rust_binder-y := \
+obj-$(CONFIG_ANDROID_BINDER_IPC_RUST) += binder.o
+binder-y := \
rust_binder_main.o \
rust_binderfs.o \
rust_binder_events.o
diff --git a/drivers/android/binder/allocation.rs b/drivers/android/binder/allocation.rs
index 165cb797eb1e..2f0763e6868d 100644
--- a/drivers/android/binder/allocation.rs
+++ b/drivers/android/binder/allocation.rs
@@ -208,7 +208,7 @@ impl Allocation {
let num_close_on_free = files.iter().filter(|entry| entry.close_on_free).count();
let mut close_on_free = KVec::with_capacity(num_close_on_free, GFP_KERNEL)?;
- let mut reservations = KVec::with_capacity(files.len(), GFP_KERNEL)?;
+ let mut reservations = KVVec::with_capacity(files.len(), GFP_KERNEL)?;
for file_info in files {
let res = FileDescriptorReservation::get_unused_fd_flags(bindings::O_CLOEXEC)?;
let fd = res.reserved_fd();
@@ -503,7 +503,7 @@ impl BinderObject {
/// The closure should write the bytes for the object into the provided slice.
pub(crate) fn read_from_inner<R>(reader: R) -> Result<BinderObject>
where
- R: FnOnce(&mut [u8; size_of::<BinderObject>()]) -> Result<()>,
+ R: FnOnce(&mut [u8; size_of::<BinderObject>()]) -> Result,
{
let mut obj = MaybeUninit::<BinderObject>::zeroed();
@@ -567,7 +567,7 @@ impl BinderObject {
#[derive(Default)]
struct FileList {
- files_to_translate: KVec<FileEntry>,
+ files_to_translate: KVVec<FileEntry>,
close_on_free: KVec<u32>,
}
@@ -581,7 +581,7 @@ struct FileEntry {
}
pub(crate) struct TranslatedFds {
- reservations: KVec<Reservation>,
+ reservations: KVVec<Reservation>,
/// If commit is called, then these fds should be closed. (If commit is not called, then they
/// shouldn't be closed.)
close_on_free: FdsCloseOnFree,
@@ -595,7 +595,7 @@ struct Reservation {
impl TranslatedFds {
pub(crate) fn new() -> Self {
Self {
- reservations: KVec::new(),
+ reservations: KVVec::new(),
close_on_free: FdsCloseOnFree(KVec::new()),
}
}
diff --git a/drivers/android/binder/defs.rs b/drivers/android/binder/defs.rs
index 8ac9bdd7a499..cc4becd6e168 100644
--- a/drivers/android/binder/defs.rs
+++ b/drivers/android/binder/defs.rs
@@ -77,7 +77,8 @@ pub_no_prefix!(
TF_ONE_WAY,
TF_ACCEPT_FDS,
TF_CLEAR_BUF,
- TF_UPDATE_TXN
+ TF_UPDATE_TXN,
+ TF_DEFER_COMPLETE,
);
pub(crate) use uapi::{
diff --git a/drivers/android/binder/freeze.rs b/drivers/android/binder/freeze.rs
index 66912b4cb527..ea2450f3f16f 100644
--- a/drivers/android/binder/freeze.rs
+++ b/drivers/android/binder/freeze.rs
@@ -155,7 +155,7 @@ impl DeliverToRead for FreezeMessage {
}
#[inline(never)]
- fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
+ fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result {
seq_print!(m, "{}has frozen binder\n", prefix);
Ok(())
}
@@ -177,10 +177,7 @@ impl FreezeListener {
}
impl Process {
- pub(crate) fn request_freeze_notif(
- self: &Arc<Self>,
- reader: &mut UserSliceReader,
- ) -> Result<()> {
+ pub(crate) fn request_freeze_notif(self: &Arc<Self>, reader: &mut UserSliceReader) -> Result {
let hc = reader.read::<BinderHandleCookie>()?;
let handle = hc.handle;
let cookie = FreezeCookie(hc.cookie);
@@ -272,7 +269,7 @@ impl Process {
Ok(())
}
- pub(crate) fn freeze_notif_done(self: &Arc<Self>, reader: &mut UserSliceReader) -> Result<()> {
+ pub(crate) fn freeze_notif_done(self: &Arc<Self>, reader: &mut UserSliceReader) -> Result {
let cookie = FreezeCookie(reader.read()?);
let alloc = FreezeMessage::new(GFP_KERNEL)?;
let mut node_refs_guard = self.node_refs.lock();
@@ -313,7 +310,7 @@ impl Process {
Ok(())
}
- pub(crate) fn clear_freeze_notif(self: &Arc<Self>, reader: &mut UserSliceReader) -> Result<()> {
+ pub(crate) fn clear_freeze_notif(self: &Arc<Self>, reader: &mut UserSliceReader) -> Result {
let hc = reader.read::<BinderHandleCookie>()?;
let handle = hc.handle;
let cookie = FreezeCookie(hc.cookie);
diff --git a/drivers/android/binder/node.rs b/drivers/android/binder/node.rs
index 0a82af14cda3..b16ea0ff9ed9 100644
--- a/drivers/android/binder/node.rs
+++ b/drivers/android/binder/node.rs
@@ -51,9 +51,9 @@ pub(crate) struct CouldNotDeliverCriticalIncrement;
/// about to drop the weak reference, then the strong increment could be processed after the
/// other thread has already exited, which would be too late.
///
-/// Note that trying to create a `ListArc` to the node can succeed even if `has_normal_push` is
+/// Note that trying to create a `ListArc` to the node can succeed even if `has_pushed_node` is
/// set. This is because another thread might just have popped the node from a todo list, but not
-/// yet called `do_work`. However, if `has_normal_push` is false, then creating a `ListArc` should
+/// yet called `do_work`. However, if `has_pushed_node` is false, then creating a `ListArc` should
/// always succeed.
///
/// Like the other fields in `NodeInner`, the delivery state is protected by the process lock.
@@ -255,11 +255,7 @@ impl Node {
}
#[inline(never)]
- pub(crate) fn full_debug_print(
- &self,
- m: &SeqFile,
- owner_inner: &mut ProcessInner,
- ) -> Result<()> {
+ pub(crate) fn full_debug_print(&self, m: &SeqFile, owner_inner: &mut ProcessInner) -> Result {
let inner = self.inner.access_mut(owner_inner);
seq_print!(
m,
@@ -738,14 +734,28 @@ impl DeliverToRead for Node {
self.do_work_locked(writer, owner_inner)
}
- fn cancel(self: DArc<Self>) {}
+ fn cancel(self: DArc<Self>) {
+ let _drop_outside_lock;
+ let mut owner_inner = self.owner.inner.lock();
+
+ // We only do something on BINDER_THREAD_EXIT, not process exit.
+ if owner_inner.is_dead {
+ return;
+ }
+
+ // If BINDER_THREAD_EXIT is invoked on a thread with a pending node refcount update, we
+ // should move ourselves to ensure the refcount update is still delivered.
+ if let Some(node) = ListArc::try_from_arc_borrow(self.as_arc_borrow()) {
+ _drop_outside_lock = owner_inner.push_work(&self.owner, node);
+ }
+ }
fn should_sync_wakeup(&self) -> bool {
false
}
#[inline(never)]
- fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
+ fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result {
seq_print!(
m,
"{}node work {}: u{:016x} c{:016x}\n",
@@ -1140,7 +1150,7 @@ impl DeliverToRead for NodeDeath {
}
#[inline(never)]
- fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
+ fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result {
let inner = self.inner.lock();
let dead_binder = inner.dead && !inner.notification_done;
diff --git a/drivers/android/binder/node/wrapper.rs b/drivers/android/binder/node/wrapper.rs
index 6e4ca01c941a..5a5e5e9883a4 100644
--- a/drivers/android/binder/node/wrapper.rs
+++ b/drivers/android/binder/node/wrapper.rs
@@ -57,14 +57,46 @@ impl DeliverToRead for NodeWrapper {
node.do_work_locked(writer, owner_inner)
}
- fn cancel(self: DArc<Self>) {}
+ fn cancel(self: DArc<Self>) {
+ let _drop_outside_lock;
+ let node = &self.node;
+ let mut owner_inner = node.owner.inner.lock();
+
+ // We only do something on BINDER_THREAD_EXIT, not process exit.
+ if owner_inner.is_dead {
+ return;
+ }
+
+ // We transfer the responsibility of the node refcount update to the scheduled Node because
+ // NodeWrapper has no way to re-create the ListArc.
+ let inner = node.inner.access_mut(&mut owner_inner);
+
+ let ds = &mut inner.delivery_state;
+ assert!(ds.has_pushed_wrapper);
+ assert!(ds.has_strong_zero2one);
+ ds.has_pushed_wrapper = false;
+
+ // We are changing the state to one where the Node is the strong zero2one update instead of
+ // the wrapper.
+ ds.has_weak_zero2one = false;
+
+ if !ds.has_pushed_node {
+ if let Some(node2) = ListArc::try_from_arc_borrow(node.as_arc_borrow()) {
+ ds.has_pushed_node = true;
+ _drop_outside_lock = owner_inner.push_work(&node.owner, node2);
+ } else {
+ // This can't actually happen.
+ ds.has_strong_zero2one = false;
+ }
+ }
+ }
fn should_sync_wakeup(&self) -> bool {
false
}
#[inline(never)]
- fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
+ fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result {
seq_print!(
m,
"{}node work {}: u{:016x} c{:016x}\n",
diff --git a/drivers/android/binder/page_range.rs b/drivers/android/binder/page_range.rs
index 71febd3d5b07..74c99432f867 100644
--- a/drivers/android/binder/page_range.rs
+++ b/drivers/android/binder/page_range.rs
@@ -66,7 +66,7 @@ impl Shrinker {
}
/// Register this shrinker with the kernel.
- pub(crate) fn register(&'static self, name: &CStr) -> Result<()> {
+ pub(crate) fn register(&'static self, name: &CStr) -> Result {
// SAFETY: These fields are not yet used, so it's okay to zero them.
unsafe {
self.inner.get().write(ptr::null_mut());
@@ -352,7 +352,7 @@ impl ShrinkablePageRange {
/// Make sure that the given pages are allocated and mapped.
///
/// Must not be called from an atomic context.
- pub(crate) fn use_range(&self, start: usize, end: usize) -> Result<()> {
+ pub(crate) fn use_range(&self, start: usize, end: usize) -> Result {
if start >= end {
return Ok(());
}
@@ -398,7 +398,7 @@ impl ShrinkablePageRange {
///
/// Assumes that `i` is in bounds.
#[cold]
- unsafe fn use_page_slow(&self, i: usize) -> Result<()> {
+ unsafe fn use_page_slow(&self, i: usize) -> Result {
let new_page = Page::alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO)?;
let mm_mutex = self.mm_lock.lock();
diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index 5372bfbd93b3..58c84be8ab77 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -548,7 +548,7 @@ impl Process {
}
#[inline(never)]
- pub(crate) fn debug_print_stats(&self, m: &SeqFile, ctx: &Context) -> Result<()> {
+ pub(crate) fn debug_print_stats(&self, m: &SeqFile, ctx: &Context) -> Result {
seq_print!(m, "proc {}\n", self.pid_in_current_ns());
seq_print!(m, "context {}\n", &*ctx.name);
@@ -596,7 +596,7 @@ impl Process {
}
#[inline(never)]
- pub(crate) fn debug_print(&self, m: &SeqFile, ctx: &Context, print_all: bool) -> Result<()> {
+ pub(crate) fn debug_print(&self, m: &SeqFile, ctx: &Context, print_all: bool) -> Result {
seq_print!(m, "proc {}\n", self.pid_in_current_ns());
seq_print!(m, "context {}\n", &*ctx.name);
@@ -686,8 +686,16 @@ impl Process {
pub(crate) fn get_work_or_register<'a>(
&'a self,
thread: &'a Arc<Thread>,
+ thread_has_deferred_work: bool,
) -> GetWorkOrRegister<'a> {
let mut inner = self.inner.lock();
+
+ if thread_has_deferred_work && !inner.work.is_empty() {
+ if let Some(work) = thread.pop_work_even_if_deferred() {
+ return GetWorkOrRegister::Work(work);
+ }
+ }
+
// Try to get work from the process queue.
if let Some(work) = inner.work.pop_front() {
return GetWorkOrRegister::Work(work);
@@ -1208,11 +1216,10 @@ impl Process {
{
let inner = self.inner.lock();
- for (node_ptr, node) in &inner.nodes {
- if *node_ptr > ptr {
- node.populate_debug_info(&mut out, &inner);
- break;
- }
+ // cursor_lower_bound retrieves the "key" passed or the next existing larger key
+ if let Some(cursor) = inner.nodes.cursor_lower_bound(&(ptr + 1)) {
+ let (_, node) = cursor.current();
+ node.populate_debug_info(&mut out, &inner);
}
}
diff --git a/drivers/android/binder/range_alloc/array.rs b/drivers/android/binder/range_alloc/array.rs
index 081d19b09d4b..71bf49f9db0d 100644
--- a/drivers/android/binder/range_alloc/array.rs
+++ b/drivers/android/binder/range_alloc/array.rs
@@ -61,7 +61,7 @@ impl<T> ArrayRangeAllocator<T> {
self.ranges.len() == self.ranges.capacity()
}
- pub(crate) fn debug_print(&self, m: &SeqFile) -> Result<()> {
+ pub(crate) fn debug_print(&self, m: &SeqFile) -> Result {
for range in &self.ranges {
seq_print!(
m,
diff --git a/drivers/android/binder/range_alloc/mod.rs b/drivers/android/binder/range_alloc/mod.rs
index 1f4734468ff1..bb6e0ec9650e 100644
--- a/drivers/android/binder/range_alloc/mod.rs
+++ b/drivers/android/binder/range_alloc/mod.rs
@@ -141,7 +141,7 @@ impl<T> RangeAllocator<T> {
}
}
- pub(crate) fn debug_print(&self, m: &SeqFile) -> Result<()> {
+ pub(crate) fn debug_print(&self, m: &SeqFile) -> Result {
match &self.inner {
Impl::Empty(_size) => Ok(()),
Impl::Array(array) => array.debug_print(m),
diff --git a/drivers/android/binder/range_alloc/tree.rs b/drivers/android/binder/range_alloc/tree.rs
index 48796fcdb362..058ff7498fa5 100644
--- a/drivers/android/binder/range_alloc/tree.rs
+++ b/drivers/android/binder/range_alloc/tree.rs
@@ -111,7 +111,7 @@ impl<T> TreeRangeAllocator<T> {
.count()
}
- pub(crate) fn debug_print(&self, m: &SeqFile) -> Result<()> {
+ pub(crate) fn debug_print(&self, m: &SeqFile) -> Result {
for desc in self.tree.values() {
let state = match &desc.state {
Some(state) => &state.0,
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index 955c4c348f73..92bf33f9ff1c 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -81,7 +81,7 @@ mod binderfs {
module! {
type: BinderModule,
- name: "rust_binder",
+ name: "binder",
authors: ["Wedson Almeida Filho", "Alice Ryhl"],
description: "Android Binder",
license: "GPL",
@@ -158,7 +158,7 @@ trait DeliverToRead: ListArcSafe + Send + Sync {
/// Generally only set to true for non-oneway transactions.
fn should_sync_wakeup(&self) -> bool;
- fn debug_print(&self, m: &SeqFile, prefix: &str, transaction_prefix: &str) -> Result<()>;
+ fn debug_print(&self, m: &SeqFile, prefix: &str, transaction_prefix: &str) -> Result;
}
// Wrapper around a `DeliverToRead` with linked list links.
@@ -274,7 +274,7 @@ impl DeliverToRead for DeliverCode {
false
}
- fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
+ fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result {
seq_print!(m, "{}", prefix);
if self.skip.load(Relaxed) {
seq_print!(m, "(skipped) ");
@@ -545,7 +545,7 @@ unsafe extern "C" fn rust_binder_transactions_show(
0
}
-fn rust_binder_transactions_show_impl(m: &SeqFile) -> Result<()> {
+fn rust_binder_transactions_show_impl(m: &SeqFile) -> Result {
seq_print!(m, "binder transactions:\n");
let contexts = context::get_all_contexts()?;
for ctx in contexts {
@@ -558,7 +558,7 @@ fn rust_binder_transactions_show_impl(m: &SeqFile) -> Result<()> {
Ok(())
}
-fn rust_binder_stats_show_impl(m: &SeqFile) -> Result<()> {
+fn rust_binder_stats_show_impl(m: &SeqFile) -> Result {
seq_print!(m, "binder stats:\n");
stats::GLOBAL_STATS.debug_print("", m);
let contexts = context::get_all_contexts()?;
@@ -572,7 +572,7 @@ fn rust_binder_stats_show_impl(m: &SeqFile) -> Result<()> {
Ok(())
}
-fn rust_binder_state_show_impl(m: &SeqFile) -> Result<()> {
+fn rust_binder_state_show_impl(m: &SeqFile) -> Result {
seq_print!(m, "binder state:\n");
let contexts = context::get_all_contexts()?;
for ctx in contexts {
@@ -585,7 +585,7 @@ fn rust_binder_state_show_impl(m: &SeqFile) -> Result<()> {
Ok(())
}
-fn rust_binder_proc_show_impl(m: &SeqFile, pid: Pid) -> Result<()> {
+fn rust_binder_proc_show_impl(m: &SeqFile, pid: Pid) -> Result {
seq_print!(m, "binder proc state:\n");
let contexts = context::get_all_contexts()?;
for ctx in contexts {
diff --git a/drivers/android/binder/rust_binderfs.c b/drivers/android/binder/rust_binderfs.c
index 300cc65562d1..acc83a179f38 100644
--- a/drivers/android/binder/rust_binderfs.c
+++ b/drivers/android/binder/rust_binderfs.c
@@ -49,7 +49,7 @@ DEFINE_SHOW_ATTRIBUTE(rust_binder_transactions);
DEFINE_SHOW_ATTRIBUTE(rust_binder_proc);
char *rust_binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
-module_param_named(rust_devices, rust_binder_devices_param, charp, 0444);
+module_param_named(devices, rust_binder_devices_param, charp, 0444);
extern u32 rust_binder_debug_mask;
module_param_named(debug_mask, rust_binder_debug_mask, uint, 0644);
@@ -72,6 +72,7 @@ struct binder_features {
bool oneway_spam_detection;
bool extended_error;
bool freeze_notification;
+ bool transaction_report;
};
static const struct constant_table binderfs_param_stats[] = {
@@ -89,6 +90,7 @@ static struct binder_features binder_features = {
.oneway_spam_detection = true,
.extended_error = true,
.freeze_notification = true,
+ .transaction_report = true,
};
static inline struct binderfs_info *BINDERFS_SB(const struct super_block *sb)
@@ -566,6 +568,12 @@ static int init_binder_features(struct super_block *sb)
if (IS_ERR(dentry))
return PTR_ERR(dentry);
+ dentry = rust_binderfs_create_file(dir, "transaction_report",
+ &binder_features_fops,
+ &binder_features.transaction_report);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
return 0;
}
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index 18a14aa8a835..edafce806d27 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -481,7 +481,7 @@ impl Thread {
}
#[inline(never)]
- pub(crate) fn debug_print(self: &Arc<Self>, m: &SeqFile, print_all: bool) -> Result<()> {
+ pub(crate) fn debug_print(self: &Arc<Self>, m: &SeqFile, print_all: bool) -> Result {
let inner = self.inner.lock();
if print_all || inner.current_transaction.is_some() || !inner.work_list.is_empty() {
@@ -584,9 +584,21 @@ impl Thread {
// mangled symbol names.
#[export_name = "rust_binder_wait"]
fn get_work(self: &Arc<Self>, wait: bool) -> Result<Option<DLArc<dyn DeliverToRead>>> {
+ let thread_has_deferred_work;
+
// Try to get work from the thread's work queue, using only a local lock.
{
let mut inner = self.inner.lock();
+
+ // The process_work_list boolean is used to make us go to sleep even if there is work
+ // in the thread todo-list, but it doesn't apply to the process todo-list. Furthermore,
+ // work in the thread todo-list must still be delivered before the process list.
+ //
+ // Thus, in some scenarios we must return the thread work now even if we were requested
+ // to wait. Adjust `process_work_list` to `true` accordingly.
+ inner.process_work_list |= inner.looper_need_return;
+ inner.process_work_list |= !wait;
+
if let Some(work) = inner.pop_work() {
return Ok(Some(work));
}
@@ -594,18 +606,26 @@ impl Thread {
drop(inner);
return Ok(self.process.get_work());
}
+
+ // Note that if the thread list is empty, then the call to `pop_work()` has changed
+ // `process_work_list` back to `false` even if we set it to `true` above.
+ thread_has_deferred_work = !inner.work_list.is_empty();
}
// If the caller doesn't want to wait, try to grab work from the process queue.
//
// We know nothing will have been queued directly to the thread queue because it is not in
- // a transaction and it is not in the process' ready list.
+ // a transaction and it is not in the process' ready list. We also know the thread list has
+ // no deferred work due to the `inner.process_work_list |= !wait` call above.
if !wait {
return self.process.get_work().ok_or(EAGAIN).map(Some);
}
// Get work from the process queue. If none is available, atomically register as ready.
- let reg = match self.process.get_work_or_register(self) {
+ let reg = match self
+ .process
+ .get_work_or_register(self, thread_has_deferred_work)
+ {
GetWorkOrRegister::Work(work) => return Ok(Some(work)),
GetWorkOrRegister::Register(reg) => reg,
};
@@ -621,14 +641,18 @@ impl Thread {
inner.looper_flags &= !(LooperFlag::Waiting | LooperFlag::WaitingProc);
if signal_pending || inner.looper_need_return {
- // We need to return now. We need to pull the thread off the list of ready threads
- // (by dropping `reg`), then check the state again after it's off the list to
- // ensure that something was not queued in the meantime. If something has been
- // queued, we just return it (instead of the error).
+ // We need to return now.
+ //
+ // We need to pull the thread off the list of ready threads (by dropping `reg`),
+ // then check the state again after it's off the list to ensure that something was
+ // not queued in the meantime. If something has been queued (or if there is
+ // deferred work), we just return it (instead of the error).
drop(inner);
drop(reg);
- let res = match self.inner.lock().pop_work() {
+ inner = self.inner.lock();
+ inner.process_work_list = true;
+ let res = match inner.pop_work() {
Some(work) => Ok(Some(work)),
None if signal_pending => Err(EINTR),
None => Ok(None),
@@ -686,6 +710,12 @@ impl Thread {
self.inner.lock().push_return_work(reply);
}
+ pub(crate) fn pop_work_even_if_deferred(&self) -> Option<DLArc<dyn DeliverToRead>> {
+ let mut thread_inner = self.inner.lock();
+ thread_inner.process_work_list = true;
+ thread_inner.pop_work()
+ }
+
fn translate_object(
&self,
obj_index: usize,
@@ -1250,7 +1280,7 @@ impl Thread {
cmd: u32,
reader: &mut UserSliceReader,
info: &mut TransactionInfo,
- ) -> Result<()> {
+ ) -> Result {
let td = match cmd {
BC_TRANSACTION | BC_REPLY => {
reader.read::<BinderTransactionData>()?.with_buffers_size(0)
@@ -1281,7 +1311,7 @@ impl Thread {
}
#[inline(never)]
- fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Result<()> {
+ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Result {
let mut info = TransactionInfo::zeroed();
self.read_transaction_info(cmd, reader, &mut info)?;
@@ -1410,8 +1440,16 @@ impl Thread {
let process = orig.from.process.clone();
let allow_fds = orig.flags.contains(TransactionFlag::AcceptFds);
let reply = Transaction::new_reply(self, process, info, allow_fds)?;
- // Not notifying: Reply to current thread.
- let _ = self.inner.lock().push_work(completion);
+ {
+ let mut inner = self.inner.lock();
+ if info.flags.contains(TransactionFlag::DeferComplete) {
+ // The flag is set. Perform a deferred push so that `read` can wait for the
+ // next incoming transaction without a userspace roundtrip.
+ inner.push_work_deferred(completion);
+ } else {
+ let _ = inner.push_work(completion);
+ }
+ }
orig.from.deliver_reply(Ok(reply), &orig, None);
Ok(())
})()
@@ -1678,7 +1716,7 @@ impl Thread {
self.unwind_transaction_stack();
// Cancel all pending work items.
- while let Ok(Some(work)) = self.get_work_local(false) {
+ while let Some(work) = self.pop_work_even_if_deferred() {
work.into_arc().cancel();
}
}
@@ -1738,7 +1776,7 @@ impl DeliverToRead for ThreadError {
false
}
- fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result<()> {
+ fn debug_print(&self, m: &SeqFile, prefix: &str, _tprefix: &str) -> Result {
seq_print!(
m,
"{}transaction error: {}\n",
diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
index 245f1556b5db..888a9e0eba8f 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -39,6 +39,7 @@ kernel::impl_flags!(
AcceptFds = TF_ACCEPT_FDS,
ClearBuf = TF_CLEAR_BUF,
UpdateTxn = TF_UPDATE_TXN,
+ DeferComplete = TF_DEFER_COMPLETE,
}
);
@@ -576,7 +577,7 @@ impl DeliverToRead for Transaction {
!self.flags.is_oneway()
}
- fn debug_print(&self, m: &SeqFile, _prefix: &str, tprefix: &str) -> Result<()> {
+ fn debug_print(&self, m: &SeqFile, _prefix: &str, tprefix: &str) -> Result {
self.debug_print_inner(m, tprefix);
Ok(())
}