spin_unlock(&node->lock);
}
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+/*
+ * Binder Debug Snapshot
+ */
+static void init_binder_transaction_base(int type, struct trace_binder_transaction_base *base,
+ struct binder_transaction *t, struct binder_thread *from,
+ struct binder_thread *to)
+{
+ struct binder_thread *t_from;
+ struct binder_thread *t_to;
+
+ if (base == NULL)
+ return;
+
+ t_from = t->from ? t->from : (from ? from : NULL);
+ t_to = t->to_thread ? t->to_thread : (to ? to : NULL);
+ base->trace_type = type;
+ base->transaction_id = t->debug_id;
+ base->from_pid = t_from ? t_from->proc->pid : 0;
+ base->from_tid = t_from ? t_from->pid : 0;
+ base->to_pid = t->to_proc ? t->to_proc->pid : 0;
+ base->to_tid = t_to ? t_to->pid : 0;
+ if (t_from) {
+ strncpy(base->from_pid_comm, t_from->proc->tsk->comm, TASK_COMM_LEN);
+ strncpy(base->from_tid_comm, t_from->task->comm, TASK_COMM_LEN);
+ } else {
+ base->from_pid_comm[0] = '\0';
+ base->from_tid_comm[0] = '\0';
+ }
+ if (t->to_proc)
+ strncpy(base->to_pid_comm, t->to_proc->tsk->comm, TASK_COMM_LEN);
+ else
+ base->to_pid_comm[0] = '\0';
+ if (t_to)
+ strncpy(base->to_tid_comm, t_to->task->comm, TASK_COMM_LEN);
+ else
+ base->to_tid_comm[0] = '\0';
+}
+
+static void dss_binder_transaction(int reply, struct binder_transaction *t, struct binder_thread *from, int to_node_id)
+{
+ struct trace_binder_transaction_base base;
+ struct trace_binder_transaction transaction;
+
+ init_binder_transaction_base(TRANSACTION, &base, t, from, NULL);
+ transaction.to_node_id = to_node_id;
+ transaction.reply = reply;
+ transaction.flags = t->flags;
+ transaction.code = t->code;
+
+ dbg_snapshot_binder(&base, &transaction, NULL);
+}
+
+static void dss_binder_transaction_received(struct binder_transaction *t, struct binder_thread *to)
+{
+ struct trace_binder_transaction_base base;
+
+ init_binder_transaction_base(TRANSACTION_DONE, &base, t, NULL, to);
+
+ dbg_snapshot_binder(&base, NULL, NULL);
+}
+
+static void dss_binder_transaction_failed(int reply, struct binder_transaction_log_entry *e,
+ char *from_pid_comm, char *from_tid_comm,
+ unsigned int flags, unsigned int code)
+{
+ struct trace_binder_transaction_base base;
+ struct trace_binder_transaction transaction;
+ struct trace_binder_transaction_error error;
+
+ base.trace_type = TRANSACTION_ERROR;
+ base.transaction_id = e->debug_id;
+ base.from_pid = e->from_proc;
+ base.from_tid = e->from_thread;
+ base.to_pid = e->to_proc;
+ base.to_tid = e->to_thread;
+ strncpy(base.from_pid_comm, from_pid_comm, TASK_COMM_LEN);
+ strncpy(base.from_tid_comm, from_tid_comm, TASK_COMM_LEN);
+ base.to_pid_comm[0] = '\0';
+ base.to_tid_comm[0] = '\0';
+ transaction.to_node_id = e->to_node;
+ transaction.reply = reply;
+ transaction.flags = flags;
+ transaction.code = code;
+ error.return_error = e->return_error;
+ error.return_error_param = e->return_error_param;
+ error.return_error_line = e->return_error_line;
+
+ dbg_snapshot_binder(&base, &transaction, &error);
+}
+#endif /* CONFIG_DEBUG_SNAPSHOT_BINDER */
+
static bool binder_worklist_empty_ilocked(struct list_head *list)
{
return list_empty(list);
t->priority = target_proc->default_priority;
}
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+ dss_binder_transaction(reply, t, t->from ? t->from : thread, target_node ? target_node->debug_id : 0);
+#endif
trace_binder_transaction(reply, t, target_node);
t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
e->return_error = return_error;
e->return_error_param = return_error_param;
e->return_error_line = return_error_line;
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+ dss_binder_transaction_failed(reply, e, proc->tsk->comm, thread->task->comm, tr->flags, tr->code);
+#endif
fe = binder_transaction_log_add(&binder_transaction_log_failed);
*fe = *e;
/*
}
ptr += sizeof(tr);
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+ dss_binder_transaction_received(t, thread);
+#endif
trace_binder_transaction_received(t);
binder_stat_br(proc, thread, cmd);
binder_debug(BINDER_DEBUG_TRANSACTION,
#ifdef CONFIG_DEBUG_SNAPSHOT
#include <asm/ptrace.h>
#include <linux/bug.h>
+#include "debug-snapshot-binder.h"
/* mandatory */
extern void dbg_snapshot_task(int cpu, void *v_task);
#define s3c2410wdt_keepalive_emergency(a, b) do { } while(0)
#endif
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+extern void dbg_snapshot_binder(struct trace_binder_transaction_base *base,
+ struct trace_binder_transaction *transaction,
+ struct trace_binder_transaction_error *error);
+#else
+#define dbg_snapshot_binder(a,b,c) do { } while(0)
+#endif
+
#else
#define dbg_snapshot_acpm(a,b,c) do { } while(0)
#define dbg_snapshot_task(a,b) do { } while(0)
#define dbg_snapshot_get_last_pc_paddr() do { } while(0)
#define dbg_snapshot_hook_hardlockup_entry(a) do { } while(0)
#define dbg_snapshot_hook_hardlockup_exit() do { } while(0)
+#define dbg_snapshot_binder(a,b,c) do { } while(0)
+
static inline unsigned int dbg_snapshot_get_item_size(char *name)
{
#ifdef CONFIG_DEBUG_SNAPSHOT_SPI
atomic_t spi_log_idx;
#endif
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+ atomic_t binder_log_idx;
+#endif
#ifndef CONFIG_DEBUG_SNAPSHOT_MINIMIZED_MODE
atomic_t clockevent_log_idx[DSS_NR_CPUS];
atomic_t printkl_log_idx;
#endif
#ifdef CONFIG_DEBUG_SNAPSHOT_SPI
atomic_set(&(dss_idx.spi_log_idx), -1);
+#endif
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+ atomic_set(&(dss_idx.binder_log_idx), -1);
#endif
atomic_set(&(dss_idx.suspend_log_idx), -1);
}
#endif
+#ifdef CONFIG_DEBUG_SNAPSHOT_BINDER
+void dbg_snapshot_binder(struct trace_binder_transaction_base *base,
+ struct trace_binder_transaction *transaction,
+ struct trace_binder_transaction_error *error)
+{
+ struct dbg_snapshot_item *item = &dss_items[dss_desc.kevents_num];
+ int cpu;
+ unsigned long i;
+
+ if (unlikely(!dss_base.enabled || !item->entry.enabled))
+ return;
+ if (base == NULL)
+ return;
+
+ cpu = raw_smp_processor_id();
+ i = atomic_inc_return(&dss_idx.binder_log_idx) &
+ (ARRAY_SIZE(dss_log->binder) - 1);
+
+ dss_log->binder[i].time = cpu_clock(cpu);
+ dss_log->binder[i].cpu = cpu;
+ dss_log->binder[i].base = *base;
+
+ if (transaction) {
+ dss_log->binder[i].transaction = *transaction;
+ } else {
+ dss_log->binder[i].transaction.to_node_id = 0;
+ dss_log->binder[i].transaction.reply = 0;
+ dss_log->binder[i].transaction.flags = 0;
+ dss_log->binder[i].transaction.code = 0;
+ }
+ if (error) {
+ dss_log->binder[i].error = *error;
+ } else {
+ dss_log->binder[i].error.return_error = 0;
+ dss_log->binder[i].error.return_error_param = 0;
+ dss_log->binder[i].error.return_error_line = 0;
+ }
+}
+#endif
+
#ifdef CONFIG_DEBUG_SNAPSHOT_ACPM
void dbg_snapshot_acpm(unsigned long long timestamp, const char *log, unsigned int data)
{