Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 22 additions & 12 deletions drivers/android/binder/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use core::mem::take;

use kernel::{
bindings,
bits::bit_u8,
cred::Credential,
error::Error,
fs::file::{self, File},
Expand Down Expand Up @@ -70,9 +71,18 @@ impl Mapping {
}
}

// bitflags for defer_work.
const PROC_DEFER_FLUSH: u8 = 1;
const PROC_DEFER_RELEASE: u8 = 2;
kernel::impl_flags!(
/// Represents multiple deferred work flags.
#[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
pub struct DeferWorks(u8);

/// Represents a single deferred work category.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeferWork {
Flush = bit_u8(0),
Release = bit_u8(1),
}
Comment on lines +79 to +84

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this code I am thinking "why do you have to write 0 and 1 on these? Can't you just leave them out and let the macro pick bits for me". After all, with a normal macro you can just write:

enum MyMacro {
    Variant1,
    Variant2,
}

I know the macro doesn't support this yet, but maybe it should?

Totally optional if you want to implement that or not.

);

#[derive(Copy, Clone)]
pub(crate) enum IsFrozen {
Expand Down Expand Up @@ -121,7 +131,7 @@ pub(crate) struct ProcessInner {
started_thread_count: u32,

/// Bitmap of deferred work to do.
defer_work: u8,
defer_work: DeferWorks,

/// Number of transactions to be transmitted before processes in freeze_wait
/// are woken up.
Expand Down Expand Up @@ -151,7 +161,7 @@ impl ProcessInner {
requested_thread_count: 0,
max_threads: 0,
started_thread_count: 0,
defer_work: 0,
defer_work: DeferWorks::default(),
outstanding_txns: 0,
is_frozen: IsFrozen::No,
sync_recv: false,
Expand Down Expand Up @@ -489,13 +499,13 @@ impl workqueue::WorkItem for Process {
{
let mut inner = me.inner.lock();
defer = inner.defer_work;
inner.defer_work = 0;
inner.defer_work = DeferWorks::default();
}

if defer & PROC_DEFER_FLUSH != 0 {
if defer.contains(DeferWork::Flush) {
me.deferred_flush();
}
if defer & PROC_DEFER_RELEASE != 0 {
if defer.contains(DeferWork::Release) {
me.deferred_release();
}
}
Expand Down Expand Up @@ -1635,8 +1645,8 @@ impl Process {
let should_schedule;
{
let mut inner = this.inner.lock();
should_schedule = inner.defer_work == 0;
inner.defer_work |= PROC_DEFER_RELEASE;
should_schedule = inner.defer_work == DeferWorks::empty();
inner.defer_work |= DeferWork::Release;
binderfs_file = inner.binderfs_file.take();
}

Expand All @@ -1653,8 +1663,8 @@ impl Process {
let should_schedule;
{
let mut inner = this.inner.lock();
should_schedule = inner.defer_work == 0;
inner.defer_work |= PROC_DEFER_FLUSH;
should_schedule = inner.defer_work == DeferWorks::empty();
inner.defer_work |= DeferWork::Flush;
}

if should_schedule {
Expand Down
69 changes: 41 additions & 28 deletions drivers/android/binder/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

use kernel::{
bindings,
bits::bit_u32,
fs::{File, LocalFile},
list::{AtomicTracker, List, ListArc, ListLinks, TryNewListArc},
prelude::*,
Expand All @@ -30,7 +31,7 @@ use crate::{
process::{GetWorkOrRegister, Process},
ptr_align,
stats::GLOBAL_STATS,
transaction::{Transaction, TransactionInfo},
transaction::{Transaction, TransactionFlag, TransactionFlags, TransactionInfo},
BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverCode, DeliverToRead,
};

Expand Down Expand Up @@ -243,7 +244,7 @@ impl PushWorkRes {
struct InnerThread {
/// Determines the looper state of the thread. It is a bit-wise combination of the constants
/// prefixed with `LOOPER_`.
looper_flags: u32,
looper_flags: LooperFlags,

/// Determines whether the looper should return.
looper_need_return: bool,
Expand All @@ -270,13 +271,23 @@ struct InnerThread {
extended_error: ExtendedError,
}

const LOOPER_REGISTERED: u32 = 0x01;
const LOOPER_ENTERED: u32 = 0x02;
const LOOPER_EXITED: u32 = 0x04;
const LOOPER_INVALID: u32 = 0x08;
const LOOPER_WAITING: u32 = 0x10;
const LOOPER_WAITING_PROC: u32 = 0x20;
const LOOPER_POLL: u32 = 0x40;
kernel::impl_flags!(
/// Represents multiple looper flags.
#[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
pub struct LooperFlags(u32);

/// Represents a single looper flag.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LooperFlag {
Registered = bit_u32(0),
Entered = bit_u32(1),
Exited = bit_u32(2),
Invalid = bit_u32(3),
Waiting = bit_u32(4),
WaitingProc = bit_u32(5),
Poll = bit_u32(6),
}
);

impl InnerThread {
fn new() -> Result<Self> {
Expand All @@ -286,7 +297,7 @@ impl InnerThread {
}

Ok(Self {
looper_flags: 0,
looper_flags: LooperFlags::default(),
looper_need_return: false,
is_dead: false,
process_work_list: false,
Expand Down Expand Up @@ -373,26 +384,27 @@ impl InnerThread {
}

fn looper_enter(&mut self) {
self.looper_flags |= LOOPER_ENTERED;
if self.looper_flags & LOOPER_REGISTERED != 0 {
self.looper_flags |= LOOPER_INVALID;
self.looper_flags |= LooperFlag::Entered;
if self.looper_flags.contains(LooperFlag::Registered) {
self.looper_flags |= LooperFlag::Invalid;
}
}

fn looper_register(&mut self, valid: bool) {
self.looper_flags |= LOOPER_REGISTERED;
if !valid || self.looper_flags & LOOPER_ENTERED != 0 {
self.looper_flags |= LOOPER_INVALID;
self.looper_flags |= LooperFlag::Registered;
if !valid || self.looper_flags.contains(LooperFlag::Entered) {
self.looper_flags |= LooperFlag::Invalid;
}
}

fn looper_exit(&mut self) {
self.looper_flags |= LOOPER_EXITED;
self.looper_flags |= LooperFlag::Exited;
}

/// Determines whether the thread is part of a pool, i.e., if it is a looper.
fn is_looper(&self) -> bool {
self.looper_flags & (LOOPER_ENTERED | LOOPER_REGISTERED) != 0
self.looper_flags
.contains_any(LooperFlag::Entered | LooperFlag::Registered)
}

/// Determines whether the thread should attempt to fetch work items from the process queue.
Expand All @@ -404,7 +416,7 @@ impl InnerThread {
}

fn poll(&mut self) -> u32 {
self.looper_flags |= LOOPER_POLL;
self.looper_flags |= LooperFlag::Poll;
if self.process_work_list || self.looper_need_return {
bindings::POLLIN
} else {
Expand Down Expand Up @@ -470,7 +482,7 @@ impl Thread {
m,
" thread {}: l {:02x} need_return {}\n",
self.id,
inner.looper_flags,
u32::from(inner.looper_flags),
inner.looper_need_return,
);
}
Expand Down Expand Up @@ -536,9 +548,9 @@ impl Thread {
return Ok(Some(work));
}

inner.looper_flags |= LOOPER_WAITING;
inner.looper_flags |= LooperFlag::Waiting;
let signal_pending = self.work_condvar.wait_interruptible_freezable(&mut inner);
inner.looper_flags &= !LOOPER_WAITING;
inner.looper_flags &= !LooperFlag::Waiting;

if signal_pending {
return Err(EINTR);
Expand Down Expand Up @@ -590,9 +602,9 @@ impl Thread {
return Ok(Some(work));
}

inner.looper_flags |= LOOPER_WAITING | LOOPER_WAITING_PROC;
inner.looper_flags |= LooperFlag::Waiting | LooperFlag::WaitingProc;
let signal_pending = self.work_condvar.wait_interruptible_freezable(&mut inner);
inner.looper_flags &= !(LOOPER_WAITING | LOOPER_WAITING_PROC);
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
Expand Down Expand Up @@ -1214,7 +1226,7 @@ impl Thread {
info.from_pid = self.process.task.pid();
info.from_tid = self.id;
info.code = td.transaction_data.code;
info.flags = td.transaction_data.flags;
info.flags = TransactionFlags::from_bits(td.transaction_data.flags);
info.data_ptr = UserPtr::from_addr(trd_data_ptr.buffer as usize);
info.data_size = td.transaction_data.data_size as usize;
info.offsets_ptr = UserPtr::from_addr(trd_data_ptr.offsets as usize);
Expand Down Expand Up @@ -1317,7 +1329,7 @@ impl Thread {
let out = (|| -> BinderResult<_> {
let completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?;
let process = orig.from.process.clone();
let allow_fds = orig.flags & TF_ACCEPT_FDS != 0;
let allow_fds = orig.flags.contains(TransactionFlag::AcceptFds);
let reply = Transaction::new_reply(self, process, info, allow_fds)?;
self.inner.lock().push_work(completion);
orig.from.deliver_reply(Ok(reply), &orig);
Expand Down Expand Up @@ -1562,7 +1574,7 @@ impl Thread {
/// Make the call to `get_work` or `get_work_local` return immediately, if any.
pub(crate) fn exit_looper(&self) {
let mut inner = self.inner.lock();
let should_notify = inner.looper_flags & LOOPER_WAITING != 0;
let should_notify = inner.looper_flags.contains(LooperFlag::Waiting);
if should_notify {
inner.looper_need_return = true;
}
Expand All @@ -1576,7 +1588,8 @@ impl Thread {
pub(crate) fn notify_if_poll_ready(&self, sync: bool) {
// Determine if we need to notify. This requires the lock.
let inner = self.inner.lock();
let notify = inner.looper_flags & LOOPER_POLL != 0 && inner.should_use_process_work_queue();
let notify =
inner.looper_flags.contains(LooperFlag::Poll) && inner.should_use_process_work_queue();
drop(inner);

// Now that the lock is no longer held, notify the waiters if we have to.
Expand Down
Loading