binder: add locking for print functions

Protect data structures for binders debugging/printing utilities

Bug: 33250092 32225111
Change-Id: I3df4f7f0cd2ceb8a5f79696eaea2fb4f020e0e29
Signed-off-by: Todd Kjos <tkjos@google.com>
This commit is contained in:
Todd Kjos
2016-10-17 13:57:08 -07:00
committed by Thierry Strudel
parent edbe2b61b9
commit b5fc610f20

View File

@@ -3714,8 +3714,9 @@ binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer)
mutex_unlock(&binder_deferred_lock);
}
static void print_binder_transaction(struct seq_file *m, const char *prefix,
struct binder_transaction *t)
static void _print_binder_transaction(struct seq_file *m,
const char *prefix,
struct binder_transaction *t)
{
seq_printf(m,
"%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d",
@@ -3737,17 +3738,19 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix,
t->buffer->data);
}
static void print_binder_work(struct seq_file *m, const char *prefix,
const char *transaction_prefix,
struct binder_work *w)
static void _print_binder_work(struct seq_file *m, const char *prefix,
const char *transaction_prefix,
struct binder_work *w)
{
struct binder_node *node;
struct binder_transaction *t;
BUG_ON(!spin_is_locked(&w->wlist->lock));
switch (w->type) {
case BINDER_WORK_TRANSACTION:
t = container_of(w, struct binder_transaction, work);
print_binder_transaction(m, transaction_prefix, t);
_print_binder_transaction(m, transaction_prefix, t);
break;
case BINDER_WORK_TRANSACTION_COMPLETE:
seq_printf(m, "%stransaction complete\n", prefix);
@@ -3773,46 +3776,56 @@ static void print_binder_work(struct seq_file *m, const char *prefix,
}
}
static void print_binder_thread(struct seq_file *m,
struct binder_thread *thread,
int print_always)
static void _print_binder_thread(struct seq_file *m,
struct binder_thread *thread,
int print_always)
{
struct binder_transaction *t;
struct binder_work *w;
size_t start_pos = m->count;
size_t header_pos;
BUG_ON(!spin_is_locked(&thread->proc->proc_lock));
seq_printf(m, " thread %d: l %02x\n", thread->pid, thread->looper);
header_pos = m->count;
t = thread->transaction_stack;
while (t) {
if (t->from == thread) {
print_binder_transaction(m,
" outgoing transaction", t);
_print_binder_transaction(m,
" outgoing transaction", t);
t = t->from_parent;
} else if (t->to_thread == thread) {
print_binder_transaction(m,
" incoming transaction", t);
_print_binder_transaction(m,
" incoming transaction", t);
t = t->to_parent;
} else {
print_binder_transaction(m, " bad transaction", t);
_print_binder_transaction(m,
" bad transaction", t);
t = NULL;
}
}
spin_lock(&thread->todo.lock);
list_for_each_entry(w, &thread->todo.list, entry) {
print_binder_work(m, " ", " pending transaction", w);
_print_binder_work(m, " ", " pending transaction", w);
}
spin_unlock(&thread->todo.lock);
if (!print_always && m->count == header_pos)
m->count = start_pos;
}
static void print_binder_node(struct seq_file *m, struct binder_node *node)
static void _print_binder_node(struct seq_file *m,
struct binder_node *node)
{
struct binder_ref *ref;
struct binder_work *w;
int count;
struct binder_proc *proc = node->proc;
if (proc)
BUG_ON(!spin_is_locked(&proc->proc_lock));
else
BUG_ON(!mutex_is_locked(&binder_dead_nodes_lock));
count = 0;
hlist_for_each_entry(ref, &node->refs, node_entry)
@@ -3829,14 +3842,18 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node)
seq_printf(m, " %d", ref->proc->pid);
}
seq_puts(m, "\n");
spin_lock(&node->async_todo.lock);
list_for_each_entry(w, &node->async_todo.list, entry)
print_binder_work(m, " ",
" pending async transaction", w);
_print_binder_work(m, " ",
" pending async transaction", w);
spin_unlock(&node->async_todo.lock);
}
static void print_binder_ref(struct seq_file *m, struct binder_ref *ref)
static void _print_binder_ref(struct seq_file *m,
struct binder_ref *ref)
{
seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %p\n",
BUG_ON(!spin_is_locked(&ref->proc->proc_lock));
seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %pK\n",
ref->debug_id, ref->desc, ref->node->proc ? "" : "dead ",
ref->node->debug_id, atomic_read(&ref->strong),
atomic_read(&ref->weak), ref->death);
@@ -3854,26 +3871,29 @@ static void print_binder_proc(struct seq_file *m,
seq_printf(m, "context %s\n", proc->context->name);
header_pos = m->count;
binder_proc_lock(proc, __LINE__);
for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
print_binder_thread(m, rb_entry(n, struct binder_thread,
rb_node), print_all);
_print_binder_thread(m, rb_entry(n, struct binder_thread,
rb_node), print_all);
for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) {
struct binder_node *node = rb_entry(n, struct binder_node,
rb_node);
if (print_all || node->has_async_transaction)
print_binder_node(m, node);
_print_binder_node(m, node);
}
if (print_all) {
for (n = rb_first(&proc->refs_by_desc);
n != NULL;
n = rb_next(n))
print_binder_ref(m, rb_entry(n, struct binder_ref,
rb_node_desc));
_print_binder_ref(m, rb_entry(n, struct binder_ref,
rb_node_desc));
}
binder_proc_unlock(proc, __LINE__);
binder_alloc_print_allocated(m, &proc->alloc);
spin_lock(&proc->todo.lock);
list_for_each_entry(w, &proc->todo.list, entry)
print_binder_work(m, " ", " pending transaction", w);
_print_binder_work(m, " ", " pending transaction", w);
spin_unlock(&proc->todo.lock);
spin_lock(&proc->delivered_death.lock);
list_for_each_entry(w, &proc->delivered_death.list, entry) {
@@ -3992,8 +4012,10 @@ static void print_binder_proc_stats(struct seq_file *m,
seq_printf(m, "proc %d\n", proc->pid);
seq_printf(m, "context %s\n", proc->context->name);
count = 0;
binder_proc_lock(proc, __LINE__);
for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
count++;
binder_proc_unlock(proc, __LINE__);
seq_printf(m, " threads: %d\n", count);
seq_printf(m, " requested threads: %d+%d/%d\n"
" ready threads %d\n"
@@ -4004,12 +4026,15 @@ static void print_binder_proc_stats(struct seq_file *m,
atomic_read(&proc->ready_threads),
binder_alloc_get_free_async_space(&proc->alloc));
count = 0;
binder_proc_lock(proc, __LINE__);
for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n))
count++;
binder_proc_unlock(proc, __LINE__);
seq_printf(m, " nodes: %d\n", count);
count = 0;
strong = 0;
weak = 0;
binder_proc_lock(proc, __LINE__);
for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
struct binder_ref *ref = rb_entry(n, struct binder_ref,
rb_node_desc);
@@ -4017,6 +4042,7 @@ static void print_binder_proc_stats(struct seq_file *m,
strong += atomic_read(&ref->strong);
weak += atomic_read(&ref->weak);
}
binder_proc_unlock(proc, __LINE__);
seq_printf(m, " refs: %d s %d w %d\n", count, strong, weak);
count = binder_alloc_get_allocated_count(&proc->alloc);
@@ -4050,7 +4076,7 @@ static int binder_state_show(struct seq_file *m, void *unused)
if (!hlist_empty(&binder_dead_nodes))
seq_puts(m, "dead nodes:\n");
hlist_for_each_entry(node, &binder_dead_nodes, dead_node)
print_binder_node(m, node);
_print_binder_node(m, node);
mutex_unlock(&binder_dead_nodes_lock);
mutex_lock(&binder_procs_lock);