mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-09 10:55:21 +02:00
ANDROID: rust_binder: add TF_UPDATE_TXN support
When a process is frozen, incoming oneway transactions are held in a queue until the process is unfrozen. If many oneway transactions are sent, then the process could run out of space for them. This patch adds a flag that avoids this by replacing previous oneway transactions in the queue to avoid having transactions of the same type build up. This can be useful when only the most recent transaction is necessary. Link: https://lore.kernel.org/rust-for-linux/20231101-rust-binder-v1-16-08ba9197f637@google.com/ Change-Id: I2f99cc54a065c0eef60324e860610b562e910a8d Signed-off-by: Alice Ryhl <aliceryhl@google.com> Bug: 278052745
This commit is contained in:
parent
50259804b1
commit
6249f06992
|
@ -63,7 +63,13 @@ pub_no_prefix!(
|
||||||
FLAT_BINDER_FLAG_TXN_SECURITY_CTX
|
FLAT_BINDER_FLAG_TXN_SECURITY_CTX
|
||||||
);
|
);
|
||||||
|
|
||||||
pub_no_prefix!(transaction_flags_, TF_ONE_WAY, TF_ACCEPT_FDS, TF_CLEAR_BUF);
|
pub_no_prefix!(
|
||||||
|
transaction_flags_,
|
||||||
|
TF_ONE_WAY,
|
||||||
|
TF_ACCEPT_FDS,
|
||||||
|
TF_CLEAR_BUF,
|
||||||
|
TF_UPDATE_TXN
|
||||||
|
);
|
||||||
|
|
||||||
pub(crate) use bindings::{
|
pub(crate) use bindings::{
|
||||||
BINDER_TYPE_BINDER, BINDER_TYPE_FD, BINDER_TYPE_FDA, BINDER_TYPE_HANDLE, BINDER_TYPE_PTR,
|
BINDER_TYPE_BINDER, BINDER_TYPE_FD, BINDER_TYPE_FDA, BINDER_TYPE_HANDLE, BINDER_TYPE_PTR,
|
||||||
|
|
|
@ -356,6 +356,25 @@ impl Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Finds an outdated transaction that the given transaction can replace.
|
||||||
|
///
|
||||||
|
/// If one is found, it is removed from the list and returned.
|
||||||
|
pub(crate) fn take_outdated_transaction(
|
||||||
|
&self,
|
||||||
|
new: &Transaction,
|
||||||
|
guard: &mut Guard<'_, ProcessInner, SpinLockBackend>,
|
||||||
|
) -> Option<DLArc<Transaction>> {
|
||||||
|
let inner = self.inner.access_mut(guard);
|
||||||
|
let mut cursor_opt = inner.oneway_todo.cursor_front();
|
||||||
|
while let Some(cursor) = cursor_opt {
|
||||||
|
if new.can_replace(&cursor.current()) {
|
||||||
|
return Some(cursor.remove());
|
||||||
|
}
|
||||||
|
cursor_opt = cursor.next();
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeliverToRead for Node {
|
impl DeliverToRead for Node {
|
||||||
|
|
|
@ -202,6 +202,9 @@ impl Transaction {
|
||||||
///
|
///
|
||||||
/// Not used for replies.
|
/// Not used for replies.
|
||||||
pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
|
pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
|
||||||
|
// Defined before `process_inner` so that the destructor runs after releasing the lock.
|
||||||
|
let mut _t_outdated = None;
|
||||||
|
|
||||||
let oneway = self.flags & TF_ONE_WAY != 0;
|
let oneway = self.flags & TF_ONE_WAY != 0;
|
||||||
let process = self.to.clone();
|
let process = self.to.clone();
|
||||||
let mut process_inner = process.inner.lock();
|
let mut process_inner = process.inner.lock();
|
||||||
|
@ -212,6 +215,10 @@ impl Transaction {
|
||||||
if let Some(target_node) = self.target_node.clone() {
|
if let Some(target_node) = self.target_node.clone() {
|
||||||
if process_inner.is_frozen {
|
if process_inner.is_frozen {
|
||||||
process_inner.async_recv = true;
|
process_inner.async_recv = true;
|
||||||
|
if self.flags & TF_UPDATE_TXN != 0 {
|
||||||
|
_t_outdated =
|
||||||
|
target_node.take_outdated_transaction(&self, &mut process_inner);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
match target_node.submit_oneway(self, &mut process_inner) {
|
match target_node.submit_oneway(self, &mut process_inner) {
|
||||||
Ok(()) => return Ok(()),
|
Ok(()) => return Ok(()),
|
||||||
|
@ -252,6 +259,25 @@ impl Transaction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check whether one oneway transaction can supersede another.
|
||||||
|
pub(crate) fn can_replace(&self, old: &Transaction) -> bool {
|
||||||
|
if self.from.process.task.pid() != old.from.process.task.pid() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.flags & old.flags & (TF_ONE_WAY | TF_UPDATE_TXN) != (TF_ONE_WAY | TF_UPDATE_TXN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let target_node_match = match (self.target_node.as_ref(), old.target_node.as_ref()) {
|
||||||
|
(None, None) => true,
|
||||||
|
(Some(tn1), Some(tn2)) => Arc::ptr_eq(tn1, tn2),
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.code == old.code && self.flags == old.flags && target_node_match
|
||||||
|
}
|
||||||
|
|
||||||
fn prepare_file_list(&self) -> Result<TranslatedFds> {
|
fn prepare_file_list(&self) -> Result<TranslatedFds> {
|
||||||
let mut alloc = self.allocation.lock().take().ok_or(ESRCH)?;
|
let mut alloc = self.allocation.lock().take().ok_or(ESRCH)?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user