From: Martijn Coenen <maco@android.com>
To: gregkh@linuxfoundation.org, john.stultz@linaro.org,
tkjos@google.com, arve@android.com, amit.pundir@linaro.org
Cc: linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org,
maco@google.com, malchev@google.com, ccross@android.com,
Martijn Coenen <maco@android.com>
Subject: [PATCH 05/13] ANDROID: binder: improve priority inheritance.
Date: Fri, 25 Aug 2017 11:33:27 +0200 [thread overview]
Message-ID: <20170825093335.100892-6-maco@android.com> (raw)
In-Reply-To: <20170825093335.100892-1-maco@android.com>
By raising the priority of a thread selected for
a transaction *before* we wake it up.
Delay restoring the priority when doing a reply
until after we wake-up the process receiving
the reply.
Signed-off-by: Martijn Coenen <maco@android.com>
---
drivers/android/binder.c | 74 ++++++++++++++++++++++++++++++++++--------------
1 file changed, 53 insertions(+), 21 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 247e913a6e6a..76d7544120a2 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -610,6 +610,7 @@ enum {
* @is_dead: thread is dead and awaiting free
* when outstanding transactions are cleaned up
* (protected by @proc->inner_lock)
+ * @task: struct task_struct for this thread
*
* Bookkeeping structure for binder threads.
*/
@@ -628,6 +629,7 @@ struct binder_thread {
struct binder_stats stats;
atomic_t tmp_ref;
bool is_dead;
+ struct task_struct *task;
};
struct binder_transaction {
@@ -646,6 +648,7 @@ struct binder_transaction {
unsigned int flags;
struct binder_priority priority;
struct binder_priority saved_priority;
+ bool set_priority_called;
kuid_t sender_euid;
/**
* @lock: protects @from, @to_proc, and @to_thread
@@ -1160,6 +1163,38 @@ static void binder_set_priority(struct task_struct *task,
set_user_nice(task, priority);
}
+static void binder_transaction_priority(struct task_struct *task,
+ struct binder_transaction *t,
+ struct binder_priority node_prio)
+{
+ struct binder_priority desired_prio;
+
+ if (t->set_priority_called)
+ return;
+
+ t->set_priority_called = true;
+ t->saved_priority.sched_policy = task->policy;
+ t->saved_priority.prio = task->normal_prio;
+
+ desired_prio.prio = t->priority.prio;
+ desired_prio.sched_policy = t->priority.sched_policy;
+
+ if (node_prio.prio < t->priority.prio ||
+ (node_prio.prio == t->priority.prio &&
+ node_prio.sched_policy == SCHED_FIFO)) {
+ /*
+ * In case the minimum priority on the node is
+ * higher (lower value), use that priority. If
+ * the priority is the same, but the node uses
+ * SCHED_FIFO, prefer SCHED_FIFO, since it can
+ * run unbounded, unlike SCHED_RR.
+ */
+ desired_prio = node_prio;
+ }
+
+ binder_set_priority(task, desired_prio);
+}
+
static struct binder_node *binder_get_node_ilocked(struct binder_proc *proc,
binder_uintptr_t ptr)
{
@@ -2633,11 +2668,15 @@ static bool binder_proc_transaction(struct binder_transaction *t,
{
struct list_head *target_list = NULL;
struct binder_node *node = t->buffer->target_node;
+ struct binder_priority node_prio;
bool oneway = !!(t->flags & TF_ONE_WAY);
bool wakeup = true;
BUG_ON(!node);
binder_node_lock(node);
+ node_prio.prio = node->min_priority;
+ node_prio.sched_policy = node->sched_policy;
+
if (oneway) {
BUG_ON(thread);
if (node->has_async_transaction) {
@@ -2659,12 +2698,14 @@ static bool binder_proc_transaction(struct binder_transaction *t,
if (!thread && !target_list)
thread = binder_select_thread_ilocked(proc);
- if (thread)
+ if (thread) {
target_list = &thread->todo;
- else if (!target_list)
+ binder_transaction_priority(thread->task, t, node_prio);
+ } else if (!target_list) {
target_list = &proc->todo;
- else
+ } else {
BUG_ON(target_list != &node->async_todo);
+ }
binder_enqueue_work_ilocked(&t->work, target_list);
@@ -2741,7 +2782,6 @@ static void binder_transaction(struct binder_proc *proc,
}
thread->transaction_stack = in_reply_to->to_parent;
binder_inner_proc_unlock(proc);
- binder_set_priority(current, in_reply_to->saved_priority);
target_thread = binder_get_txn_from_and_acq_inner(in_reply_to);
if (target_thread == NULL) {
return_error = BR_DEAD_REPLY;
@@ -3151,6 +3191,7 @@ static void binder_transaction(struct binder_proc *proc,
binder_enqueue_work_ilocked(&t->work, &target_thread->todo);
binder_inner_proc_unlock(target_proc);
wake_up_interruptible_sync(&target_thread->wait);
+ binder_set_priority(current, in_reply_to->saved_priority);
binder_free_transaction(in_reply_to);
} else if (!(t->flags & TF_ONE_WAY)) {
BUG_ON(t->buffer->async_transaction != 0);
@@ -3239,6 +3280,7 @@ static void binder_transaction(struct binder_proc *proc,
BUG_ON(thread->return_error.cmd != BR_OK);
if (in_reply_to) {
+ binder_set_priority(current, in_reply_to->saved_priority);
thread->return_error.cmd = BR_TRANSACTION_COMPLETE;
binder_enqueue_work(thread->proc,
&thread->return_error.work,
@@ -4050,26 +4092,13 @@ static int binder_thread_read(struct binder_proc *proc,
BUG_ON(t->buffer == NULL);
if (t->buffer->target_node) {
struct binder_node *target_node = t->buffer->target_node;
- struct binder_priority prio = t->priority;
+ struct binder_priority node_prio;
tr.target.ptr = target_node->ptr;
tr.cookie = target_node->cookie;
- t->saved_priority.sched_policy = current->policy;
- t->saved_priority.prio = current->normal_prio;
- if (target_node->min_priority < t->priority.prio ||
- (target_node->min_priority == t->priority.prio &&
- target_node->sched_policy == SCHED_FIFO)) {
- /*
- * In case the minimum priority on the node is
- * higher (lower value), use that priority. If
- * the priority is the same, but the node uses
- * SCHED_FIFO, prefer SCHED_FIFO, since it can
- * run unbounded, unlike SCHED_RR.
- */
- prio.sched_policy = target_node->sched_policy;
- prio.prio = target_node->min_priority;
- }
- binder_set_priority(current, prio);
+ node_prio.sched_policy = target_node->sched_policy;
+ node_prio.prio = target_node->min_priority;
+ binder_transaction_priority(current, t, node_prio);
cmd = BR_TRANSACTION;
} else {
tr.target.ptr = 0;
@@ -4245,6 +4274,8 @@ static struct binder_thread *binder_get_thread_ilocked(
binder_stats_created(BINDER_STAT_THREAD);
thread->proc = proc;
thread->pid = current->pid;
+ get_task_struct(current);
+ thread->task = current;
atomic_set(&thread->tmp_ref, 0);
init_waitqueue_head(&thread->wait);
INIT_LIST_HEAD(&thread->todo);
@@ -4295,6 +4326,7 @@ static void binder_free_thread(struct binder_thread *thread)
BUG_ON(!list_empty(&thread->todo));
binder_stats_deleted(BINDER_STAT_THREAD);
binder_proc_dec_tmpref(thread->proc);
+ put_task_struct(thread->task);
kfree(thread);
}
--
2.14.1.480.gb18f417b89-goog
next prev parent reply other threads:[~2017-08-25 9:34 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-25 9:33 [PATCH 00/13] ANDROID: binder: RT priority inheritance and small fixes Martijn Coenen
2017-08-25 9:33 ` [PATCH 01/13] ANDROID: binder: remove proc waitqueue Martijn Coenen
2017-08-25 9:33 ` [PATCH 02/13] ANDROID: binder: push new transactions to waiting threads Martijn Coenen
2017-08-25 9:33 ` [PATCH 03/13] ANDROID: binder: add support for RT prio inheritance Martijn Coenen
2017-08-25 15:08 ` Thomas Gleixner
2017-08-25 18:47 ` Martijn Coenen
2017-08-25 9:33 ` [PATCH 04/13] ANDROID: binder: add min sched_policy to node Martijn Coenen
2017-08-25 9:33 ` Martijn Coenen [this message]
2017-08-25 9:33 ` [PATCH 06/13] ANDROID: binder: add RT inheritance flag " Martijn Coenen
2017-08-25 9:33 ` [PATCH 07/13] Add BINDER_GET_NODE_DEBUG_INFO ioctl Martijn Coenen
2017-08-25 9:33 ` [PATCH 08/13] ANDROID: binder: don't check prio permissions on restore Martijn Coenen
2017-08-25 9:33 ` [PATCH 09/13] ANDROID: binder: Don't BUG_ON(!spin_is_locked()) Martijn Coenen
2017-08-25 9:33 ` [PATCH 10/13] ANDROID: binder: call poll_wait() unconditionally Martijn Coenen
2017-08-25 9:33 ` [PATCH 11/13] ANDROID: binder: don't enqueue death notifications to thread todo Martijn Coenen
2017-08-25 9:33 ` [PATCH 12/13] ANDROID: binder: don't queue async transactions to thread Martijn Coenen
2017-08-25 9:33 ` [PATCH 13/13] ANDROID: binder: Add tracing for binder priority inheritance Martijn Coenen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170825093335.100892-6-maco@android.com \
--to=maco@android.com \
--cc=amit.pundir@linaro.org \
--cc=arve@android.com \
--cc=ccross@android.com \
--cc=devel@driverdev.osuosl.org \
--cc=gregkh@linuxfoundation.org \
--cc=john.stultz@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maco@google.com \
--cc=malchev@google.com \
--cc=tkjos@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox