diff options
Diffstat (limited to 'drivers/android/binder/thread.rs')
| -rw-r--r-- | drivers/android/binder/thread.rs | 78 |
1 files changed, 39 insertions, 39 deletions
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs index a7a190e1b000..a51821dde0ad 100644 --- a/drivers/android/binder/thread.rs +++ b/drivers/android/binder/thread.rs @@ -9,15 +9,14 @@ use kernel::{ bindings, - fs::{File, LocalFile}, + fs::LocalFile, list::{AtomicTracker, List, ListArc, ListLinks, TryNewListArc}, prelude::*, security, seq_file::SeqFile, seq_print, sync::atomic::{ordering::Relaxed, Atomic}, - sync::poll::{PollCondVar, PollTable}, - sync::{aref::ARef, Arc, SpinLock}, + sync::{aref::ARef, Arc, CondVar, SpinLock}, task::Task, uaccess::{UserPtr, UserSlice, UserSliceReader}, uapi, @@ -225,8 +224,10 @@ impl UnusedBufferSpace { } } +#[must_use] pub(crate) enum PushWorkRes { Ok, + OkNotifyPoll, FailedDead(DLArc<dyn DeliverToRead>), } @@ -234,6 +235,7 @@ impl PushWorkRes { fn is_ok(&self) -> bool { match self { PushWorkRes::Ok => true, + PushWorkRes::OkNotifyPoll => true, PushWorkRes::FailedDead(_) => false, } } @@ -310,27 +312,32 @@ impl InnerThread { fn push_work(&mut self, work: DLArc<dyn DeliverToRead>) -> PushWorkRes { if self.is_dead { - PushWorkRes::FailedDead(work) + return PushWorkRes::FailedDead(work); + } + self.work_list.push_back(work); + self.process_work_list = true; + if self.looper_flags & LOOPER_POLL != 0 { + PushWorkRes::OkNotifyPoll } else { - self.work_list.push_back(work); - self.process_work_list = true; PushWorkRes::Ok } } - fn push_reply_work(&mut self, code: u32) { + fn push_reply_work(&mut self, code: u32) -> PushWorkRes { if let Ok(work) = ListArc::try_from_arc(self.reply_work.clone()) { work.set_error_code(code); - self.push_work(work); + self.push_work(work) } else { pr_warn!("Thread reply work is already in use."); + PushWorkRes::Ok } } fn push_return_work(&mut self, reply: u32) { if let Ok(work) = ListArc::try_from_arc(self.return_work.clone()) { work.set_error_code(reply); - self.push_work(work); + // Not notifying: Reply to current thread. + let _ = self.push_work(work); } else { pr_warn!("Thread return work is already in use."); } @@ -422,7 +429,7 @@ pub(crate) struct Thread { #[pin] inner: SpinLock<InnerThread>, #[pin] - work_condvar: PollCondVar, + work_condvar: CondVar, /// Used to insert this thread into the process' `ready_threads` list. /// /// INVARIANT: May never be used for any other list than the `self.process.ready_threads`. @@ -453,7 +460,7 @@ impl Thread { process, task: ARef::from(&**kernel::current!()), inner <- kernel::new_spinlock!(inner, "Thread::inner"), - work_condvar <- kernel::new_poll_condvar!("Thread::work_condvar"), + work_condvar <- kernel::new_condvar!("Thread::work_condvar"), links <- ListLinks::new(), links_track <- AtomicTracker::new(), }), @@ -624,7 +631,14 @@ impl Thread { /// Returns whether the item was successfully pushed. This can only fail if the thread is dead. pub(crate) fn push_work(&self, work: DLArc<dyn DeliverToRead>) -> PushWorkRes { let sync = work.should_sync_wakeup(); + self.push_work_inner(work, sync) + } + pub(crate) fn push_work_inner( + &self, + work: DLArc<dyn DeliverToRead>, + sync: bool, + ) -> PushWorkRes { let res = self.inner.lock().push_work(work); if res.is_ok() { @@ -643,7 +657,8 @@ impl Thread { pub(crate) fn push_work_if_looper(&self, work: DLArc<dyn DeliverToRead>) -> BinderResult { let mut inner = self.inner.lock(); if inner.is_looper() && !inner.is_dead { - inner.push_work(work); + // Not notifying: Reply to current thread. + let _ = inner.push_work(work); Ok(()) } else { drop(inner); @@ -1160,7 +1175,7 @@ impl Thread { transaction.set_outstanding(&mut self.process.inner.lock()); } - { + let ret = { let mut inner = self.inner.lock(); if !inner.pop_transaction_replied(transaction) { return false; @@ -1177,15 +1192,16 @@ impl Thread { } match reply { - Ok(work) => { - inner.push_work(work); - } + Ok(work) => inner.push_work(work), Err(code) => inner.push_reply_work(code), } - } + }; // Notify the thread now that we've released the inner lock. self.work_condvar.notify_sync(); + if matches!(ret, PushWorkRes::OkNotifyPoll) { + self.process.notify_poll(true); + } false } @@ -1382,7 +1398,8 @@ impl Thread { let process = orig.from.process.clone(); let allow_fds = orig.flags & TF_ACCEPT_FDS != 0; let reply = Transaction::new_reply(self, process, info, allow_fds)?; - self.inner.lock().push_work(completion); + // Not notifying: Reply to current thread. + let _ = self.inner.lock().push_work(completion); orig.from.deliver_reply(Ok(reply), &orig, None); Ok(()) })() @@ -1421,7 +1438,8 @@ impl Thread { let list_completion = DTRWrap::arc_try_new(DeliverCode::new(code, self.process.task.pid()))?; let completion = list_completion.clone_arc(); - self.inner.lock().push_work(list_completion); + // Not notifying: Reply to current thread. + let _ = self.inner.lock().push_work(list_completion); match transaction.submit(info) { Ok(()) => Ok(()), Err(err) => { @@ -1623,10 +1641,9 @@ impl Thread { ret } - pub(crate) fn poll(&self, file: &File, table: PollTable<'_>) -> (bool, u32) { - table.register_wait(file, &self.work_condvar); + pub(crate) fn poll(&self) -> Result<(bool, u32)> { let mut inner = self.inner.lock(); - (inner.should_use_process_work_queue(), inner.poll()) + Ok((inner.should_use_process_work_queue(), inner.poll())) } /// Make the call to `get_work` or `get_work_local` return immediately, if any. @@ -1643,26 +1660,9 @@ 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(); - drop(inner); - - // Now that the lock is no longer held, notify the waiters if we have to. - if notify { - if sync { - self.work_condvar.notify_sync(); - } else { - self.work_condvar.notify_one(); - } - } - } - pub(crate) fn release(self: &Arc<Self>) { self.inner.lock().is_dead = true; - //self.work_condvar.clear(); self.unwind_transaction_stack(); // Cancel all pending work items. |
