Commit b6d282ce authored by Todd Kjos's avatar Todd Kjos Committed by Greg Kroah-Hartman

binder: refactor binder_pop_transaction

binder_pop_transaction needs to be split into 2 pieces to
to allow the proc lock to be held on entry to dequeue the
transaction stack, but no lock when kfree'ing the transaction.

Split into binder_pop_transaction_locked and binder_free_transaction
(the actual locks are still to be added).
Signed-off-by: default avatarTodd Kjos <tkjos@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d99c7333
...@@ -768,14 +768,16 @@ static int binder_dec_ref(struct binder_ref *ref, int strong) ...@@ -768,14 +768,16 @@ static int binder_dec_ref(struct binder_ref *ref, int strong)
static void binder_pop_transaction(struct binder_thread *target_thread, static void binder_pop_transaction(struct binder_thread *target_thread,
struct binder_transaction *t) struct binder_transaction *t)
{ {
if (target_thread) { BUG_ON(!target_thread);
BUG_ON(target_thread->transaction_stack != t); BUG_ON(target_thread->transaction_stack != t);
BUG_ON(target_thread->transaction_stack->from != target_thread); BUG_ON(target_thread->transaction_stack->from != target_thread);
target_thread->transaction_stack = target_thread->transaction_stack =
target_thread->transaction_stack->from_parent; target_thread->transaction_stack->from_parent;
t->from = NULL; t->from = NULL;
} }
t->need_reply = 0;
static void binder_free_transaction(struct binder_transaction *t)
{
if (t->buffer) if (t->buffer)
t->buffer->transaction = NULL; t->buffer->transaction = NULL;
kfree(t); kfree(t);
...@@ -808,6 +810,7 @@ static void binder_send_failed_reply(struct binder_transaction *t, ...@@ -808,6 +810,7 @@ static void binder_send_failed_reply(struct binder_transaction *t,
binder_pop_transaction(target_thread, t); binder_pop_transaction(target_thread, t);
target_thread->return_error = error_code; target_thread->return_error = error_code;
wake_up_interruptible(&target_thread->wait); wake_up_interruptible(&target_thread->wait);
binder_free_transaction(t);
} else { } else {
pr_err("reply failed, target thread, %d:%d, has error code %d already\n", pr_err("reply failed, target thread, %d:%d, has error code %d already\n",
target_thread->proc->pid, target_thread->proc->pid,
...@@ -822,7 +825,7 @@ static void binder_send_failed_reply(struct binder_transaction *t, ...@@ -822,7 +825,7 @@ static void binder_send_failed_reply(struct binder_transaction *t,
"send failed reply for transaction %d, target dead\n", "send failed reply for transaction %d, target dead\n",
t->debug_id); t->debug_id);
binder_pop_transaction(target_thread, t); binder_free_transaction(t);
if (next == NULL) { if (next == NULL) {
binder_debug(BINDER_DEBUG_DEAD_BINDER, binder_debug(BINDER_DEBUG_DEAD_BINDER,
"reply failed, no target thread at root\n"); "reply failed, no target thread at root\n");
...@@ -1806,6 +1809,7 @@ static void binder_transaction(struct binder_proc *proc, ...@@ -1806,6 +1809,7 @@ static void binder_transaction(struct binder_proc *proc,
if (reply) { if (reply) {
BUG_ON(t->buffer->async_transaction != 0); BUG_ON(t->buffer->async_transaction != 0);
binder_pop_transaction(target_thread, in_reply_to); binder_pop_transaction(target_thread, in_reply_to);
binder_free_transaction(in_reply_to);
} else if (!(t->flags & TF_ONE_WAY)) { } else if (!(t->flags & TF_ONE_WAY)) {
BUG_ON(t->buffer->async_transaction != 0); BUG_ON(t->buffer->async_transaction != 0);
t->need_reply = 1; t->need_reply = 1;
...@@ -2635,9 +2639,7 @@ static int binder_thread_read(struct binder_proc *proc, ...@@ -2635,9 +2639,7 @@ static int binder_thread_read(struct binder_proc *proc,
t->to_thread = thread; t->to_thread = thread;
thread->transaction_stack = t; thread->transaction_stack = t;
} else { } else {
t->buffer->transaction = NULL; binder_free_transaction(t);
kfree(t);
binder_stats_deleted(BINDER_STAT_TRANSACTION);
} }
break; break;
} }
...@@ -2680,9 +2682,7 @@ static void binder_release_work(struct list_head *list) ...@@ -2680,9 +2682,7 @@ static void binder_release_work(struct list_head *list)
binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
"undelivered transaction %d\n", "undelivered transaction %d\n",
t->debug_id); t->debug_id);
t->buffer->transaction = NULL; binder_free_transaction(t);
kfree(t);
binder_stats_deleted(BINDER_STAT_TRANSACTION);
} }
} break; } break;
case BINDER_WORK_TRANSACTION_COMPLETE: { case BINDER_WORK_TRANSACTION_COMPLETE: {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment