Linux-mediatek Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v1 1/1] binder: transaction latency tracking for user build
@ 2020-02-05  6:52 Frankie Chang
  2020-02-05  9:36 ` Greg Kroah-Hartman
  0 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-02-05  6:52 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Todd Kjos, Martijn Coenen,
	Arve Hjønnevåg, Joel Fernandes, Christian Brauner
  Cc: Frankie Chang, Jian-Min.Liu, linux-mediatek, linux-kernel, wsd_upstream

Record start/end timestamp to binder transaction.
When transaction is completed or transaction is free,
it would be checked if transaction latency over threshold (2 sec),
if yes, printing related information for tracing.

Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/Kconfig           |    8 +++
 drivers/android/binder.c          |  107 +++++++++++++++++++++++++++++++++++++
 drivers/android/binder_internal.h |    4 ++
 3 files changed, 119 insertions(+)

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 6fdf2ab..7ba80eb 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
 	  exhaustively with combinations of various buffer sizes and
 	  alignments.
 
+config BINDER_USER_TRACKING
+	bool "Android Binder transaction tracking"
+	help
+	  Used for track abnormal binder transaction which is over 2 seconds,
+	  when the transaction is done or be free, this transaction would be
+	  checked whether it executed overtime.
+	  If yes, printing out the detail info about it.
+
 endif # if ANDROID
 
 endmenu
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index e9bc9fc..5a352ee 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -76,6 +76,11 @@
 #include "binder_internal.h"
 #include "binder_trace.h"
 
+#ifdef CONFIG_BINDER_USER_TRACKING
+#include <linux/rtc.h>
+#include <linux/time.h>
+#endif
+
 static HLIST_HEAD(binder_deferred_list);
 static DEFINE_MUTEX(binder_deferred_lock);
 
@@ -591,8 +596,104 @@ struct binder_transaction {
 	 * during thread teardown
 	 */
 	spinlock_t lock;
+#ifdef CONFIG_BINDER_USER_TRACKING
+	struct timespec timestamp;
+	struct timeval tv;
+#endif
 };
 
+#ifdef CONFIG_BINDER_USER_TRACKING
+
+/*
+ * binder_print_delay - Output info of a delay transaction
+ * @t:          pointer to the over-time transaction
+ */
+static void binder_print_delay(struct binder_transaction *t)
+{
+	struct rtc_time tm;
+	struct timespec *startime;
+	struct timespec cur, sub_t;
+
+	ktime_get_ts(&cur);
+	startime = &t->timestamp;
+	sub_t = timespec_sub(cur, *startime);
+
+	/* if transaction time is over than 2 sec,
+	 * show timeout warning log.
+	 */
+	if (sub_t.tv_sec < 2)
+		return;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+
+	spin_lock(&t->lock);
+	pr_info_ratelimited("%d: from %d:%d to %d:%d",
+			    t->debug_id,
+			    t->from ? t->from->proc->pid : 0,
+			    t->from ? t->from->pid : 0,
+			    t->to_proc ? t->to_proc->pid : 0,
+			    t->to_thread ? t->to_thread->pid : 0);
+	spin_unlock(&t->lock);
+
+	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
+			    (unsigned int)sub_t.tv_sec,
+			    (sub_t.tv_nsec / NSEC_PER_MSEC),
+			    t->code,
+			    (unsigned long)startime->tv_sec,
+			    (startime->tv_nsec / NSEC_PER_MSEC),
+			    (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+			    tm.tm_hour, tm.tm_min, tm.tm_sec,
+			    (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+
+static void binder_log_entry_setup(struct binder_transaction_log_entry *e)
+{
+	ktime_get_ts(&e->timestamp);
+	do_gettimeofday(&e->tv);
+	e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
+}
+
+static void timestamp_copy(struct binder_transaction *t,
+			   struct binder_transaction_log_entry *e)
+{
+	memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
+	memcpy(&t->tv, &e->tv, sizeof(struct timeval));
+}
+
+static void print_binder_transaction_ext(struct seq_file *m,
+					 struct binder_transaction *t)
+{
+	struct rtc_time tm;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+	seq_printf(m,
+		   " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
+		   (unsigned long)t->timestamp.tv_sec,
+		   (t->timestamp.tv_nsec / NSEC_PER_USEC),
+		   (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+		   tm.tm_hour, tm.tm_min, tm.tm_sec,
+		   (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+#else
+static void binder_print_delay(struct binder_transaction *t)
+{
+}
+
+static void binder_log_entry_setup(struct binder_transaction_log_entry *e)
+{
+}
+
+static void timestamp_copy(struct binder_transaction *t,
+			   struct binder_transaction_log_entry *e)
+{
+}
+
+static void print_binder_transaction_ext(struct seq_file *m,
+					 struct binder_transaction *t)
+{
+}
+#endif
+
 /**
  * struct binder_object - union of flat binder object types
  * @hdr:   generic object header
@@ -1927,6 +2028,7 @@ static void binder_free_transaction(struct binder_transaction *t)
 	 * If the transaction has no target_proc, then
 	 * t->buffer->transaction has already been cleared.
 	 */
+	binder_print_delay(t);
 	binder_free_txn_fixups(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
@@ -2872,6 +2974,8 @@ static void binder_transaction(struct binder_proc *proc,
 	e->offsets_size = tr->offsets_size;
 	strscpy(e->context_name, proc->context->name, BINDERFS_MAX_NAME);
 
+	binder_log_entry_setup(e);
+
 	if (reply) {
 		binder_inner_proc_lock(proc);
 		in_reply_to = thread->transaction_stack;
@@ -3058,6 +3162,7 @@ static void binder_transaction(struct binder_proc *proc,
 		return_error_line = __LINE__;
 		goto err_alloc_t_failed;
 	}
+	timestamp_copy(t, e);
 	INIT_LIST_HEAD(&t->fd_fixups);
 	binder_stats_created(BINDER_STAT_TRANSACTION);
 	spin_lock_init(&t->lock);
@@ -3496,6 +3601,7 @@ static void binder_transaction(struct binder_proc *proc,
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 err_alloc_tcomplete_failed:
+	binder_print_delay(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
 err_alloc_t_failed:
@@ -5544,6 +5650,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
 		   t->to_thread ? t->to_thread->pid : 0,
 		   t->code, t->flags, t->priority, t->need_reply);
 	spin_unlock(&t->lock);
+	print_binder_transaction_ext(m, t);
 
 	if (proc != to_proc) {
 		/*
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index ae99109..ea52c5d 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -131,6 +131,10 @@ struct binder_transaction_log_entry {
 	uint32_t return_error;
 	uint32_t return_error_param;
 	char context_name[BINDERFS_MAX_NAME + 1];
+#ifdef CONFIG_BINDER_USER_TRACKING
+	struct timespec timestamp;
+	struct timeval tv;
+#endif
 };
 
 struct binder_transaction_log {
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v1 1/1] binder: transaction latency tracking for user build
  2020-02-05  6:52 [PATCH v1 1/1] binder: transaction latency tracking for user build Frankie Chang
@ 2020-02-05  9:36 ` Greg Kroah-Hartman
  2020-02-05 15:49   ` Joel Fernandes
  0 siblings, 1 reply; 72+ messages in thread
From: Greg Kroah-Hartman @ 2020-02-05  9:36 UTC (permalink / raw)
  To: Frankie Chang
  Cc: Todd Kjos, wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min.Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Wed, Feb 05, 2020 at 02:52:52PM +0800, Frankie Chang wrote:
> Record start/end timestamp to binder transaction.
> When transaction is completed or transaction is free,
> it would be checked if transaction latency over threshold (2 sec),
> if yes, printing related information for tracing.
> 
> Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
> ---
>  drivers/android/Kconfig           |    8 +++
>  drivers/android/binder.c          |  107 +++++++++++++++++++++++++++++++++++++
>  drivers/android/binder_internal.h |    4 ++
>  3 files changed, 119 insertions(+)
> 
> diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> index 6fdf2ab..7ba80eb 100644
> --- a/drivers/android/Kconfig
> +++ b/drivers/android/Kconfig
> @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
>  	  exhaustively with combinations of various buffer sizes and
>  	  alignments.
>  
> +config BINDER_USER_TRACKING
> +	bool "Android Binder transaction tracking"
> +	help
> +	  Used for track abnormal binder transaction which is over 2 seconds,
> +	  when the transaction is done or be free, this transaction would be
> +	  checked whether it executed overtime.
> +	  If yes, printing out the detail info about it.
> +
>  endif # if ANDROID
>  
>  endmenu
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index e9bc9fc..5a352ee 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -76,6 +76,11 @@
>  #include "binder_internal.h"
>  #include "binder_trace.h"
>  
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +#include <linux/rtc.h>
> +#include <linux/time.h>
> +#endif
> +
>  static HLIST_HEAD(binder_deferred_list);
>  static DEFINE_MUTEX(binder_deferred_lock);
>  
> @@ -591,8 +596,104 @@ struct binder_transaction {
>  	 * during thread teardown
>  	 */
>  	spinlock_t lock;
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +	struct timespec timestamp;
> +	struct timeval tv;
> +#endif
>  };
>  
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +
> +/*
> + * binder_print_delay - Output info of a delay transaction
> + * @t:          pointer to the over-time transaction
> + */
> +static void binder_print_delay(struct binder_transaction *t)
> +{
> +	struct rtc_time tm;
> +	struct timespec *startime;
> +	struct timespec cur, sub_t;
> +
> +	ktime_get_ts(&cur);
> +	startime = &t->timestamp;
> +	sub_t = timespec_sub(cur, *startime);
> +
> +	/* if transaction time is over than 2 sec,
> +	 * show timeout warning log.
> +	 */
> +	if (sub_t.tv_sec < 2)
> +		return;
> +
> +	rtc_time_to_tm(t->tv.tv_sec, &tm);
> +
> +	spin_lock(&t->lock);
> +	pr_info_ratelimited("%d: from %d:%d to %d:%d",
> +			    t->debug_id,
> +			    t->from ? t->from->proc->pid : 0,
> +			    t->from ? t->from->pid : 0,
> +			    t->to_proc ? t->to_proc->pid : 0,
> +			    t->to_thread ? t->to_thread->pid : 0);
> +	spin_unlock(&t->lock);
> +
> +	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> +			    (unsigned int)sub_t.tv_sec,
> +			    (sub_t.tv_nsec / NSEC_PER_MSEC),
> +			    t->code,
> +			    (unsigned long)startime->tv_sec,
> +			    (startime->tv_nsec / NSEC_PER_MSEC),
> +			    (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> +			    tm.tm_hour, tm.tm_min, tm.tm_sec,
> +			    (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> +}

Ick, why not use a tracepoint for this instead?

And what is userspace supposed to do with this if they see it?

thanks,

greg k-h

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v1 1/1] binder: transaction latency tracking for user build
  2020-02-05  9:36 ` Greg Kroah-Hartman
@ 2020-02-05 15:49   ` Joel Fernandes
  2020-02-07  3:10     ` Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Joel Fernandes @ 2020-02-05 15:49 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Todd Kjos, wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min.Liu, linux-mediatek, Frankie Chang, Martijn Coenen,
	Christian Brauner

On Wed, Feb 05, 2020 at 09:36:12AM +0000, Greg Kroah-Hartman wrote:
> On Wed, Feb 05, 2020 at 02:52:52PM +0800, Frankie Chang wrote:
> > Record start/end timestamp to binder transaction.
> > When transaction is completed or transaction is free,
> > it would be checked if transaction latency over threshold (2 sec),
> > if yes, printing related information for tracing.
> > 
> > Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
> > ---
> >  drivers/android/Kconfig           |    8 +++
> >  drivers/android/binder.c          |  107 +++++++++++++++++++++++++++++++++++++
> >  drivers/android/binder_internal.h |    4 ++
> >  3 files changed, 119 insertions(+)
> > 
> > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > index 6fdf2ab..7ba80eb 100644
> > --- a/drivers/android/Kconfig
> > +++ b/drivers/android/Kconfig
> > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> >  	  exhaustively with combinations of various buffer sizes and
> >  	  alignments.
> >  
> > +config BINDER_USER_TRACKING
> > +	bool "Android Binder transaction tracking"
> > +	help
> > +	  Used for track abnormal binder transaction which is over 2 seconds,
> > +	  when the transaction is done or be free, this transaction would be
> > +	  checked whether it executed overtime.
> > +	  If yes, printing out the detail info about it.
> > +
> >  endif # if ANDROID
> >  
> >  endmenu
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index e9bc9fc..5a352ee 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -76,6 +76,11 @@
> >  #include "binder_internal.h"
> >  #include "binder_trace.h"
> >  
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +#include <linux/rtc.h>
> > +#include <linux/time.h>
> > +#endif
> > +
> >  static HLIST_HEAD(binder_deferred_list);
> >  static DEFINE_MUTEX(binder_deferred_lock);
> >  
> > @@ -591,8 +596,104 @@ struct binder_transaction {
> >  	 * during thread teardown
> >  	 */
> >  	spinlock_t lock;
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +	struct timespec timestamp;
> > +	struct timeval tv;
> > +#endif
> >  };
> >  
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +
> > +/*
> > + * binder_print_delay - Output info of a delay transaction
> > + * @t:          pointer to the over-time transaction
> > + */
> > +static void binder_print_delay(struct binder_transaction *t)
> > +{
> > +	struct rtc_time tm;
> > +	struct timespec *startime;
> > +	struct timespec cur, sub_t;
> > +
> > +	ktime_get_ts(&cur);
> > +	startime = &t->timestamp;
> > +	sub_t = timespec_sub(cur, *startime);
> > +
> > +	/* if transaction time is over than 2 sec,
> > +	 * show timeout warning log.
> > +	 */
> > +	if (sub_t.tv_sec < 2)
> > +		return;
> > +
> > +	rtc_time_to_tm(t->tv.tv_sec, &tm);
> > +
> > +	spin_lock(&t->lock);
> > +	pr_info_ratelimited("%d: from %d:%d to %d:%d",
> > +			    t->debug_id,
> > +			    t->from ? t->from->proc->pid : 0,
> > +			    t->from ? t->from->pid : 0,
> > +			    t->to_proc ? t->to_proc->pid : 0,
> > +			    t->to_thread ? t->to_thread->pid : 0);
> > +	spin_unlock(&t->lock);
> > +
> > +	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> > +			    (unsigned int)sub_t.tv_sec,
> > +			    (sub_t.tv_nsec / NSEC_PER_MSEC),
> > +			    t->code,
> > +			    (unsigned long)startime->tv_sec,
> > +			    (startime->tv_nsec / NSEC_PER_MSEC),
> > +			    (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > +			    tm.tm_hour, tm.tm_min, tm.tm_sec,
> > +			    (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > +}
> 
> Ick, why not use a tracepoint for this instead?
> 
> And what is userspace supposed to do with this if they see it?

Or another option is to implement this separately outside of binder.c using
register_trace_* on the existing binder tracepoints, similar to what say the
block tracer or preempt-off tracers do. Call it, say, "binder-latency tracer".

That way all of this tracing code is in-kernel but outside of binder.c.

thanks,

 - Joel


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v1 1/1] binder: transaction latency tracking for user build
  2020-02-05 15:49   ` Joel Fernandes
@ 2020-02-07  3:10     ` Frankie Chang
  2020-02-07  3:17       ` Joel Fernandes
  0 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-02-07  3:10 UTC (permalink / raw)
  To: Joel Fernandes, Greg Kroah-Hartman
  Cc: Todd Kjos, wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min.Liu, linux-mediatek, Martijn Coenen, Christian Brauner

On Wed, 2020-02-05 at 10:49 -0500, Joel Fernandes wrote:
> On Wed, Feb 05, 2020 at 09:36:12AM +0000, Greg Kroah-Hartman wrote:
> > On Wed, Feb 05, 2020 at 02:52:52PM +0800, Frankie Chang wrote:
> > > Record start/end timestamp to binder transaction.
> > > When transaction is completed or transaction is free,
> > > it would be checked if transaction latency over threshold (2 sec),
> > > if yes, printing related information for tracing.
> > > 
> > > Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
> > > ---
> > >  drivers/android/Kconfig           |    8 +++
> > >  drivers/android/binder.c          |  107 +++++++++++++++++++++++++++++++++++++
> > >  drivers/android/binder_internal.h |    4 ++
> > >  3 files changed, 119 insertions(+)
> > > 
> > > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > > index 6fdf2ab..7ba80eb 100644
> > > --- a/drivers/android/Kconfig
> > > +++ b/drivers/android/Kconfig
> > > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> > >  	  exhaustively with combinations of various buffer sizes and
> > >  	  alignments.
> > >  
> > > +config BINDER_USER_TRACKING
> > > +	bool "Android Binder transaction tracking"
> > > +	help
> > > +	  Used for track abnormal binder transaction which is over 2 seconds,
> > > +	  when the transaction is done or be free, this transaction would be
> > > +	  checked whether it executed overtime.
> > > +	  If yes, printing out the detail info about it.
> > > +
> > >  endif # if ANDROID
> > >  
> > >  endmenu
> > > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > > index e9bc9fc..5a352ee 100644
> > > --- a/drivers/android/binder.c
> > > +++ b/drivers/android/binder.c
> > > @@ -76,6 +76,11 @@
> > >  #include "binder_internal.h"
> > >  #include "binder_trace.h"
> > >  
> > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > +#include <linux/rtc.h>
> > > +#include <linux/time.h>
> > > +#endif
> > > +
> > >  static HLIST_HEAD(binder_deferred_list);
> > >  static DEFINE_MUTEX(binder_deferred_lock);
> > >  
> > > @@ -591,8 +596,104 @@ struct binder_transaction {
> > >  	 * during thread teardown
> > >  	 */
> > >  	spinlock_t lock;
> > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > +	struct timespec timestamp;
> > > +	struct timeval tv;
> > > +#endif
> > >  };
> > >  
> > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > +
> > > +/*
> > > + * binder_print_delay - Output info of a delay transaction
> > > + * @t:          pointer to the over-time transaction
> > > + */
> > > +static void binder_print_delay(struct binder_transaction *t)
> > > +{
> > > +	struct rtc_time tm;
> > > +	struct timespec *startime;
> > > +	struct timespec cur, sub_t;
> > > +
> > > +	ktime_get_ts(&cur);
> > > +	startime = &t->timestamp;
> > > +	sub_t = timespec_sub(cur, *startime);
> > > +
> > > +	/* if transaction time is over than 2 sec,
> > > +	 * show timeout warning log.
> > > +	 */
> > > +	if (sub_t.tv_sec < 2)
> > > +		return;
> > > +
> > > +	rtc_time_to_tm(t->tv.tv_sec, &tm);
> > > +
> > > +	spin_lock(&t->lock);
> > > +	pr_info_ratelimited("%d: from %d:%d to %d:%d",
> > > +			    t->debug_id,
> > > +			    t->from ? t->from->proc->pid : 0,
> > > +			    t->from ? t->from->pid : 0,
> > > +			    t->to_proc ? t->to_proc->pid : 0,
> > > +			    t->to_thread ? t->to_thread->pid : 0);
> > > +	spin_unlock(&t->lock);
> > > +
> > > +	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> > > +			    (unsigned int)sub_t.tv_sec,
> > > +			    (sub_t.tv_nsec / NSEC_PER_MSEC),
> > > +			    t->code,
> > > +			    (unsigned long)startime->tv_sec,
> > > +			    (startime->tv_nsec / NSEC_PER_MSEC),
> > > +			    (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > > +			    tm.tm_hour, tm.tm_min, tm.tm_sec,
> > > +			    (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > > +}
> > 
> > Ick, why not use a tracepoint for this instead?
> > 
> > And what is userspace supposed to do with this if they see it?
> 
> Or another option is to implement this separately outside of binder.c using
> register_trace_* on the existing binder tracepoints, similar to what say the
> block tracer or preempt-off tracers do. Call it, say, "binder-latency tracer".
> 
> That way all of this tracing code is in-kernel but outside of binder.c.
> 
> thanks,
> 
>  - Joel
> 
Time limitation of recording is the reason why we don't use tracepoint.
In some situations, the exception is caused by a series of transactions
interaction.
Some abnormal transactions may be pending for a long time ago, they
could not be recorded due to buffer limited.
Therefore, it is difficult to dig out the root causes which caused by
the earlier transactions occurred.

Another point is that we'd just like to record the abnormal
transactions.
But most of transactions are less than 2 seconds, these are not the key
point we need to focus on.

thanks,

Frankie
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v1 1/1] binder: transaction latency tracking for user build
  2020-02-07  3:10     ` Frankie Chang
@ 2020-02-07  3:17       ` Joel Fernandes
  2020-02-07  6:28         ` Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Joel Fernandes @ 2020-02-07  3:17 UTC (permalink / raw)
  To: Frankie Chang
  Cc: Todd Kjos, wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min.Liu, linux-mediatek,
	Martijn Coenen, Christian Brauner

On Fri, Feb 07, 2020 at 11:10:23AM +0800, Frankie Chang wrote:
> On Wed, 2020-02-05 at 10:49 -0500, Joel Fernandes wrote:
> > On Wed, Feb 05, 2020 at 09:36:12AM +0000, Greg Kroah-Hartman wrote:
> > > On Wed, Feb 05, 2020 at 02:52:52PM +0800, Frankie Chang wrote:
> > > > Record start/end timestamp to binder transaction.
> > > > When transaction is completed or transaction is free,
> > > > it would be checked if transaction latency over threshold (2 sec),
> > > > if yes, printing related information for tracing.
> > > > 
> > > > Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
> > > > ---
> > > >  drivers/android/Kconfig           |    8 +++
> > > >  drivers/android/binder.c          |  107 +++++++++++++++++++++++++++++++++++++
> > > >  drivers/android/binder_internal.h |    4 ++
> > > >  3 files changed, 119 insertions(+)
> > > > 
> > > > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > > > index 6fdf2ab..7ba80eb 100644
> > > > --- a/drivers/android/Kconfig
> > > > +++ b/drivers/android/Kconfig
> > > > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> > > >  	  exhaustively with combinations of various buffer sizes and
> > > >  	  alignments.
> > > >  
> > > > +config BINDER_USER_TRACKING
> > > > +	bool "Android Binder transaction tracking"
> > > > +	help
> > > > +	  Used for track abnormal binder transaction which is over 2 seconds,
> > > > +	  when the transaction is done or be free, this transaction would be
> > > > +	  checked whether it executed overtime.
> > > > +	  If yes, printing out the detail info about it.
> > > > +
> > > >  endif # if ANDROID
> > > >  
> > > >  endmenu
> > > > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > > > index e9bc9fc..5a352ee 100644
> > > > --- a/drivers/android/binder.c
> > > > +++ b/drivers/android/binder.c
> > > > @@ -76,6 +76,11 @@
> > > >  #include "binder_internal.h"
> > > >  #include "binder_trace.h"
> > > >  
> > > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > > +#include <linux/rtc.h>
> > > > +#include <linux/time.h>
> > > > +#endif
> > > > +
> > > >  static HLIST_HEAD(binder_deferred_list);
> > > >  static DEFINE_MUTEX(binder_deferred_lock);
> > > >  
> > > > @@ -591,8 +596,104 @@ struct binder_transaction {
> > > >  	 * during thread teardown
> > > >  	 */
> > > >  	spinlock_t lock;
> > > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > > +	struct timespec timestamp;
> > > > +	struct timeval tv;
> > > > +#endif
> > > >  };
> > > >  
> > > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > > +
> > > > +/*
> > > > + * binder_print_delay - Output info of a delay transaction
> > > > + * @t:          pointer to the over-time transaction
> > > > + */
> > > > +static void binder_print_delay(struct binder_transaction *t)
> > > > +{
> > > > +	struct rtc_time tm;
> > > > +	struct timespec *startime;
> > > > +	struct timespec cur, sub_t;
> > > > +
> > > > +	ktime_get_ts(&cur);
> > > > +	startime = &t->timestamp;
> > > > +	sub_t = timespec_sub(cur, *startime);
> > > > +
> > > > +	/* if transaction time is over than 2 sec,
> > > > +	 * show timeout warning log.
> > > > +	 */
> > > > +	if (sub_t.tv_sec < 2)
> > > > +		return;
> > > > +
> > > > +	rtc_time_to_tm(t->tv.tv_sec, &tm);
> > > > +
> > > > +	spin_lock(&t->lock);
> > > > +	pr_info_ratelimited("%d: from %d:%d to %d:%d",
> > > > +			    t->debug_id,
> > > > +			    t->from ? t->from->proc->pid : 0,
> > > > +			    t->from ? t->from->pid : 0,
> > > > +			    t->to_proc ? t->to_proc->pid : 0,
> > > > +			    t->to_thread ? t->to_thread->pid : 0);
> > > > +	spin_unlock(&t->lock);
> > > > +
> > > > +	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> > > > +			    (unsigned int)sub_t.tv_sec,
> > > > +			    (sub_t.tv_nsec / NSEC_PER_MSEC),
> > > > +			    t->code,
> > > > +			    (unsigned long)startime->tv_sec,
> > > > +			    (startime->tv_nsec / NSEC_PER_MSEC),
> > > > +			    (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > > > +			    tm.tm_hour, tm.tm_min, tm.tm_sec,
> > > > +			    (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > > > +}
> > > 
> > > Ick, why not use a tracepoint for this instead?
> > > 
> > > And what is userspace supposed to do with this if they see it?
> > 
> > Or another option is to implement this separately outside of binder.c using
> > register_trace_* on the existing binder tracepoints, similar to what say the
> > block tracer or preempt-off tracers do. Call it, say, "binder-latency tracer".
> > 
> > That way all of this tracing code is in-kernel but outside of binder.c.
> > 
> > thanks,
> > 
> >  - Joel
> > 
> Time limitation of recording is the reason why we don't use tracepoint.
> In some situations, the exception is caused by a series of transactions
> interaction.
> Some abnormal transactions may be pending for a long time ago, they
> could not be recorded due to buffer limited.

register_trace_* does not use the trace buffer so I am not sure what you
mean. I am asking you to use tracepoints, not ftrace events.

thanks,

 - Joel


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v1 1/1] binder: transaction latency tracking for user build
  2020-02-07  3:17       ` Joel Fernandes
@ 2020-02-07  6:28         ` Frankie Chang
  2020-02-07 13:26           ` Joel Fernandes
  0 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-02-07  6:28 UTC (permalink / raw)
  To: Joel Fernandes
  Cc: Todd Kjos, wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min.Liu, linux-mediatek,
	Martijn Coenen, Christian Brauner

On Thu, 2020-02-06 at 22:17 -0500, Joel Fernandes wrote:
> On Fri, Feb 07, 2020 at 11:10:23AM +0800, Frankie Chang wrote:
> > On Wed, 2020-02-05 at 10:49 -0500, Joel Fernandes wrote:
> > > On Wed, Feb 05, 2020 at 09:36:12AM +0000, Greg Kroah-Hartman wrote:
> > > > On Wed, Feb 05, 2020 at 02:52:52PM +0800, Frankie Chang wrote:
> > > > > Record start/end timestamp to binder transaction.
> > > > > When transaction is completed or transaction is free,
> > > > > it would be checked if transaction latency over threshold (2 sec),
> > > > > if yes, printing related information for tracing.
> > > > > 
> > > > > Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
> > > > > ---
> > > > >  drivers/android/Kconfig           |    8 +++
> > > > >  drivers/android/binder.c          |  107 +++++++++++++++++++++++++++++++++++++
> > > > >  drivers/android/binder_internal.h |    4 ++
> > > > >  3 files changed, 119 insertions(+)
> > > > > 
> > > > > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > > > > index 6fdf2ab..7ba80eb 100644
> > > > > --- a/drivers/android/Kconfig
> > > > > +++ b/drivers/android/Kconfig
> > > > > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> > > > >  	  exhaustively with combinations of various buffer sizes and
> > > > >  	  alignments.
> > > > >  
> > > > > +config BINDER_USER_TRACKING
> > > > > +	bool "Android Binder transaction tracking"
> > > > > +	help
> > > > > +	  Used for track abnormal binder transaction which is over 2 seconds,
> > > > > +	  when the transaction is done or be free, this transaction would be
> > > > > +	  checked whether it executed overtime.
> > > > > +	  If yes, printing out the detail info about it.
> > > > > +
> > > > >  endif # if ANDROID
> > > > >  
> > > > >  endmenu
> > > > > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > > > > index e9bc9fc..5a352ee 100644
> > > > > --- a/drivers/android/binder.c
> > > > > +++ b/drivers/android/binder.c
> > > > > @@ -76,6 +76,11 @@
> > > > >  #include "binder_internal.h"
> > > > >  #include "binder_trace.h"
> > > > >  
> > > > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > > > +#include <linux/rtc.h>
> > > > > +#include <linux/time.h>
> > > > > +#endif
> > > > > +
> > > > >  static HLIST_HEAD(binder_deferred_list);
> > > > >  static DEFINE_MUTEX(binder_deferred_lock);
> > > > >  
> > > > > @@ -591,8 +596,104 @@ struct binder_transaction {
> > > > >  	 * during thread teardown
> > > > >  	 */
> > > > >  	spinlock_t lock;
> > > > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > > > +	struct timespec timestamp;
> > > > > +	struct timeval tv;
> > > > > +#endif
> > > > >  };
> > > > >  
> > > > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > > > +
> > > > > +/*
> > > > > + * binder_print_delay - Output info of a delay transaction
> > > > > + * @t:          pointer to the over-time transaction
> > > > > + */
> > > > > +static void binder_print_delay(struct binder_transaction *t)
> > > > > +{
> > > > > +	struct rtc_time tm;
> > > > > +	struct timespec *startime;
> > > > > +	struct timespec cur, sub_t;
> > > > > +
> > > > > +	ktime_get_ts(&cur);
> > > > > +	startime = &t->timestamp;
> > > > > +	sub_t = timespec_sub(cur, *startime);
> > > > > +
> > > > > +	/* if transaction time is over than 2 sec,
> > > > > +	 * show timeout warning log.
> > > > > +	 */
> > > > > +	if (sub_t.tv_sec < 2)
> > > > > +		return;
> > > > > +
> > > > > +	rtc_time_to_tm(t->tv.tv_sec, &tm);
> > > > > +
> > > > > +	spin_lock(&t->lock);
> > > > > +	pr_info_ratelimited("%d: from %d:%d to %d:%d",
> > > > > +			    t->debug_id,
> > > > > +			    t->from ? t->from->proc->pid : 0,
> > > > > +			    t->from ? t->from->pid : 0,
> > > > > +			    t->to_proc ? t->to_proc->pid : 0,
> > > > > +			    t->to_thread ? t->to_thread->pid : 0);
> > > > > +	spin_unlock(&t->lock);
> > > > > +
> > > > > +	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> > > > > +			    (unsigned int)sub_t.tv_sec,
> > > > > +			    (sub_t.tv_nsec / NSEC_PER_MSEC),
> > > > > +			    t->code,
> > > > > +			    (unsigned long)startime->tv_sec,
> > > > > +			    (startime->tv_nsec / NSEC_PER_MSEC),
> > > > > +			    (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > > > > +			    tm.tm_hour, tm.tm_min, tm.tm_sec,
> > > > > +			    (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > > > > +}
> > > > 
> > > > Ick, why not use a tracepoint for this instead?
> > > > 
> > > > And what is userspace supposed to do with this if they see it?
> > > 
> > > Or another option is to implement this separately outside of binder.c using
> > > register_trace_* on the existing binder tracepoints, similar to what say the
> > > block tracer or preempt-off tracers do. Call it, say, "binder-latency tracer".
> > > 
> > > That way all of this tracing code is in-kernel but outside of binder.c.
> > > 
> > > thanks,
> > > 
> > >  - Joel
> > > 
> > Time limitation of recording is the reason why we don't use tracepoint.
> > In some situations, the exception is caused by a series of transactions
> > interaction.
> > Some abnormal transactions may be pending for a long time ago, they
> > could not be recorded due to buffer limited.
> 
> register_trace_* does not use the trace buffer so I am not sure what you
> mean. I am asking you to use tracepoints, not ftrace events.
> 
> thanks,
> 
>  - Joel
> 
The existing binder tracepoint may not be precise enough because there
is no proper tracepoint which can represent the real finished time of
transaction.

The reason why we don't put the code outside binder.c is that structure
of binder_transaction didn't put in header file.
If it could be moved to binder_internal.h, then we can add
"binder-latency tracer" as you mentioned earlier.
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v1 1/1] binder: transaction latency tracking for user build
  2020-02-07  6:28         ` Frankie Chang
@ 2020-02-07 13:26           ` Joel Fernandes
  2020-04-13  6:24             ` Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Joel Fernandes @ 2020-02-07 13:26 UTC (permalink / raw)
  To: Frankie Chang
  Cc: Todd Kjos, wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min.Liu, linux-mediatek,
	Martijn Coenen, Christian Brauner

On Fri, Feb 07, 2020 at 02:28:59PM +0800, Frankie Chang wrote:
> On Thu, 2020-02-06 at 22:17 -0500, Joel Fernandes wrote:
> > On Fri, Feb 07, 2020 at 11:10:23AM +0800, Frankie Chang wrote:
> > > On Wed, 2020-02-05 at 10:49 -0500, Joel Fernandes wrote:
> > > > On Wed, Feb 05, 2020 at 09:36:12AM +0000, Greg Kroah-Hartman wrote:
> > > > > On Wed, Feb 05, 2020 at 02:52:52PM +0800, Frankie Chang wrote:
> > > > > > Record start/end timestamp to binder transaction.
> > > > > > When transaction is completed or transaction is free,
> > > > > > it would be checked if transaction latency over threshold (2 sec),
> > > > > > if yes, printing related information for tracing.
> > > > > > 
> > > > > > Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
> > > > > > ---
> > > > > >  drivers/android/Kconfig           |    8 +++
> > > > > >  drivers/android/binder.c          |  107 +++++++++++++++++++++++++++++++++++++
> > > > > >  drivers/android/binder_internal.h |    4 ++
> > > > > >  3 files changed, 119 insertions(+)
> > > > > > 
> > > > > > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > > > > > index 6fdf2ab..7ba80eb 100644
> > > > > > --- a/drivers/android/Kconfig
> > > > > > +++ b/drivers/android/Kconfig
> > > > > > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> > > > > >  	  exhaustively with combinations of various buffer sizes and
> > > > > >  	  alignments.
> > > > > >  
> > > > > > +config BINDER_USER_TRACKING
> > > > > > +	bool "Android Binder transaction tracking"
> > > > > > +	help
> > > > > > +	  Used for track abnormal binder transaction which is over 2 seconds,
> > > > > > +	  when the transaction is done or be free, this transaction would be
> > > > > > +	  checked whether it executed overtime.
> > > > > > +	  If yes, printing out the detail info about it.
> > > > > > +
> > > > > >  endif # if ANDROID
> > > > > >  
> > > > > >  endmenu
> > > > > > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > > > > > index e9bc9fc..5a352ee 100644
> > > > > > --- a/drivers/android/binder.c
> > > > > > +++ b/drivers/android/binder.c
> > > > > > @@ -76,6 +76,11 @@
> > > > > >  #include "binder_internal.h"
> > > > > >  #include "binder_trace.h"
> > > > > >  
> > > > > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > > > > +#include <linux/rtc.h>
> > > > > > +#include <linux/time.h>
> > > > > > +#endif
> > > > > > +
> > > > > >  static HLIST_HEAD(binder_deferred_list);
> > > > > >  static DEFINE_MUTEX(binder_deferred_lock);
> > > > > >  
> > > > > > @@ -591,8 +596,104 @@ struct binder_transaction {
> > > > > >  	 * during thread teardown
> > > > > >  	 */
> > > > > >  	spinlock_t lock;
> > > > > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > > > > +	struct timespec timestamp;
> > > > > > +	struct timeval tv;
> > > > > > +#endif
> > > > > >  };
> > > > > >  
> > > > > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > > > > +
> > > > > > +/*
> > > > > > + * binder_print_delay - Output info of a delay transaction
> > > > > > + * @t:          pointer to the over-time transaction
> > > > > > + */
> > > > > > +static void binder_print_delay(struct binder_transaction *t)
> > > > > > +{
> > > > > > +	struct rtc_time tm;
> > > > > > +	struct timespec *startime;
> > > > > > +	struct timespec cur, sub_t;
> > > > > > +
> > > > > > +	ktime_get_ts(&cur);
> > > > > > +	startime = &t->timestamp;
> > > > > > +	sub_t = timespec_sub(cur, *startime);
> > > > > > +
> > > > > > +	/* if transaction time is over than 2 sec,
> > > > > > +	 * show timeout warning log.
> > > > > > +	 */
> > > > > > +	if (sub_t.tv_sec < 2)
> > > > > > +		return;
> > > > > > +
> > > > > > +	rtc_time_to_tm(t->tv.tv_sec, &tm);
> > > > > > +
> > > > > > +	spin_lock(&t->lock);
> > > > > > +	pr_info_ratelimited("%d: from %d:%d to %d:%d",
> > > > > > +			    t->debug_id,
> > > > > > +			    t->from ? t->from->proc->pid : 0,
> > > > > > +			    t->from ? t->from->pid : 0,
> > > > > > +			    t->to_proc ? t->to_proc->pid : 0,
> > > > > > +			    t->to_thread ? t->to_thread->pid : 0);
> > > > > > +	spin_unlock(&t->lock);
> > > > > > +
> > > > > > +	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> > > > > > +			    (unsigned int)sub_t.tv_sec,
> > > > > > +			    (sub_t.tv_nsec / NSEC_PER_MSEC),
> > > > > > +			    t->code,
> > > > > > +			    (unsigned long)startime->tv_sec,
> > > > > > +			    (startime->tv_nsec / NSEC_PER_MSEC),
> > > > > > +			    (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > > > > > +			    tm.tm_hour, tm.tm_min, tm.tm_sec,
> > > > > > +			    (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > > > > > +}
> > > > > 
> > > > > Ick, why not use a tracepoint for this instead?
> > > > > 
> > > > > And what is userspace supposed to do with this if they see it?
> > > > 
> > > > Or another option is to implement this separately outside of binder.c using
> > > > register_trace_* on the existing binder tracepoints, similar to what say the
> > > > block tracer or preempt-off tracers do. Call it, say, "binder-latency tracer".
> > > > 
> > > > That way all of this tracing code is in-kernel but outside of binder.c.
> > > > 
> > > > thanks,
> > > > 
> > > >  - Joel
> > > > 
> > > Time limitation of recording is the reason why we don't use tracepoint.
> > > In some situations, the exception is caused by a series of transactions
> > > interaction.
> > > Some abnormal transactions may be pending for a long time ago, they
> > > could not be recorded due to buffer limited.
> > 
> > register_trace_* does not use the trace buffer so I am not sure what you
> > mean. I am asking you to use tracepoints, not ftrace events.
> > 
> > thanks,
> > 
> >  - Joel
> > 
> The existing binder tracepoint may not be precise enough because there
> is no proper tracepoint which can represent the real finished time of
> transaction.

May be you can add such TP then?

> The reason why we don't put the code outside binder.c is that structure
> of binder_transaction didn't put in header file.
> If it could be moved to binder_internal.h, then we can add
> "binder-latency tracer" as you mentioned earlier.

That should be doable.

The reason I don't like custom tracing logic in core files as your patch is
doing, is that it is doubtful if a lot of people would use it to warrant
adding into a core file. In this case, probably a separate tracer (outside of
binder.c) is a better option so as to not pollute the core files.

thanks,

 - Joel


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v1 1/1] binder: transaction latency tracking for user build
  2020-02-07 13:26           ` Joel Fernandes
@ 2020-04-13  6:24             ` Frankie Chang
  2020-04-15  5:37               ` [PATCH v2] " Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-04-13  6:24 UTC (permalink / raw)
  To: Joel Fernandes
  Cc: Todd Kjos, wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min.Liu, linux-mediatek,
	Martijn Coenen, Christian Brauner

On Fri, 2020-02-07 at 08:26 -0500, Joel Fernandes wrote:
> On Fri, Feb 07, 2020 at 02:28:59PM +0800, Frankie Chang wrote:
> > On Thu, 2020-02-06 at 22:17 -0500, Joel Fernandes wrote:
> > > On Fri, Feb 07, 2020 at 11:10:23AM +0800, Frankie Chang wrote:
> > > > On Wed, 2020-02-05 at 10:49 -0500, Joel Fernandes wrote:
> > > > > On Wed, Feb 05, 2020 at 09:36:12AM +0000, Greg Kroah-Hartman wrote:
> > > > > > On Wed, Feb 05, 2020 at 02:52:52PM +0800, Frankie Chang wrote:
> > > > > > > Record start/end timestamp to binder transaction.
> > > > > > > When transaction is completed or transaction is free,
> > > > > > > it would be checked if transaction latency over threshold (2 sec),
> > > > > > > if yes, printing related information for tracing.
> > > > > > > 
> > > > > > > Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
> > > > > > > ---
> > > > > > >  drivers/android/Kconfig           |    8 +++
> > > > > > >  drivers/android/binder.c          |  107 +++++++++++++++++++++++++++++++++++++
> > > > > > >  drivers/android/binder_internal.h |    4 ++
> > > > > > >  3 files changed, 119 insertions(+)
> > > > > > > 
> > > > > > > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > > > > > > index 6fdf2ab..7ba80eb 100644
> > > > > > > --- a/drivers/android/Kconfig
> > > > > > > +++ b/drivers/android/Kconfig
> > > > > > > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> > > > > > >  	  exhaustively with combinations of various buffer sizes and
> > > > > > >  	  alignments.
> > > > > > >  
> > > > > > > +config BINDER_USER_TRACKING
> > > > > > > +	bool "Android Binder transaction tracking"
> > > > > > > +	help
> > > > > > > +	  Used for track abnormal binder transaction which is over 2 seconds,
> > > > > > > +	  when the transaction is done or be free, this transaction would be
> > > > > > > +	  checked whether it executed overtime.
> > > > > > > +	  If yes, printing out the detail info about it.
> > > > > > > +
> > > > > > >  endif # if ANDROID
> > > > > > >  
> > > > > > >  endmenu
> > > > > > > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > > > > > > index e9bc9fc..5a352ee 100644
> > > > > > > --- a/drivers/android/binder.c
> > > > > > > +++ b/drivers/android/binder.c
> > > > > > > @@ -76,6 +76,11 @@
> > > > > > >  #include "binder_internal.h"
> > > > > > >  #include "binder_trace.h"
> > > > > > >  
> > > > > > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > > > > > +#include <linux/rtc.h>
> > > > > > > +#include <linux/time.h>
> > > > > > > +#endif
> > > > > > > +
> > > > > > >  static HLIST_HEAD(binder_deferred_list);
> > > > > > >  static DEFINE_MUTEX(binder_deferred_lock);
> > > > > > >  
> > > > > > > @@ -591,8 +596,104 @@ struct binder_transaction {
> > > > > > >  	 * during thread teardown
> > > > > > >  	 */
> > > > > > >  	spinlock_t lock;
> > > > > > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > > > > > +	struct timespec timestamp;
> > > > > > > +	struct timeval tv;
> > > > > > > +#endif
> > > > > > >  };
> > > > > > >  
> > > > > > > +#ifdef CONFIG_BINDER_USER_TRACKING
> > > > > > > +
> > > > > > > +/*
> > > > > > > + * binder_print_delay - Output info of a delay transaction
> > > > > > > + * @t:          pointer to the over-time transaction
> > > > > > > + */
> > > > > > > +static void binder_print_delay(struct binder_transaction *t)
> > > > > > > +{
> > > > > > > +	struct rtc_time tm;
> > > > > > > +	struct timespec *startime;
> > > > > > > +	struct timespec cur, sub_t;
> > > > > > > +
> > > > > > > +	ktime_get_ts(&cur);
> > > > > > > +	startime = &t->timestamp;
> > > > > > > +	sub_t = timespec_sub(cur, *startime);
> > > > > > > +
> > > > > > > +	/* if transaction time is over than 2 sec,
> > > > > > > +	 * show timeout warning log.
> > > > > > > +	 */
> > > > > > > +	if (sub_t.tv_sec < 2)
> > > > > > > +		return;
> > > > > > > +
> > > > > > > +	rtc_time_to_tm(t->tv.tv_sec, &tm);
> > > > > > > +
> > > > > > > +	spin_lock(&t->lock);
> > > > > > > +	pr_info_ratelimited("%d: from %d:%d to %d:%d",
> > > > > > > +			    t->debug_id,
> > > > > > > +			    t->from ? t->from->proc->pid : 0,
> > > > > > > +			    t->from ? t->from->pid : 0,
> > > > > > > +			    t->to_proc ? t->to_proc->pid : 0,
> > > > > > > +			    t->to_thread ? t->to_thread->pid : 0);
> > > > > > > +	spin_unlock(&t->lock);
> > > > > > > +
> > > > > > > +	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> > > > > > > +			    (unsigned int)sub_t.tv_sec,
> > > > > > > +			    (sub_t.tv_nsec / NSEC_PER_MSEC),
> > > > > > > +			    t->code,
> > > > > > > +			    (unsigned long)startime->tv_sec,
> > > > > > > +			    (startime->tv_nsec / NSEC_PER_MSEC),
> > > > > > > +			    (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > > > > > > +			    tm.tm_hour, tm.tm_min, tm.tm_sec,
> > > > > > > +			    (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > > > > > > +}
> > > > > > 
> > > > > > Ick, why not use a tracepoint for this instead?
> > > > > > 
> > > > > > And what is userspace supposed to do with this if they see it?
> > > > > 
> > > > > Or another option is to implement this separately outside of binder.c using
> > > > > register_trace_* on the existing binder tracepoints, similar to what say the
> > > > > block tracer or preempt-off tracers do. Call it, say, "binder-latency tracer".
> > > > > 
> > > > > That way all of this tracing code is in-kernel but outside of binder.c.
> > > > > 
> > > > > thanks,
> > > > > 
> > > > >  - Joel
> > > > > 
> > > > Time limitation of recording is the reason why we don't use tracepoint.
> > > > In some situations, the exception is caused by a series of transactions
> > > > interaction.
> > > > Some abnormal transactions may be pending for a long time ago, they
> > > > could not be recorded due to buffer limited.
> > > 
> > > register_trace_* does not use the trace buffer so I am not sure what you
> > > mean. I am asking you to use tracepoints, not ftrace events.
> > > 
> > > thanks,
> > > 
> > >  - Joel
> > > 
> > The existing binder tracepoint may not be precise enough because there
> > is no proper tracepoint which can represent the real finished time of
> > transaction.
> 
> May be you can add such TP then?
> 
Yes, we will add TP at the real finished time of transaction.

> > The reason why we don't put the code outside binder.c is that structure
> > of binder_transaction didn't put in header file.
> > If it could be moved to binder_internal.h, then we can add
> > "binder-latency tracer" as you mentioned earlier.
> 
> That should be doable.
> 
> The reason I don't like custom tracing logic in core files as your patch is
> doing, is that it is doubtful if a lot of people would use it to warrant
> adding into a core file. In this case, probably a separate tracer (outside of
> binder.c) is a better option so as to not pollute the core files.
> 
> thanks,
> 
>  - Joel
> 
Thanks for your advice, sincerely.

We will move tracing logic out of core files and implement a separate
latency tracer. And also move some structures needed by tracer module
from core file to header file (binder_internal.h) in next version.

Many thanks,

 - Frankie

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v2] binder: transaction latency tracking for user build
  2020-04-13  6:24             ` Frankie Chang
@ 2020-04-15  5:37               ` Frankie Chang
  2020-04-15  5:37                 ` [PATCH v2 1/1] " Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-04-15  5:37 UTC (permalink / raw)
  To: Joel Fernandes, Greg Kroah-Hartman
  Cc: Todd Kjos, wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Martijn Coenen, Christian Brauner


Frankie Chang (1):
  binder: transaction latency tracking for user build

 drivers/android/Kconfig                 |    8 ++
 drivers/android/Makefile                |    1 +
 drivers/android/binder.c                |  237 ++++---------------------------
 drivers/android/binder_internal.h       |  227 +++++++++++++++++++++++++++++
 drivers/android/binder_latency_tracer.c |  100 +++++++++++++
 drivers/android/binder_trace.h          |   36 +++++
 6 files changed, 400 insertions(+), 209 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v2 1/1] binder: transaction latency tracking for user build
  2020-04-15  5:37               ` [PATCH v2] " Frankie Chang
@ 2020-04-15  5:37                 ` Frankie Chang
  2020-04-15 22:25                   ` Todd Kjos
  2020-04-30  8:13                   ` Frankie Chang
  0 siblings, 2 replies; 72+ messages in thread
From: Frankie Chang @ 2020-04-15  5:37 UTC (permalink / raw)
  To: Joel Fernandes, Greg Kroah-Hartman
  Cc: Todd Kjos, wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Frankie Chang, Martijn Coenen,
	Christian Brauner

Record start/end timestamp to binder transaction.
When transaction is completed or transaction is free,
it would be checked if transaction latency over threshold (2 sec),
if yes, printing related information for tracing.

/* Implement details */
- Add tracepoint/trace at free transaction.
  Since the original trace_binder_transaction_reveived cannot
  precisely present the real finished time of transaction, adding a
  trace_binder_free_transaction at the point of free transaction
  may be more close to it.

- Add latency tracer module to monitor slow transaction.
  The trace_binder_free_transaction would not be enabled
  by default. Monitoring which transaction is too slow to
  cause some of exceptions is important. So we hook the
  tracepoint to call the monitor function.

- Move some struct from core file to header file.
  Need some struct defined in core file in latency trace module
  In addition, moving structs to header file makes module more
  extendable.

Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/Kconfig                 |    8 ++
 drivers/android/Makefile                |    1 +
 drivers/android/binder.c                |  237 ++++---------------------------
 drivers/android/binder_internal.h       |  227 +++++++++++++++++++++++++++++
 drivers/android/binder_latency_tracer.c |  100 +++++++++++++
 drivers/android/binder_trace.h          |   36 +++++
 6 files changed, 400 insertions(+), 209 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 6fdf2ab..7ba80eb 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
 	  exhaustively with combinations of various buffer sizes and
 	  alignments.
 
+config BINDER_USER_TRACKING
+	bool "Android Binder transaction tracking"
+	help
+	  Used for track abnormal binder transaction which is over 2 seconds,
+	  when the transaction is done or be free, this transaction would be
+	  checked whether it executed overtime.
+	  If yes, printing out the detail info about it.
+
 endif # if ANDROID
 
 endmenu
diff --git a/drivers/android/Makefile b/drivers/android/Makefile
index c9d3d0c9..552e8ac 100644
--- a/drivers/android/Makefile
+++ b/drivers/android/Makefile
@@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
 obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
 obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
 obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
+obj-$(CONFIG_BINDER_USER_TRACKING)	+= binder_latency_tracer.o
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index a6b2082..380a68b 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -160,24 +160,6 @@ static int binder_set_stop_on_user_error(const char *val,
 #define to_binder_fd_array_object(hdr) \
 	container_of(hdr, struct binder_fd_array_object, hdr)
 
-enum binder_stat_types {
-	BINDER_STAT_PROC,
-	BINDER_STAT_THREAD,
-	BINDER_STAT_NODE,
-	BINDER_STAT_REF,
-	BINDER_STAT_DEATH,
-	BINDER_STAT_TRANSACTION,
-	BINDER_STAT_TRANSACTION_COMPLETE,
-	BINDER_STAT_COUNT
-};
-
-struct binder_stats {
-	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
-	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
-	atomic_t obj_created[BINDER_STAT_COUNT];
-	atomic_t obj_deleted[BINDER_STAT_COUNT];
-};
-
 static struct binder_stats binder_stats;
 
 static inline void binder_stats_deleted(enum binder_stat_types type)
@@ -214,32 +196,6 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
 }
 
 /**
- * struct binder_work - work enqueued on a worklist
- * @entry:             node enqueued on list
- * @type:              type of work to be performed
- *
- * There are separate work lists for proc, thread, and node (async).
- */
-struct binder_work {
-	struct list_head entry;
-
-	enum {
-		BINDER_WORK_TRANSACTION = 1,
-		BINDER_WORK_TRANSACTION_COMPLETE,
-		BINDER_WORK_RETURN_ERROR,
-		BINDER_WORK_NODE,
-		BINDER_WORK_DEAD_BINDER,
-		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
-		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
-	} type;
-};
-
-struct binder_error {
-	struct binder_work work;
-	uint32_t cmd;
-};
-
-/**
  * struct binder_node - binder node bookkeeping
  * @debug_id:             unique ID for debugging
  *                        (invariant after initialized)
@@ -402,89 +358,6 @@ enum binder_deferred_state {
 	BINDER_DEFERRED_RELEASE      = 0x02,
 };
 
-/**
- * struct binder_proc - binder process bookkeeping
- * @proc_node:            element for binder_procs list
- * @threads:              rbtree of binder_threads in this proc
- *                        (protected by @inner_lock)
- * @nodes:                rbtree of binder nodes associated with
- *                        this proc ordered by node->ptr
- *                        (protected by @inner_lock)
- * @refs_by_desc:         rbtree of refs ordered by ref->desc
- *                        (protected by @outer_lock)
- * @refs_by_node:         rbtree of refs ordered by ref->node
- *                        (protected by @outer_lock)
- * @waiting_threads:      threads currently waiting for proc work
- *                        (protected by @inner_lock)
- * @pid                   PID of group_leader of process
- *                        (invariant after initialized)
- * @tsk                   task_struct for group_leader of process
- *                        (invariant after initialized)
- * @deferred_work_node:   element for binder_deferred_list
- *                        (protected by binder_deferred_lock)
- * @deferred_work:        bitmap of deferred work to perform
- *                        (protected by binder_deferred_lock)
- * @is_dead:              process is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @inner_lock)
- * @todo:                 list of work for this process
- *                        (protected by @inner_lock)
- * @stats:                per-process binder statistics
- *                        (atomics, no lock needed)
- * @delivered_death:      list of delivered death notification
- *                        (protected by @inner_lock)
- * @max_threads:          cap on number of binder threads
- *                        (protected by @inner_lock)
- * @requested_threads:    number of binder threads requested but not
- *                        yet started. In current implementation, can
- *                        only be 0 or 1.
- *                        (protected by @inner_lock)
- * @requested_threads_started: number binder threads started
- *                        (protected by @inner_lock)
- * @tmp_ref:              temporary reference to indicate proc is in use
- *                        (protected by @inner_lock)
- * @default_priority:     default scheduler priority
- *                        (invariant after initialized)
- * @debugfs_entry:        debugfs node
- * @alloc:                binder allocator bookkeeping
- * @context:              binder_context for this proc
- *                        (invariant after initialized)
- * @inner_lock:           can nest under outer_lock and/or node lock
- * @outer_lock:           no nesting under innor or node lock
- *                        Lock order: 1) outer, 2) node, 3) inner
- * @binderfs_entry:       process-specific binderfs log file
- *
- * Bookkeeping structure for binder processes
- */
-struct binder_proc {
-	struct hlist_node proc_node;
-	struct rb_root threads;
-	struct rb_root nodes;
-	struct rb_root refs_by_desc;
-	struct rb_root refs_by_node;
-	struct list_head waiting_threads;
-	int pid;
-	struct task_struct *tsk;
-	struct hlist_node deferred_work_node;
-	int deferred_work;
-	bool is_dead;
-
-	struct list_head todo;
-	struct binder_stats stats;
-	struct list_head delivered_death;
-	int max_threads;
-	int requested_threads;
-	int requested_threads_started;
-	int tmp_ref;
-	long default_priority;
-	struct dentry *debugfs_entry;
-	struct binder_alloc alloc;
-	struct binder_context *context;
-	spinlock_t inner_lock;
-	spinlock_t outer_lock;
-	struct dentry *binderfs_entry;
-};
-
 enum {
 	BINDER_LOOPER_STATE_REGISTERED  = 0x01,
 	BINDER_LOOPER_STATE_ENTERED     = 0x02,
@@ -495,60 +368,6 @@ enum {
 };
 
 /**
- * struct binder_thread - binder thread bookkeeping
- * @proc:                 binder process for this thread
- *                        (invariant after initialization)
- * @rb_node:              element for proc->threads rbtree
- *                        (protected by @proc->inner_lock)
- * @waiting_thread_node:  element for @proc->waiting_threads list
- *                        (protected by @proc->inner_lock)
- * @pid:                  PID for this thread
- *                        (invariant after initialization)
- * @looper:               bitmap of looping state
- *                        (only accessed by this thread)
- * @looper_needs_return:  looping thread needs to exit driver
- *                        (no lock needed)
- * @transaction_stack:    stack of in-progress transactions for this thread
- *                        (protected by @proc->inner_lock)
- * @todo:                 list of work to do for this thread
- *                        (protected by @proc->inner_lock)
- * @process_todo:         whether work in @todo should be processed
- *                        (protected by @proc->inner_lock)
- * @return_error:         transaction errors reported by this thread
- *                        (only accessed by this thread)
- * @reply_error:          transaction errors reported by target thread
- *                        (protected by @proc->inner_lock)
- * @wait:                 wait queue for thread work
- * @stats:                per-thread statistics
- *                        (atomics, no lock needed)
- * @tmp_ref:              temporary reference to indicate thread is in use
- *                        (atomic since @proc->inner_lock cannot
- *                        always be acquired)
- * @is_dead:              thread is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder threads.
- */
-struct binder_thread {
-	struct binder_proc *proc;
-	struct rb_node rb_node;
-	struct list_head waiting_thread_node;
-	int pid;
-	int looper;              /* only modified by this thread */
-	bool looper_need_return; /* can be written by other thread */
-	struct binder_transaction *transaction_stack;
-	struct list_head todo;
-	bool process_todo;
-	struct binder_error return_error;
-	struct binder_error reply_error;
-	wait_queue_head_t wait;
-	struct binder_stats stats;
-	atomic_t tmp_ref;
-	bool is_dead;
-};
-
-/**
  * struct binder_txn_fd_fixup - transaction fd fixup list element
  * @fixup_entry:          list entry
  * @file:                 struct file to be associated with new fd
@@ -565,34 +384,6 @@ struct binder_txn_fd_fixup {
 	size_t offset;
 };
 
-struct binder_transaction {
-	int debug_id;
-	struct binder_work work;
-	struct binder_thread *from;
-	struct binder_transaction *from_parent;
-	struct binder_proc *to_proc;
-	struct binder_thread *to_thread;
-	struct binder_transaction *to_parent;
-	unsigned need_reply:1;
-	/* unsigned is_dead:1; */	/* not used at the moment */
-
-	struct binder_buffer *buffer;
-	unsigned int	code;
-	unsigned int	flags;
-	long	priority;
-	long	saved_priority;
-	kuid_t	sender_euid;
-	struct list_head fd_fixups;
-	binder_uintptr_t security_ctx;
-	/**
-	 * @lock:  protects @from, @to_proc, and @to_thread
-	 *
-	 * @from, @to_proc, and @to_thread can be set to NULL
-	 * during thread teardown
-	 */
-	spinlock_t lock;
-};
-
 /**
  * struct binder_object - union of flat binder object types
  * @hdr:   generic object header
@@ -613,6 +404,26 @@ struct binder_object {
 	};
 };
 
+static void (*__binder_update_info_cb)(struct binder_transaction *t,
+					struct binder_transaction_log_entry *e);
+
+void set_binder_update_info_cb(void (*fn)(struct binder_transaction *t,
+					struct binder_transaction_log_entry *e))
+{
+	__binder_update_info_cb = fn;
+}
+EXPORT_SYMBOL_GPL(set_binder_update_info_cb);
+
+static void (*__print_transaction_ext_cb)(struct seq_file *m,
+					struct binder_transaction *t);
+
+void set_print_transaction_ext_cb(void (*fn)(struct seq_file *m,
+					struct binder_transaction *t))
+{
+	__print_transaction_ext_cb = fn;
+}
+EXPORT_SYMBOL_GPL(set_print_transaction_ext_cb);
+
 /**
  * binder_proc_lock() - Acquire outer lock for given binder_proc
  * @proc:         struct binder_proc to acquire
@@ -1927,6 +1738,7 @@ static void binder_free_transaction(struct binder_transaction *t)
 	 * If the transaction has no target_proc, then
 	 * t->buffer->transaction has already been cleared.
 	 */
+	trace_binder_free_transaction(t);
 	binder_free_txn_fixups(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
@@ -2874,6 +2686,7 @@ static void binder_transaction(struct binder_proc *proc,
 	e->offsets_size = tr->offsets_size;
 	strscpy(e->context_name, proc->context->name, BINDERFS_MAX_NAME);
 
+
 	if (reply) {
 		binder_inner_proc_lock(proc);
 		in_reply_to = thread->transaction_stack;
@@ -3060,6 +2873,9 @@ static void binder_transaction(struct binder_proc *proc,
 		return_error_line = __LINE__;
 		goto err_alloc_t_failed;
 	}
+
+	if (__binder_update_info_cb)
+		__binder_update_info_cb(t, e);
 	INIT_LIST_HEAD(&t->fd_fixups);
 	binder_stats_created(BINDER_STAT_TRANSACTION);
 	spin_lock_init(&t->lock);
@@ -3498,6 +3314,7 @@ static void binder_transaction(struct binder_proc *proc,
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 err_alloc_tcomplete_failed:
+	trace_binder_free_transaction(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
 err_alloc_t_failed:
@@ -5547,6 +5364,8 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
 		   t->to_thread ? t->to_thread->pid : 0,
 		   t->code, t->flags, t->priority, t->need_reply);
 	spin_unlock(&t->lock);
+	if (__print_transaction_ext_cb)
+		__print_transaction_ext_cb(m, t);
 
 	if (proc != to_proc) {
 		/*
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index ae99109..86b4960 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -12,6 +12,11 @@
 #include <linux/types.h>
 #include <linux/uidgid.h>
 
+#ifdef CONFIG_BINDER_USER_TRACKING
+#include <linux/rtc.h>
+#include <linux/time.h>
+#endif
+
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
 	struct mutex context_mgr_node_lock;
@@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
 	uint32_t return_error;
 	uint32_t return_error_param;
 	char context_name[BINDERFS_MAX_NAME + 1];
+#ifdef CONFIG_BINDER_USER_TRACKING
+	struct timespec timestamp;
+	struct timeval tv;
+#endif
 };
 
 struct binder_transaction_log {
@@ -139,6 +148,224 @@ struct binder_transaction_log {
 	struct binder_transaction_log_entry entry[32];
 };
 
+enum binder_stat_types {
+	BINDER_STAT_PROC,
+	BINDER_STAT_THREAD,
+	BINDER_STAT_NODE,
+	BINDER_STAT_REF,
+	BINDER_STAT_DEATH,
+	BINDER_STAT_TRANSACTION,
+	BINDER_STAT_TRANSACTION_COMPLETE,
+	BINDER_STAT_COUNT
+};
+
+struct binder_stats {
+	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
+	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
+	atomic_t obj_created[BINDER_STAT_COUNT];
+	atomic_t obj_deleted[BINDER_STAT_COUNT];
+};
+
+/**
+ * struct binder_work - work enqueued on a worklist
+ * @entry:             node enqueued on list
+ * @type:              type of work to be performed
+ *
+ * There are separate work lists for proc, thread, and node (async).
+ */
+struct binder_work {
+	struct list_head entry;
+
+	enum {
+		BINDER_WORK_TRANSACTION = 1,
+		BINDER_WORK_TRANSACTION_COMPLETE,
+		BINDER_WORK_RETURN_ERROR,
+		BINDER_WORK_NODE,
+		BINDER_WORK_DEAD_BINDER,
+		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
+		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
+	} type;
+};
+
+struct binder_error {
+	struct binder_work work;
+	uint32_t cmd;
+};
+
+/**
+ * struct binder_proc - binder process bookkeeping
+ * @proc_node:            element for binder_procs list
+ * @threads:              rbtree of binder_threads in this proc
+ *                        (protected by @inner_lock)
+ * @nodes:                rbtree of binder nodes associated with
+ *                        this proc ordered by node->ptr
+ *                        (protected by @inner_lock)
+ * @refs_by_desc:         rbtree of refs ordered by ref->desc
+ *                        (protected by @outer_lock)
+ * @refs_by_node:         rbtree of refs ordered by ref->node
+ *                        (protected by @outer_lock)
+ * @waiting_threads:      threads currently waiting for proc work
+ *                        (protected by @inner_lock)
+ * @pid                   PID of group_leader of process
+ *                        (invariant after initialized)
+ * @tsk                   task_struct for group_leader of process
+ *                        (invariant after initialized)
+ * @deferred_work_node:   element for binder_deferred_list
+ *                        (protected by binder_deferred_lock)
+ * @deferred_work:        bitmap of deferred work to perform
+ *                        (protected by binder_deferred_lock)
+ * @is_dead:              process is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @inner_lock)
+ * @todo:                 list of work for this process
+ *                        (protected by @inner_lock)
+ * @stats:                per-process binder statistics
+ *                        (atomics, no lock needed)
+ * @delivered_death:      list of delivered death notification
+ *                        (protected by @inner_lock)
+ * @max_threads:          cap on number of binder threads
+ *                        (protected by @inner_lock)
+ * @requested_threads:    number of binder threads requested but not
+ *                        yet started. In current implementation, can
+ *                        only be 0 or 1.
+ *                        (protected by @inner_lock)
+ * @requested_threads_started: number binder threads started
+ *                        (protected by @inner_lock)
+ * @tmp_ref:              temporary reference to indicate proc is in use
+ *                        (protected by @inner_lock)
+ * @default_priority:     default scheduler priority
+ *                        (invariant after initialized)
+ * @debugfs_entry:        debugfs node
+ * @alloc:                binder allocator bookkeeping
+ * @context:              binder_context for this proc
+ *                        (invariant after initialized)
+ * @inner_lock:           can nest under outer_lock and/or node lock
+ * @outer_lock:           no nesting under innor or node lock
+ *                        Lock order: 1) outer, 2) node, 3) inner
+ * @binderfs_entry:       process-specific binderfs log file
+ *
+ * Bookkeeping structure for binder processes
+ */
+struct binder_proc {
+	struct hlist_node proc_node;
+	struct rb_root threads;
+	struct rb_root nodes;
+	struct rb_root refs_by_desc;
+	struct rb_root refs_by_node;
+	struct list_head waiting_threads;
+	int pid;
+	struct task_struct *tsk;
+	struct hlist_node deferred_work_node;
+	int deferred_work;
+	bool is_dead;
+
+	struct list_head todo;
+	struct binder_stats stats;
+	struct list_head delivered_death;
+	int max_threads;
+	int requested_threads;
+	int requested_threads_started;
+	int tmp_ref;
+	long default_priority;
+	struct dentry *debugfs_entry;
+	struct binder_alloc alloc;
+	struct binder_context *context;
+	spinlock_t inner_lock;
+	spinlock_t outer_lock;
+	struct dentry *binderfs_entry;
+};
+
+/**
+ * struct binder_thread - binder thread bookkeeping
+ * @proc:                 binder process for this thread
+ *                        (invariant after initialization)
+ * @rb_node:              element for proc->threads rbtree
+ *                        (protected by @proc->inner_lock)
+ * @waiting_thread_node:  element for @proc->waiting_threads list
+ *                        (protected by @proc->inner_lock)
+ * @pid:                  PID for this thread
+ *                        (invariant after initialization)
+ * @looper:               bitmap of looping state
+ *                        (only accessed by this thread)
+ * @looper_needs_return:  looping thread needs to exit driver
+ *                        (no lock needed)
+ * @transaction_stack:    stack of in-progress transactions for this thread
+ *                        (protected by @proc->inner_lock)
+ * @todo:                 list of work to do for this thread
+ *                        (protected by @proc->inner_lock)
+ * @process_todo:         whether work in @todo should be processed
+ *                        (protected by @proc->inner_lock)
+ * @return_error:         transaction errors reported by this thread
+ *                        (only accessed by this thread)
+ * @reply_error:          transaction errors reported by target thread
+ *                        (protected by @proc->inner_lock)
+ * @wait:                 wait queue for thread work
+ * @stats:                per-thread statistics
+ *                        (atomics, no lock needed)
+ * @tmp_ref:              temporary reference to indicate thread is in use
+ *                        (atomic since @proc->inner_lock cannot
+ *                        always be acquired)
+ * @is_dead:              thread is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder threads.
+ */
+struct binder_thread {
+	struct binder_proc *proc;
+	struct rb_node rb_node;
+	struct list_head waiting_thread_node;
+	int pid;
+	int looper;              /* only modified by this thread */
+	bool looper_need_return; /* can be written by other thread */
+	struct binder_transaction *transaction_stack;
+	struct list_head todo;
+	bool process_todo;
+	struct binder_error return_error;
+	struct binder_error reply_error;
+	wait_queue_head_t wait;
+	struct binder_stats stats;
+	atomic_t tmp_ref;
+	bool is_dead;
+};
+
+struct binder_transaction {
+	int debug_id;
+	struct binder_work work;
+	struct binder_thread *from;
+	struct binder_transaction *from_parent;
+	struct binder_proc *to_proc;
+	struct binder_thread *to_thread;
+	struct binder_transaction *to_parent;
+	unsigned need_reply:1;
+	/* unsigned is_dead:1; */       /* not used at the moment */
+
+	struct binder_buffer *buffer;
+	unsigned int    code;
+	unsigned int    flags;
+	long    priority;
+	long    saved_priority;
+	kuid_t  sender_euid;
+	struct list_head fd_fixups;
+	binder_uintptr_t security_ctx;
+	/**
+	 * @lock:  protects @from, @to_proc, and @to_thread
+	 *
+	 * @from, @to_proc, and @to_thread can be set to NULL
+	 * during thread teardown
+	 */
+	spinlock_t lock;
+#ifdef CONFIG_BINDER_USER_TRACKING
+	struct timespec timestamp;
+	struct timeval tv;
+#endif
+};
+
 extern struct binder_transaction_log binder_transaction_log;
 extern struct binder_transaction_log binder_transaction_log_failed;
+
+extern void set_binder_update_info_cb(void (*fn)(struct binder_transaction *t,
+				struct binder_transaction_log_entry *e));
+extern void set_print_transaction_ext_cb(void (*fn)(struct seq_file *m,
+					struct binder_transaction *t));
 #endif /* _LINUX_BINDER_INTERNAL_H */
diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
new file mode 100644
index 0000000..c9626f5
--- /dev/null
+++ b/drivers/android/binder_latency_tracer.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ */
+
+#include <linux/module.h>
+#include <uapi/linux/android/binder.h>
+#include "binder_alloc.h"
+#include "binder_internal.h"
+#include "binder_trace.h"
+
+/*
+ * probe_binder_free_transaction - Output info of a delay transaction
+ * @t:          pointer to the over-time transaction
+ */
+void probe_binder_free_transaction(void *ignore, struct binder_transaction *t)
+{
+	struct rtc_time tm;
+	struct timespec *startime;
+	struct timespec cur, sub_t;
+
+	ktime_get_ts(&cur);
+	startime = &t->timestamp;
+	sub_t = timespec_sub(cur, *startime);
+
+	/* if transaction time is over than 2 sec,
+	 * show timeout warning log.
+	 */
+	if (sub_t.tv_sec < 2)
+		return;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+
+	spin_lock(&t->lock);
+	pr_info_ratelimited("%d: from %d:%d to %d:%d",
+			t->debug_id,
+			t->from ? t->from->proc->pid : 0,
+			t->from ? t->from->pid : 0,
+			t->to_proc ? t->to_proc->pid : 0,
+			t->to_thread ? t->to_thread->pid : 0);
+	spin_unlock(&t->lock);
+
+	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
+			(unsigned int)sub_t.tv_sec,
+			(sub_t.tv_nsec / NSEC_PER_MSEC),
+			t->code,
+			(unsigned long)startime->tv_sec,
+			(startime->tv_nsec / NSEC_PER_MSEC),
+			(tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+			tm.tm_hour, tm.tm_min, tm.tm_sec,
+			(unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+
+static void binder_update_info_cb(struct binder_transaction *t,
+			   struct binder_transaction_log_entry *e)
+{
+	ktime_get_ts(&e->timestamp);
+	do_gettimeofday(&e->tv);
+	e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
+	memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
+	memcpy(&t->tv, &e->tv, sizeof(struct timeval));
+}
+
+static void print_binder_transaction_ext(struct seq_file *m,
+					 struct binder_transaction *t)
+{
+	struct rtc_time tm;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+	seq_printf(m,
+		   " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
+		   (unsigned long)t->timestamp.tv_sec,
+		   (t->timestamp.tv_nsec / NSEC_PER_USEC),
+		   (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+		   tm.tm_hour, tm.tm_min, tm.tm_sec,
+		   (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+
+}
+
+static int __init init_binder_latency_tracer(void)
+{
+	register_trace_binder_free_transaction(
+			probe_binder_free_transaction, NULL);
+
+	set_binder_update_info_cb(binder_update_info_cb);
+	set_print_transaction_ext_cb(print_binder_transaction_ext);
+	return 0;
+}
+
+static void exit_binder_latency_tracer(void)
+{
+	unregister_trace_binder_free_transaction(
+			probe_binder_free_transaction, NULL);
+}
+
+module_init(init_binder_latency_tracer);
+module_exit(exit_binder_latency_tracer);
+
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 6731c3c..c7c76c1 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,42 @@
 		  __entry->thread_todo)
 );
 
+TRACE_EVENT(binder_free_transaction,
+	TP_PROTO(struct binder_transaction *t),
+	TP_ARGS(t),
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, from_proc)
+		__field(int, from_thread)
+		__field(int, to_proc)
+		__field(int, to_thread)
+		__field(unsigned int, code)
+		__field(unsigned int, flags)
+		__field(unsigned long, start_sec)
+		__field(unsigned long, start_nsec)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->from_proc = t->from ? t->from->proc->pid : 0;
+		__entry->from_thread = t->from ? t->from->pid : 0;
+		__entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
+		__entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
+		__entry->code = t->code;
+		__entry->flags = t->flags;
+#ifdef CONFIG_BINDER_USER_TRACKING
+		__entry->start_sec = t->timestamp.tv_sec;
+		__entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
+#else
+		__entry->start_sec = 0;
+		__entry->start_nsec = 0;
+#endif
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
+		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
+		  __entry->to_proc, __entry->to_thread, __entry->code,
+		  __entry->flags, __entry->start_sec, __entry->start_nsec)
+);
+
 TRACE_EVENT(binder_transaction,
 	TP_PROTO(bool reply, struct binder_transaction *t,
 		 struct binder_node *target_node),
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 1/1] binder: transaction latency tracking for user build
  2020-04-15  5:37                 ` [PATCH v2 1/1] " Frankie Chang
@ 2020-04-15 22:25                   ` Todd Kjos
  2020-04-29  8:32                     ` Frankie Chang
  2020-04-30  8:13                   ` Frankie Chang
  1 sibling, 1 reply; 72+ messages in thread
From: Todd Kjos @ 2020-04-15 22:25 UTC (permalink / raw)
  To: Frankie Chang
  Cc: Todd Kjos, wsd_upstream, Greg Kroah-Hartman, LKML,
	Arve Hjønnevåg, Jian-Min Liu, linux-mediatek,
	Joel Fernandes, Martijn Coenen, Christian Brauner

On Tue, Apr 14, 2020 at 10:38 PM Frankie Chang
<Frankie.Chang@mediatek.com> wrote:
>
> Record start/end timestamp to binder transaction.

s/timestamp to/timestamps for/

> When transaction is completed or transaction is free,
> it would be checked if transaction latency over threshold (2 sec),

Is the 2 sec configurable? Why was 2 sec chosen?

> if yes, printing related information for tracing.
>
> /* Implement details */
> - Add tracepoint/trace at free transaction.
>   Since the original trace_binder_transaction_reveived cannot

s/reveived/received/

>   precisely present the real finished time of transaction, adding a
>   trace_binder_free_transaction at the point of free transaction
>   may be more close to it.

Can we just add that trace instead?

>
> - Add latency tracer module to monitor slow transaction.
>   The trace_binder_free_transaction would not be enabled
>   by default. Monitoring which transaction is too slow to
>   cause some of exceptions is important. So we hook the
>   tracepoint to call the monitor function.
>
> - Move some struct from core file to header file.
>   Need some struct defined in core file in latency trace module
>   In addition, moving structs to header file makes module more
>   extendable.
>
> Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
> ---
>  drivers/android/Kconfig                 |    8 ++
>  drivers/android/Makefile                |    1 +
>  drivers/android/binder.c                |  237 ++++---------------------------
>  drivers/android/binder_internal.h       |  227 +++++++++++++++++++++++++++++
>  drivers/android/binder_latency_tracer.c |  100 +++++++++++++
>  drivers/android/binder_trace.h          |   36 +++++
>  6 files changed, 400 insertions(+), 209 deletions(-)
>  create mode 100644 drivers/android/binder_latency_tracer.c
>
> diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> index 6fdf2ab..7ba80eb 100644
> --- a/drivers/android/Kconfig
> +++ b/drivers/android/Kconfig
> @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
>           exhaustively with combinations of various buffer sizes and
>           alignments.
>
> +config BINDER_USER_TRACKING
> +       bool "Android Binder transaction tracking"
> +       help
> +         Used for track abnormal binder transaction which is over 2 seconds,
> +         when the transaction is done or be free, this transaction would be
> +         checked whether it executed overtime.
> +         If yes, printing out the detail info about it.
> +
>  endif # if ANDROID
>
>  endmenu
> diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> index c9d3d0c9..552e8ac 100644
> --- a/drivers/android/Makefile
> +++ b/drivers/android/Makefile
> @@ -4,3 +4,4 @@ ccflags-y += -I$(src)                   # needed for trace events
>  obj-$(CONFIG_ANDROID_BINDERFS)         += binderfs.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC)       += binder.o binder_alloc.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> +obj-$(CONFIG_BINDER_USER_TRACKING)     += binder_latency_tracer.o
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index a6b2082..380a68b 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -160,24 +160,6 @@ static int binder_set_stop_on_user_error(const char *val,
>  #define to_binder_fd_array_object(hdr) \
>         container_of(hdr, struct binder_fd_array_object, hdr)
>
> -enum binder_stat_types {
> -       BINDER_STAT_PROC,
> -       BINDER_STAT_THREAD,
> -       BINDER_STAT_NODE,
> -       BINDER_STAT_REF,
> -       BINDER_STAT_DEATH,
> -       BINDER_STAT_TRANSACTION,
> -       BINDER_STAT_TRANSACTION_COMPLETE,
> -       BINDER_STAT_COUNT
> -};
> -
> -struct binder_stats {
> -       atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
> -       atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
> -       atomic_t obj_created[BINDER_STAT_COUNT];
> -       atomic_t obj_deleted[BINDER_STAT_COUNT];
> -};
> -
>  static struct binder_stats binder_stats;
>
>  static inline void binder_stats_deleted(enum binder_stat_types type)
> @@ -214,32 +196,6 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
>  }
>
>  /**
> - * struct binder_work - work enqueued on a worklist
> - * @entry:             node enqueued on list
> - * @type:              type of work to be performed
> - *
> - * There are separate work lists for proc, thread, and node (async).
> - */
> -struct binder_work {
> -       struct list_head entry;
> -
> -       enum {
> -               BINDER_WORK_TRANSACTION = 1,
> -               BINDER_WORK_TRANSACTION_COMPLETE,
> -               BINDER_WORK_RETURN_ERROR,
> -               BINDER_WORK_NODE,
> -               BINDER_WORK_DEAD_BINDER,
> -               BINDER_WORK_DEAD_BINDER_AND_CLEAR,
> -               BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
> -       } type;
> -};
> -
> -struct binder_error {
> -       struct binder_work work;
> -       uint32_t cmd;
> -};
> -
> -/**
>   * struct binder_node - binder node bookkeeping
>   * @debug_id:             unique ID for debugging
>   *                        (invariant after initialized)

Please, if we must have a binder_internal.h for the key data
structures, then move them all.
The use of structs by transaction latency stuff shouldn't be the
rationale for what moves and
what stays. binder_proc, binder_node, binder_thread etc should be defined
in the same file.

> @@ -402,89 +358,6 @@ enum binder_deferred_state {
>         BINDER_DEFERRED_RELEASE      = 0x02,
>  };
>
> -/**
> - * struct binder_proc - binder process bookkeeping
> - * @proc_node:            element for binder_procs list
> - * @threads:              rbtree of binder_threads in this proc
> - *                        (protected by @inner_lock)
> - * @nodes:                rbtree of binder nodes associated with
> - *                        this proc ordered by node->ptr
> - *                        (protected by @inner_lock)
> - * @refs_by_desc:         rbtree of refs ordered by ref->desc
> - *                        (protected by @outer_lock)
> - * @refs_by_node:         rbtree of refs ordered by ref->node
> - *                        (protected by @outer_lock)
> - * @waiting_threads:      threads currently waiting for proc work
> - *                        (protected by @inner_lock)
> - * @pid                   PID of group_leader of process
> - *                        (invariant after initialized)
> - * @tsk                   task_struct for group_leader of process
> - *                        (invariant after initialized)
> - * @deferred_work_node:   element for binder_deferred_list
> - *                        (protected by binder_deferred_lock)
> - * @deferred_work:        bitmap of deferred work to perform
> - *                        (protected by binder_deferred_lock)
> - * @is_dead:              process is dead and awaiting free
> - *                        when outstanding transactions are cleaned up
> - *                        (protected by @inner_lock)
> - * @todo:                 list of work for this process
> - *                        (protected by @inner_lock)
> - * @stats:                per-process binder statistics
> - *                        (atomics, no lock needed)
> - * @delivered_death:      list of delivered death notification
> - *                        (protected by @inner_lock)
> - * @max_threads:          cap on number of binder threads
> - *                        (protected by @inner_lock)
> - * @requested_threads:    number of binder threads requested but not
> - *                        yet started. In current implementation, can
> - *                        only be 0 or 1.
> - *                        (protected by @inner_lock)
> - * @requested_threads_started: number binder threads started
> - *                        (protected by @inner_lock)
> - * @tmp_ref:              temporary reference to indicate proc is in use
> - *                        (protected by @inner_lock)
> - * @default_priority:     default scheduler priority
> - *                        (invariant after initialized)
> - * @debugfs_entry:        debugfs node
> - * @alloc:                binder allocator bookkeeping
> - * @context:              binder_context for this proc
> - *                        (invariant after initialized)
> - * @inner_lock:           can nest under outer_lock and/or node lock
> - * @outer_lock:           no nesting under innor or node lock
> - *                        Lock order: 1) outer, 2) node, 3) inner
> - * @binderfs_entry:       process-specific binderfs log file
> - *
> - * Bookkeeping structure for binder processes
> - */
> -struct binder_proc {
> -       struct hlist_node proc_node;
> -       struct rb_root threads;
> -       struct rb_root nodes;
> -       struct rb_root refs_by_desc;
> -       struct rb_root refs_by_node;
> -       struct list_head waiting_threads;
> -       int pid;
> -       struct task_struct *tsk;
> -       struct hlist_node deferred_work_node;
> -       int deferred_work;
> -       bool is_dead;
> -
> -       struct list_head todo;
> -       struct binder_stats stats;
> -       struct list_head delivered_death;
> -       int max_threads;
> -       int requested_threads;
> -       int requested_threads_started;
> -       int tmp_ref;
> -       long default_priority;
> -       struct dentry *debugfs_entry;
> -       struct binder_alloc alloc;
> -       struct binder_context *context;
> -       spinlock_t inner_lock;
> -       spinlock_t outer_lock;
> -       struct dentry *binderfs_entry;
> -};
> -
>  enum {
>         BINDER_LOOPER_STATE_REGISTERED  = 0x01,
>         BINDER_LOOPER_STATE_ENTERED     = 0x02,
> @@ -495,60 +368,6 @@ enum {
>  };
>
>  /**
> - * struct binder_thread - binder thread bookkeeping
> - * @proc:                 binder process for this thread
> - *                        (invariant after initialization)
> - * @rb_node:              element for proc->threads rbtree
> - *                        (protected by @proc->inner_lock)
> - * @waiting_thread_node:  element for @proc->waiting_threads list
> - *                        (protected by @proc->inner_lock)
> - * @pid:                  PID for this thread
> - *                        (invariant after initialization)
> - * @looper:               bitmap of looping state
> - *                        (only accessed by this thread)
> - * @looper_needs_return:  looping thread needs to exit driver
> - *                        (no lock needed)
> - * @transaction_stack:    stack of in-progress transactions for this thread
> - *                        (protected by @proc->inner_lock)
> - * @todo:                 list of work to do for this thread
> - *                        (protected by @proc->inner_lock)
> - * @process_todo:         whether work in @todo should be processed
> - *                        (protected by @proc->inner_lock)
> - * @return_error:         transaction errors reported by this thread
> - *                        (only accessed by this thread)
> - * @reply_error:          transaction errors reported by target thread
> - *                        (protected by @proc->inner_lock)
> - * @wait:                 wait queue for thread work
> - * @stats:                per-thread statistics
> - *                        (atomics, no lock needed)
> - * @tmp_ref:              temporary reference to indicate thread is in use
> - *                        (atomic since @proc->inner_lock cannot
> - *                        always be acquired)
> - * @is_dead:              thread is dead and awaiting free
> - *                        when outstanding transactions are cleaned up
> - *                        (protected by @proc->inner_lock)
> - *
> - * Bookkeeping structure for binder threads.
> - */
> -struct binder_thread {
> -       struct binder_proc *proc;
> -       struct rb_node rb_node;
> -       struct list_head waiting_thread_node;
> -       int pid;
> -       int looper;              /* only modified by this thread */
> -       bool looper_need_return; /* can be written by other thread */
> -       struct binder_transaction *transaction_stack;
> -       struct list_head todo;
> -       bool process_todo;
> -       struct binder_error return_error;
> -       struct binder_error reply_error;
> -       wait_queue_head_t wait;
> -       struct binder_stats stats;
> -       atomic_t tmp_ref;
> -       bool is_dead;
> -};
> -
> -/**
>   * struct binder_txn_fd_fixup - transaction fd fixup list element
>   * @fixup_entry:          list entry
>   * @file:                 struct file to be associated with new fd
> @@ -565,34 +384,6 @@ struct binder_txn_fd_fixup {
>         size_t offset;
>  };
>
>

extra empty line?

> -struct binder_transaction {
> -       int debug_id;
> -       struct binder_work work;
> -       struct binder_thread *from;
> -       struct binder_transaction *from_parent;
> -       struct binder_proc *to_proc;
> -       struct binder_thread *to_thread;
> -       struct binder_transaction *to_parent;
> -       unsigned need_reply:1;
> -       /* unsigned is_dead:1; */       /* not used at the moment */
> -
> -       struct binder_buffer *buffer;
> -       unsigned int    code;
> -       unsigned int    flags;
> -       long    priority;
> -       long    saved_priority;
> -       kuid_t  sender_euid;
> -       struct list_head fd_fixups;
> -       binder_uintptr_t security_ctx;
> -       /**
> -        * @lock:  protects @from, @to_proc, and @to_thread
> -        *
> -        * @from, @to_proc, and @to_thread can be set to NULL
> -        * during thread teardown
> -        */
> -       spinlock_t lock;
> -};
> -
>  /**
>   * struct binder_object - union of flat binder object types
>   * @hdr:   generic object header
> @@ -613,6 +404,26 @@ struct binder_object {
>         };
>  };
>
> +static void (*__binder_update_info_cb)(struct binder_transaction *t,
> +                                       struct binder_transaction_log_entry *e);
> +
> +void set_binder_update_info_cb(void (*fn)(struct binder_transaction *t,
> +                                       struct binder_transaction_log_entry *e))
> +{
> +       __binder_update_info_cb = fn;
> +}
> +EXPORT_SYMBOL_GPL(set_binder_update_info_cb);
> +
> +static void (*__print_transaction_ext_cb)(struct seq_file *m,
> +                                       struct binder_transaction *t);
> +
> +void set_print_transaction_ext_cb(void (*fn)(struct seq_file *m,
> +                                       struct binder_transaction *t))
> +{
> +       __print_transaction_ext_cb = fn;
> +}
> +EXPORT_SYMBOL_GPL(set_print_transaction_ext_cb);

Why can't we use tracepoints (not trace events) for this instead of
custom registration functions? You can attach to the tracepoint with
register_trace_* lets a module register to be called to handle the
tracepoint as Joel pointed out.

> +
>  /**
>   * binder_proc_lock() - Acquire outer lock for given binder_proc
>   * @proc:         struct binder_proc to acquire
> @@ -1927,6 +1738,7 @@ static void binder_free_transaction(struct binder_transaction *t)
>          * If the transaction has no target_proc, then
>          * t->buffer->transaction has already been cleared.
>          */
> +       trace_binder_free_transaction(t);
>         binder_free_txn_fixups(t);
>         kfree(t);
>         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> @@ -2874,6 +2686,7 @@ static void binder_transaction(struct binder_proc *proc,
>         e->offsets_size = tr->offsets_size;
>         strscpy(e->context_name, proc->context->name, BINDERFS_MAX_NAME);
>
> +

why 2 empty lines?

>         if (reply) {
>                 binder_inner_proc_lock(proc);
>                 in_reply_to = thread->transaction_stack;
> @@ -3060,6 +2873,9 @@ static void binder_transaction(struct binder_proc *proc,
>                 return_error_line = __LINE__;
>                 goto err_alloc_t_failed;
>         }
> +
> +       if (__binder_update_info_cb)
> +               __binder_update_info_cb(t, e);

This should be a tracepoint that your module can attach to with
register_trace_binder_update_info(...)

>         INIT_LIST_HEAD(&t->fd_fixups);
>         binder_stats_created(BINDER_STAT_TRANSACTION);
>         spin_lock_init(&t->lock);
> @@ -3498,6 +3314,7 @@ static void binder_transaction(struct binder_proc *proc,
>         kfree(tcomplete);
>         binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
>  err_alloc_tcomplete_failed:
> +       trace_binder_free_transaction(t);
>         kfree(t);
>         binder_stats_deleted(BINDER_STAT_TRANSACTION);
>  err_alloc_t_failed:
> @@ -5547,6 +5364,8 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
>                    t->to_thread ? t->to_thread->pid : 0,
>                    t->code, t->flags, t->priority, t->need_reply);
>         spin_unlock(&t->lock);
> +       if (__print_transaction_ext_cb)
> +               __print_transaction_ext_cb(m, t);

same here.

>
>         if (proc != to_proc) {
>                 /*
> diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> index ae99109..86b4960 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -12,6 +12,11 @@
>  #include <linux/types.h>
>  #include <linux/uidgid.h>
>
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +#include <linux/rtc.h>
> +#include <linux/time.h>
> +#endif
> +
>  struct binder_context {
>         struct binder_node *binder_context_mgr_node;
>         struct mutex context_mgr_node_lock;
> @@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
>         uint32_t return_error;
>         uint32_t return_error_param;
>         char context_name[BINDERFS_MAX_NAME + 1];
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +       struct timespec timestamp;
> +       struct timeval tv;
> +#endif
>  };
>
>  struct binder_transaction_log {
> @@ -139,6 +148,224 @@ struct binder_transaction_log {
>         struct binder_transaction_log_entry entry[32];
>  };
>
> +enum binder_stat_types {
> +       BINDER_STAT_PROC,
> +       BINDER_STAT_THREAD,
> +       BINDER_STAT_NODE,
> +       BINDER_STAT_REF,
> +       BINDER_STAT_DEATH,
> +       BINDER_STAT_TRANSACTION,
> +       BINDER_STAT_TRANSACTION_COMPLETE,
> +       BINDER_STAT_COUNT
> +};
> +
> +struct binder_stats {
> +       atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
> +       atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
> +       atomic_t obj_created[BINDER_STAT_COUNT];
> +       atomic_t obj_deleted[BINDER_STAT_COUNT];
> +};
> +
> +/**
> + * struct binder_work - work enqueued on a worklist
> + * @entry:             node enqueued on list
> + * @type:              type of work to be performed
> + *
> + * There are separate work lists for proc, thread, and node (async).
> + */
> +struct binder_work {
> +       struct list_head entry;
> +
> +       enum {
> +               BINDER_WORK_TRANSACTION = 1,
> +               BINDER_WORK_TRANSACTION_COMPLETE,
> +               BINDER_WORK_RETURN_ERROR,
> +               BINDER_WORK_NODE,
> +               BINDER_WORK_DEAD_BINDER,
> +               BINDER_WORK_DEAD_BINDER_AND_CLEAR,
> +               BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
> +       } type;
> +};
> +
> +struct binder_error {
> +       struct binder_work work;
> +       uint32_t cmd;
> +};
> +
> +/**
> + * struct binder_proc - binder process bookkeeping
> + * @proc_node:            element for binder_procs list
> + * @threads:              rbtree of binder_threads in this proc
> + *                        (protected by @inner_lock)
> + * @nodes:                rbtree of binder nodes associated with
> + *                        this proc ordered by node->ptr
> + *                        (protected by @inner_lock)
> + * @refs_by_desc:         rbtree of refs ordered by ref->desc
> + *                        (protected by @outer_lock)
> + * @refs_by_node:         rbtree of refs ordered by ref->node
> + *                        (protected by @outer_lock)
> + * @waiting_threads:      threads currently waiting for proc work
> + *                        (protected by @inner_lock)
> + * @pid                   PID of group_leader of process
> + *                        (invariant after initialized)
> + * @tsk                   task_struct for group_leader of process
> + *                        (invariant after initialized)
> + * @deferred_work_node:   element for binder_deferred_list
> + *                        (protected by binder_deferred_lock)
> + * @deferred_work:        bitmap of deferred work to perform
> + *                        (protected by binder_deferred_lock)
> + * @is_dead:              process is dead and awaiting free
> + *                        when outstanding transactions are cleaned up
> + *                        (protected by @inner_lock)
> + * @todo:                 list of work for this process
> + *                        (protected by @inner_lock)
> + * @stats:                per-process binder statistics
> + *                        (atomics, no lock needed)
> + * @delivered_death:      list of delivered death notification
> + *                        (protected by @inner_lock)
> + * @max_threads:          cap on number of binder threads
> + *                        (protected by @inner_lock)
> + * @requested_threads:    number of binder threads requested but not
> + *                        yet started. In current implementation, can
> + *                        only be 0 or 1.
> + *                        (protected by @inner_lock)
> + * @requested_threads_started: number binder threads started
> + *                        (protected by @inner_lock)
> + * @tmp_ref:              temporary reference to indicate proc is in use
> + *                        (protected by @inner_lock)
> + * @default_priority:     default scheduler priority
> + *                        (invariant after initialized)
> + * @debugfs_entry:        debugfs node
> + * @alloc:                binder allocator bookkeeping
> + * @context:              binder_context for this proc
> + *                        (invariant after initialized)
> + * @inner_lock:           can nest under outer_lock and/or node lock
> + * @outer_lock:           no nesting under innor or node lock
> + *                        Lock order: 1) outer, 2) node, 3) inner
> + * @binderfs_entry:       process-specific binderfs log file
> + *
> + * Bookkeeping structure for binder processes
> + */
> +struct binder_proc {
> +       struct hlist_node proc_node;
> +       struct rb_root threads;
> +       struct rb_root nodes;
> +       struct rb_root refs_by_desc;
> +       struct rb_root refs_by_node;
> +       struct list_head waiting_threads;
> +       int pid;
> +       struct task_struct *tsk;
> +       struct hlist_node deferred_work_node;
> +       int deferred_work;
> +       bool is_dead;
> +
> +       struct list_head todo;
> +       struct binder_stats stats;
> +       struct list_head delivered_death;
> +       int max_threads;
> +       int requested_threads;
> +       int requested_threads_started;
> +       int tmp_ref;
> +       long default_priority;
> +       struct dentry *debugfs_entry;
> +       struct binder_alloc alloc;
> +       struct binder_context *context;
> +       spinlock_t inner_lock;
> +       spinlock_t outer_lock;
> +       struct dentry *binderfs_entry;
> +};
> +
> +/**
> + * struct binder_thread - binder thread bookkeeping
> + * @proc:                 binder process for this thread
> + *                        (invariant after initialization)
> + * @rb_node:              element for proc->threads rbtree
> + *                        (protected by @proc->inner_lock)
> + * @waiting_thread_node:  element for @proc->waiting_threads list
> + *                        (protected by @proc->inner_lock)
> + * @pid:                  PID for this thread
> + *                        (invariant after initialization)
> + * @looper:               bitmap of looping state
> + *                        (only accessed by this thread)
> + * @looper_needs_return:  looping thread needs to exit driver
> + *                        (no lock needed)
> + * @transaction_stack:    stack of in-progress transactions for this thread
> + *                        (protected by @proc->inner_lock)
> + * @todo:                 list of work to do for this thread
> + *                        (protected by @proc->inner_lock)
> + * @process_todo:         whether work in @todo should be processed
> + *                        (protected by @proc->inner_lock)
> + * @return_error:         transaction errors reported by this thread
> + *                        (only accessed by this thread)
> + * @reply_error:          transaction errors reported by target thread
> + *                        (protected by @proc->inner_lock)
> + * @wait:                 wait queue for thread work
> + * @stats:                per-thread statistics
> + *                        (atomics, no lock needed)
> + * @tmp_ref:              temporary reference to indicate thread is in use
> + *                        (atomic since @proc->inner_lock cannot
> + *                        always be acquired)
> + * @is_dead:              thread is dead and awaiting free
> + *                        when outstanding transactions are cleaned up
> + *                        (protected by @proc->inner_lock)
> + *
> + * Bookkeeping structure for binder threads.
> + */
> +struct binder_thread {
> +       struct binder_proc *proc;
> +       struct rb_node rb_node;
> +       struct list_head waiting_thread_node;
> +       int pid;
> +       int looper;              /* only modified by this thread */
> +       bool looper_need_return; /* can be written by other thread */
> +       struct binder_transaction *transaction_stack;
> +       struct list_head todo;
> +       bool process_todo;
> +       struct binder_error return_error;
> +       struct binder_error reply_error;
> +       wait_queue_head_t wait;
> +       struct binder_stats stats;
> +       atomic_t tmp_ref;
> +       bool is_dead;
> +};
> +
> +struct binder_transaction {
> +       int debug_id;
> +       struct binder_work work;
> +       struct binder_thread *from;
> +       struct binder_transaction *from_parent;
> +       struct binder_proc *to_proc;
> +       struct binder_thread *to_thread;
> +       struct binder_transaction *to_parent;
> +       unsigned need_reply:1;
> +       /* unsigned is_dead:1; */       /* not used at the moment */
> +
> +       struct binder_buffer *buffer;
> +       unsigned int    code;
> +       unsigned int    flags;
> +       long    priority;
> +       long    saved_priority;
> +       kuid_t  sender_euid;
> +       struct list_head fd_fixups;
> +       binder_uintptr_t security_ctx;
> +       /**
> +        * @lock:  protects @from, @to_proc, and @to_thread
> +        *
> +        * @from, @to_proc, and @to_thread can be set to NULL
> +        * during thread teardown
> +        */
> +       spinlock_t lock;
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +       struct timespec timestamp;
> +       struct timeval tv;
> +#endif
> +};
> +
>  extern struct binder_transaction_log binder_transaction_log;
>  extern struct binder_transaction_log binder_transaction_log_failed;
> +
> +extern void set_binder_update_info_cb(void (*fn)(struct binder_transaction *t,
> +                               struct binder_transaction_log_entry *e));
> +extern void set_print_transaction_ext_cb(void (*fn)(struct seq_file *m,
> +                                       struct binder_transaction *t));
>  #endif /* _LINUX_BINDER_INTERNAL_H */
> diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
> new file mode 100644
> index 0000000..c9626f5
> --- /dev/null
> +++ b/drivers/android/binder_latency_tracer.c
> @@ -0,0 +1,100 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2019 MediaTek Inc.
> + */
> +
> +#include <linux/module.h>
> +#include <uapi/linux/android/binder.h>
> +#include "binder_alloc.h"
> +#include "binder_internal.h"
> +#include "binder_trace.h"
> +
> +/*
> + * probe_binder_free_transaction - Output info of a delay transaction
> + * @t:          pointer to the over-time transaction
> + */
> +void probe_binder_free_transaction(void *ignore, struct binder_transaction *t)
> +{
> +       struct rtc_time tm;
> +       struct timespec *startime;
> +       struct timespec cur, sub_t;
> +
> +       ktime_get_ts(&cur);
> +       startime = &t->timestamp;
> +       sub_t = timespec_sub(cur, *startime);
> +
> +       /* if transaction time is over than 2 sec,
> +        * show timeout warning log.
> +        */
> +       if (sub_t.tv_sec < 2)
> +               return;
> +
> +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> +
> +       spin_lock(&t->lock);
> +       pr_info_ratelimited("%d: from %d:%d to %d:%d",
> +                       t->debug_id,
> +                       t->from ? t->from->proc->pid : 0,
> +                       t->from ? t->from->pid : 0,
> +                       t->to_proc ? t->to_proc->pid : 0,
> +                       t->to_thread ? t->to_thread->pid : 0);
> +       spin_unlock(&t->lock);
> +
> +       pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> +                       (unsigned int)sub_t.tv_sec,
> +                       (sub_t.tv_nsec / NSEC_PER_MSEC),
> +                       t->code,
> +                       (unsigned long)startime->tv_sec,
> +                       (startime->tv_nsec / NSEC_PER_MSEC),
> +                       (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> +                       tm.tm_hour, tm.tm_min, tm.tm_sec,
> +                       (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> +}
> +
> +static void binder_update_info_cb(struct binder_transaction *t,
> +                          struct binder_transaction_log_entry *e)
> +{
> +       ktime_get_ts(&e->timestamp);
> +       do_gettimeofday(&e->tv);
> +       e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
> +       memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
> +       memcpy(&t->tv, &e->tv, sizeof(struct timeval));
> +}
> +
> +static void print_binder_transaction_ext(struct seq_file *m,
> +                                        struct binder_transaction *t)
> +{
> +       struct rtc_time tm;
> +
> +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> +       seq_printf(m,
> +                  " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
> +                  (unsigned long)t->timestamp.tv_sec,
> +                  (t->timestamp.tv_nsec / NSEC_PER_USEC),
> +                  (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> +                  tm.tm_hour, tm.tm_min, tm.tm_sec,
> +                  (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> +
> +}
> +
> +static int __init init_binder_latency_tracer(void)
> +{
> +       register_trace_binder_free_transaction(
> +                       probe_binder_free_transaction, NULL);
> +
> +       set_binder_update_info_cb(binder_update_info_cb);
> +       set_print_transaction_ext_cb(print_binder_transaction_ext);
> +       return 0;
> +}
> +
> +static void exit_binder_latency_tracer(void)
> +{
> +       unregister_trace_binder_free_transaction(
> +                       probe_binder_free_transaction, NULL);
> +}
> +
> +module_init(init_binder_latency_tracer);
> +module_exit(exit_binder_latency_tracer);
> +
> +MODULE_LICENSE("GPL v2");
> +
> diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> index 6731c3c..c7c76c1 100644
> --- a/drivers/android/binder_trace.h
> +++ b/drivers/android/binder_trace.h
> @@ -95,6 +95,42 @@
>                   __entry->thread_todo)
>  );
>
> +TRACE_EVENT(binder_free_transaction,
> +       TP_PROTO(struct binder_transaction *t),
> +       TP_ARGS(t),
> +       TP_STRUCT__entry(
> +               __field(int, debug_id)
> +               __field(int, from_proc)
> +               __field(int, from_thread)
> +               __field(int, to_proc)
> +               __field(int, to_thread)
> +               __field(unsigned int, code)
> +               __field(unsigned int, flags)
> +               __field(unsigned long, start_sec)
> +               __field(unsigned long, start_nsec)
> +       ),
> +       TP_fast_assign(
> +               __entry->debug_id = t->debug_id;
> +               __entry->from_proc = t->from ? t->from->proc->pid : 0;
> +               __entry->from_thread = t->from ? t->from->pid : 0;
> +               __entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
> +               __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
> +               __entry->code = t->code;
> +               __entry->flags = t->flags;
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +               __entry->start_sec = t->timestamp.tv_sec;
> +               __entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
> +#else
> +               __entry->start_sec = 0;
> +               __entry->start_nsec = 0;
> +#endif
> +       ),
> +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
> +                 __entry->debug_id, __entry->from_proc, __entry->from_thread,
> +                 __entry->to_proc, __entry->to_thread, __entry->code,
> +                 __entry->flags, __entry->start_sec, __entry->start_nsec)
> +);
> +
>  TRACE_EVENT(binder_transaction,
>         TP_PROTO(bool reply, struct binder_transaction *t,
>                  struct binder_node *target_node),
> --
> 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 1/1] binder: transaction latency tracking for user build
  2020-04-15 22:25                   ` Todd Kjos
@ 2020-04-29  8:32                     ` Frankie Chang
  0 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-04-29  8:32 UTC (permalink / raw)
  To: Todd Kjos
  Cc: Todd Kjos, wsd_upstream, Greg Kroah-Hartman, LKML,
	Arve Hjønnevåg, Jian-Min Liu, linux-mediatek,
	Joel Fernandes, Martijn Coenen, Christian Brauner

On Wed, 2020-04-15 at 15:25 -0700, Todd Kjos wrote:
> On Tue, Apr 14, 2020 at 10:38 PM Frankie Chang
> <Frankie.Chang@mediatek.com> wrote:
> >
> > Record start/end timestamp to binder transaction.
> 
> s/timestamp to/timestamps for/
> 
> > When transaction is completed or transaction is free,
> > it would be checked if transaction latency over threshold (2 sec),
> 
> Is the 2 sec configurable? Why was 2 sec chosen?

Some of modules would trigger timeout NE if their binder transaction
don't finish in time, such as audio timeout (5 sec), even BT command
timeout (2 sec), etc.

Therefore, we want to record these transactions which exceed 2 sec. It
could be helpful to debug.

> > if yes, printing related information for tracing.
> >
> > /* Implement details */
> > - Add tracepoint/trace at free transaction.
> >   Since the original trace_binder_transaction_reveived cannot
> 
> s/reveived/received/
> 
> >   precisely present the real finished time of transaction, adding a
> >   trace_binder_free_transaction at the point of free transaction
> >   may be more close to it.
> 
> Can we just add that trace instead?

Time limitation of recording is the reason why we don't just use trace
here.

In some long time stability test, such as MTBF,
the exception is caused by a series of transactions interaction.
Some abnormal transactions may be pending for a long time ago, they 
could not be recorded due to buffer limited. 

> >
> > - Add latency tracer module to monitor slow transaction.
> >   The trace_binder_free_transaction would not be enabled
> >   by default. Monitoring which transaction is too slow to
> >   cause some of exceptions is important. So we hook the
> >   tracepoint to call the monitor function.
> >
> > - Move some struct from core file to header file.
> >   Need some struct defined in core file in latency trace module
> >   In addition, moving structs to header file makes module more
> >   extendable.
> >
> > Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
> > ---
> >  drivers/android/Kconfig                 |    8 ++
> >  drivers/android/Makefile                |    1 +
> >  drivers/android/binder.c                |  237 ++++---------------------------
> >  drivers/android/binder_internal.h       |  227 +++++++++++++++++++++++++++++
> >  drivers/android/binder_latency_tracer.c |  100 +++++++++++++
> >  drivers/android/binder_trace.h          |   36 +++++
> >  6 files changed, 400 insertions(+), 209 deletions(-)
> >  create mode 100644 drivers/android/binder_latency_tracer.c
> >
> > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > index 6fdf2ab..7ba80eb 100644
> > --- a/drivers/android/Kconfig
> > +++ b/drivers/android/Kconfig
> > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> >           exhaustively with combinations of various buffer sizes and
> >           alignments.
> >
> > +config BINDER_USER_TRACKING
> > +       bool "Android Binder transaction tracking"
> > +       help
> > +         Used for track abnormal binder transaction which is over 2 seconds,
> > +         when the transaction is done or be free, this transaction would be
> > +         checked whether it executed overtime.
> > +         If yes, printing out the detail info about it.
> > +
> >  endif # if ANDROID
> >
> >  endmenu
> > diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> > index c9d3d0c9..552e8ac 100644
> > --- a/drivers/android/Makefile
> > +++ b/drivers/android/Makefile
> > @@ -4,3 +4,4 @@ ccflags-y += -I$(src)                   # needed for trace events
> >  obj-$(CONFIG_ANDROID_BINDERFS)         += binderfs.o
> >  obj-$(CONFIG_ANDROID_BINDER_IPC)       += binder.o binder_alloc.o
> >  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> > +obj-$(CONFIG_BINDER_USER_TRACKING)     += binder_latency_tracer.o
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index a6b2082..380a68b 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -160,24 +160,6 @@ static int binder_set_stop_on_user_error(const char *val,
> >  #define to_binder_fd_array_object(hdr) \
> >         container_of(hdr, struct binder_fd_array_object, hdr)
> >
> > -enum binder_stat_types {
> > -       BINDER_STAT_PROC,
> > -       BINDER_STAT_THREAD,
> > -       BINDER_STAT_NODE,
> > -       BINDER_STAT_REF,
> > -       BINDER_STAT_DEATH,
> > -       BINDER_STAT_TRANSACTION,
> > -       BINDER_STAT_TRANSACTION_COMPLETE,
> > -       BINDER_STAT_COUNT
> > -};
> > -
> > -struct binder_stats {
> > -       atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
> > -       atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
> > -       atomic_t obj_created[BINDER_STAT_COUNT];
> > -       atomic_t obj_deleted[BINDER_STAT_COUNT];
> > -};
> > -
> >  static struct binder_stats binder_stats;
> >
> >  static inline void binder_stats_deleted(enum binder_stat_types type)
> > @@ -214,32 +196,6 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
> >  }
> >
> >  /**
> > - * struct binder_work - work enqueued on a worklist
> > - * @entry:             node enqueued on list
> > - * @type:              type of work to be performed
> > - *
> > - * There are separate work lists for proc, thread, and node (async).
> > - */
> > -struct binder_work {
> > -       struct list_head entry;
> > -
> > -       enum {
> > -               BINDER_WORK_TRANSACTION = 1,
> > -               BINDER_WORK_TRANSACTION_COMPLETE,
> > -               BINDER_WORK_RETURN_ERROR,
> > -               BINDER_WORK_NODE,
> > -               BINDER_WORK_DEAD_BINDER,
> > -               BINDER_WORK_DEAD_BINDER_AND_CLEAR,
> > -               BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
> > -       } type;
> > -};
> > -
> > -struct binder_error {
> > -       struct binder_work work;
> > -       uint32_t cmd;
> > -};
> > -
> > -/**
> >   * struct binder_node - binder node bookkeeping
> >   * @debug_id:             unique ID for debugging
> >   *                        (invariant after initialized)
> 
> Please, if we must have a binder_internal.h for the key data
> structures, then move them all.
> The use of structs by transaction latency stuff shouldn't be the
> rationale for what moves and
> what stays. binder_proc, binder_node, binder_thread etc should be defined
> in the same file.

Okay, we will move all structs to binder_internal.h to make them defined in same file, thanks.

> > @@ -402,89 +358,6 @@ enum binder_deferred_state {
> >         BINDER_DEFERRED_RELEASE      = 0x02,
> >  };
> >
> > -/**
> > - * struct binder_proc - binder process bookkeeping
> > - * @proc_node:            element for binder_procs list
> > - * @threads:              rbtree of binder_threads in this proc
> > - *                        (protected by @inner_lock)
> > - * @nodes:                rbtree of binder nodes associated with
> > - *                        this proc ordered by node->ptr
> > - *                        (protected by @inner_lock)
> > - * @refs_by_desc:         rbtree of refs ordered by ref->desc
> > - *                        (protected by @outer_lock)
> > - * @refs_by_node:         rbtree of refs ordered by ref->node
> > - *                        (protected by @outer_lock)
> > - * @waiting_threads:      threads currently waiting for proc work
> > - *                        (protected by @inner_lock)
> > - * @pid                   PID of group_leader of process
> > - *                        (invariant after initialized)
> > - * @tsk                   task_struct for group_leader of process
> > - *                        (invariant after initialized)
> > - * @deferred_work_node:   element for binder_deferred_list
> > - *                        (protected by binder_deferred_lock)
> > - * @deferred_work:        bitmap of deferred work to perform
> > - *                        (protected by binder_deferred_lock)
> > - * @is_dead:              process is dead and awaiting free
> > - *                        when outstanding transactions are cleaned up
> > - *                        (protected by @inner_lock)
> > - * @todo:                 list of work for this process
> > - *                        (protected by @inner_lock)
> > - * @stats:                per-process binder statistics
> > - *                        (atomics, no lock needed)
> > - * @delivered_death:      list of delivered death notification
> > - *                        (protected by @inner_lock)
> > - * @max_threads:          cap on number of binder threads
> > - *                        (protected by @inner_lock)
> > - * @requested_threads:    number of binder threads requested but not
> > - *                        yet started. In current implementation, can
> > - *                        only be 0 or 1.
> > - *                        (protected by @inner_lock)
> > - * @requested_threads_started: number binder threads started
> > - *                        (protected by @inner_lock)
> > - * @tmp_ref:              temporary reference to indicate proc is in use
> > - *                        (protected by @inner_lock)
> > - * @default_priority:     default scheduler priority
> > - *                        (invariant after initialized)
> > - * @debugfs_entry:        debugfs node
> > - * @alloc:                binder allocator bookkeeping
> > - * @context:              binder_context for this proc
> > - *                        (invariant after initialized)
> > - * @inner_lock:           can nest under outer_lock and/or node lock
> > - * @outer_lock:           no nesting under innor or node lock
> > - *                        Lock order: 1) outer, 2) node, 3) inner
> > - * @binderfs_entry:       process-specific binderfs log file
> > - *
> > - * Bookkeeping structure for binder processes
> > - */
> > -struct binder_proc {
> > -       struct hlist_node proc_node;
> > -       struct rb_root threads;
> > -       struct rb_root nodes;
> > -       struct rb_root refs_by_desc;
> > -       struct rb_root refs_by_node;
> > -       struct list_head waiting_threads;
> > -       int pid;
> > -       struct task_struct *tsk;
> > -       struct hlist_node deferred_work_node;
> > -       int deferred_work;
> > -       bool is_dead;
> > -
> > -       struct list_head todo;
> > -       struct binder_stats stats;
> > -       struct list_head delivered_death;
> > -       int max_threads;
> > -       int requested_threads;
> > -       int requested_threads_started;
> > -       int tmp_ref;
> > -       long default_priority;
> > -       struct dentry *debugfs_entry;
> > -       struct binder_alloc alloc;
> > -       struct binder_context *context;
> > -       spinlock_t inner_lock;
> > -       spinlock_t outer_lock;
> > -       struct dentry *binderfs_entry;
> > -};
> > -
> >  enum {
> >         BINDER_LOOPER_STATE_REGISTERED  = 0x01,
> >         BINDER_LOOPER_STATE_ENTERED     = 0x02,
> > @@ -495,60 +368,6 @@ enum {
> >  };
> >
> >  /**
> > - * struct binder_thread - binder thread bookkeeping
> > - * @proc:                 binder process for this thread
> > - *                        (invariant after initialization)
> > - * @rb_node:              element for proc->threads rbtree
> > - *                        (protected by @proc->inner_lock)
> > - * @waiting_thread_node:  element for @proc->waiting_threads list
> > - *                        (protected by @proc->inner_lock)
> > - * @pid:                  PID for this thread
> > - *                        (invariant after initialization)
> > - * @looper:               bitmap of looping state
> > - *                        (only accessed by this thread)
> > - * @looper_needs_return:  looping thread needs to exit driver
> > - *                        (no lock needed)
> > - * @transaction_stack:    stack of in-progress transactions for this thread
> > - *                        (protected by @proc->inner_lock)
> > - * @todo:                 list of work to do for this thread
> > - *                        (protected by @proc->inner_lock)
> > - * @process_todo:         whether work in @todo should be processed
> > - *                        (protected by @proc->inner_lock)
> > - * @return_error:         transaction errors reported by this thread
> > - *                        (only accessed by this thread)
> > - * @reply_error:          transaction errors reported by target thread
> > - *                        (protected by @proc->inner_lock)
> > - * @wait:                 wait queue for thread work
> > - * @stats:                per-thread statistics
> > - *                        (atomics, no lock needed)
> > - * @tmp_ref:              temporary reference to indicate thread is in use
> > - *                        (atomic since @proc->inner_lock cannot
> > - *                        always be acquired)
> > - * @is_dead:              thread is dead and awaiting free
> > - *                        when outstanding transactions are cleaned up
> > - *                        (protected by @proc->inner_lock)
> > - *
> > - * Bookkeeping structure for binder threads.
> > - */
> > -struct binder_thread {
> > -       struct binder_proc *proc;
> > -       struct rb_node rb_node;
> > -       struct list_head waiting_thread_node;
> > -       int pid;
> > -       int looper;              /* only modified by this thread */
> > -       bool looper_need_return; /* can be written by other thread */
> > -       struct binder_transaction *transaction_stack;
> > -       struct list_head todo;
> > -       bool process_todo;
> > -       struct binder_error return_error;
> > -       struct binder_error reply_error;
> > -       wait_queue_head_t wait;
> > -       struct binder_stats stats;
> > -       atomic_t tmp_ref;
> > -       bool is_dead;
> > -};
> > -
> > -/**
> >   * struct binder_txn_fd_fixup - transaction fd fixup list element
> >   * @fixup_entry:          list entry
> >   * @file:                 struct file to be associated with new fd
> > @@ -565,34 +384,6 @@ struct binder_txn_fd_fixup {
> >         size_t offset;
> >  };
> >
> >
> 
> extra empty line?
> 
> > -struct binder_transaction {
> > -       int debug_id;
> > -       struct binder_work work;
> > -       struct binder_thread *from;
> > -       struct binder_transaction *from_parent;
> > -       struct binder_proc *to_proc;
> > -       struct binder_thread *to_thread;
> > -       struct binder_transaction *to_parent;
> > -       unsigned need_reply:1;
> > -       /* unsigned is_dead:1; */       /* not used at the moment */
> > -
> > -       struct binder_buffer *buffer;
> > -       unsigned int    code;
> > -       unsigned int    flags;
> > -       long    priority;
> > -       long    saved_priority;
> > -       kuid_t  sender_euid;
> > -       struct list_head fd_fixups;
> > -       binder_uintptr_t security_ctx;
> > -       /**
> > -        * @lock:  protects @from, @to_proc, and @to_thread
> > -        *
> > -        * @from, @to_proc, and @to_thread can be set to NULL
> > -        * during thread teardown
> > -        */
> > -       spinlock_t lock;
> > -};
> > -
> >  /**
> >   * struct binder_object - union of flat binder object types
> >   * @hdr:   generic object header
> > @@ -613,6 +404,26 @@ struct binder_object {
> >         };
> >  };
> >
> > +static void (*__binder_update_info_cb)(struct binder_transaction *t,
> > +                                       struct binder_transaction_log_entry *e);
> > +
> > +void set_binder_update_info_cb(void (*fn)(struct binder_transaction *t,
> > +                                       struct binder_transaction_log_entry *e))
> > +{
> > +       __binder_update_info_cb = fn;
> > +}
> > +EXPORT_SYMBOL_GPL(set_binder_update_info_cb);
> > +
> > +static void (*__print_transaction_ext_cb)(struct seq_file *m,
> > +                                       struct binder_transaction *t);
> > +
> > +void set_print_transaction_ext_cb(void (*fn)(struct seq_file *m,
> > +                                       struct binder_transaction *t))
> > +{
> > +       __print_transaction_ext_cb = fn;
> > +}
> > +EXPORT_SYMBOL_GPL(set_print_transaction_ext_cb);
> 
> Why can't we use tracepoints (not trace events) for this instead of
> custom registration functions? You can attach to the tracepoint with
> register_trace_* lets a module register to be called to handle the
> tracepoint as Joel pointed out.

Yes, we will use tracepoints instead of custom registration functions in
next version patch, thanks.

> > +
> >  /**
> >   * binder_proc_lock() - Acquire outer lock for given binder_proc
> >   * @proc:         struct binder_proc to acquire
> > @@ -1927,6 +1738,7 @@ static void binder_free_transaction(struct binder_transaction *t)
> >          * If the transaction has no target_proc, then
> >          * t->buffer->transaction has already been cleared.
> >          */
> > +       trace_binder_free_transaction(t);
> >         binder_free_txn_fixups(t);
> >         kfree(t);
> >         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> > @@ -2874,6 +2686,7 @@ static void binder_transaction(struct binder_proc *proc,
> >         e->offsets_size = tr->offsets_size;
> >         strscpy(e->context_name, proc->context->name, BINDERFS_MAX_NAME);
> >
> > +
> 
> why 2 empty lines?
> 
> >         if (reply) {
> >                 binder_inner_proc_lock(proc);
> >                 in_reply_to = thread->transaction_stack;
> > @@ -3060,6 +2873,9 @@ static void binder_transaction(struct binder_proc *proc,
> >                 return_error_line = __LINE__;
> >                 goto err_alloc_t_failed;
> >         }
> > +
> > +       if (__binder_update_info_cb)
> > +               __binder_update_info_cb(t, e);
> 
> This should be a tracepoint that your module can attach to with
> register_trace_binder_update_info(...)
> 
> >         INIT_LIST_HEAD(&t->fd_fixups);
> >         binder_stats_created(BINDER_STAT_TRANSACTION);
> >         spin_lock_init(&t->lock);
> > @@ -3498,6 +3314,7 @@ static void binder_transaction(struct binder_proc *proc,
> >         kfree(tcomplete);
> >         binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
> >  err_alloc_tcomplete_failed:
> > +       trace_binder_free_transaction(t);
> >         kfree(t);
> >         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> >  err_alloc_t_failed:
> > @@ -5547,6 +5364,8 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
> >                    t->to_thread ? t->to_thread->pid : 0,
> >                    t->code, t->flags, t->priority, t->need_reply);
> >         spin_unlock(&t->lock);
> > +       if (__print_transaction_ext_cb)
> > +               __print_transaction_ext_cb(m, t);
> 
> same here.
> 
> >
> >         if (proc != to_proc) {
> >                 /*
> > diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> > index ae99109..86b4960 100644
> > --- a/drivers/android/binder_internal.h
> > +++ b/drivers/android/binder_internal.h
> > @@ -12,6 +12,11 @@
> >  #include <linux/types.h>
> >  #include <linux/uidgid.h>
> >
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +#include <linux/rtc.h>
> > +#include <linux/time.h>
> > +#endif
> > +
> >  struct binder_context {
> >         struct binder_node *binder_context_mgr_node;
> >         struct mutex context_mgr_node_lock;
> > @@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
> >         uint32_t return_error;
> >         uint32_t return_error_param;
> >         char context_name[BINDERFS_MAX_NAME + 1];
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +       struct timespec timestamp;
> > +       struct timeval tv;
> > +#endif
> >  };
> >
> >  struct binder_transaction_log {
> > @@ -139,6 +148,224 @@ struct binder_transaction_log {
> >         struct binder_transaction_log_entry entry[32];
> >  };
> >
> > +enum binder_stat_types {
> > +       BINDER_STAT_PROC,
> > +       BINDER_STAT_THREAD,
> > +       BINDER_STAT_NODE,
> > +       BINDER_STAT_REF,
> > +       BINDER_STAT_DEATH,
> > +       BINDER_STAT_TRANSACTION,
> > +       BINDER_STAT_TRANSACTION_COMPLETE,
> > +       BINDER_STAT_COUNT
> > +};
> > +
> > +struct binder_stats {
> > +       atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
> > +       atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
> > +       atomic_t obj_created[BINDER_STAT_COUNT];
> > +       atomic_t obj_deleted[BINDER_STAT_COUNT];
> > +};
> > +
> > +/**
> > + * struct binder_work - work enqueued on a worklist
> > + * @entry:             node enqueued on list
> > + * @type:              type of work to be performed
> > + *
> > + * There are separate work lists for proc, thread, and node (async).
> > + */
> > +struct binder_work {
> > +       struct list_head entry;
> > +
> > +       enum {
> > +               BINDER_WORK_TRANSACTION = 1,
> > +               BINDER_WORK_TRANSACTION_COMPLETE,
> > +               BINDER_WORK_RETURN_ERROR,
> > +               BINDER_WORK_NODE,
> > +               BINDER_WORK_DEAD_BINDER,
> > +               BINDER_WORK_DEAD_BINDER_AND_CLEAR,
> > +               BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
> > +       } type;
> > +};
> > +
> > +struct binder_error {
> > +       struct binder_work work;
> > +       uint32_t cmd;
> > +};
> > +
> > +/**
> > + * struct binder_proc - binder process bookkeeping
> > + * @proc_node:            element for binder_procs list
> > + * @threads:              rbtree of binder_threads in this proc
> > + *                        (protected by @inner_lock)
> > + * @nodes:                rbtree of binder nodes associated with
> > + *                        this proc ordered by node->ptr
> > + *                        (protected by @inner_lock)
> > + * @refs_by_desc:         rbtree of refs ordered by ref->desc
> > + *                        (protected by @outer_lock)
> > + * @refs_by_node:         rbtree of refs ordered by ref->node
> > + *                        (protected by @outer_lock)
> > + * @waiting_threads:      threads currently waiting for proc work
> > + *                        (protected by @inner_lock)
> > + * @pid                   PID of group_leader of process
> > + *                        (invariant after initialized)
> > + * @tsk                   task_struct for group_leader of process
> > + *                        (invariant after initialized)
> > + * @deferred_work_node:   element for binder_deferred_list
> > + *                        (protected by binder_deferred_lock)
> > + * @deferred_work:        bitmap of deferred work to perform
> > + *                        (protected by binder_deferred_lock)
> > + * @is_dead:              process is dead and awaiting free
> > + *                        when outstanding transactions are cleaned up
> > + *                        (protected by @inner_lock)
> > + * @todo:                 list of work for this process
> > + *                        (protected by @inner_lock)
> > + * @stats:                per-process binder statistics
> > + *                        (atomics, no lock needed)
> > + * @delivered_death:      list of delivered death notification
> > + *                        (protected by @inner_lock)
> > + * @max_threads:          cap on number of binder threads
> > + *                        (protected by @inner_lock)
> > + * @requested_threads:    number of binder threads requested but not
> > + *                        yet started. In current implementation, can
> > + *                        only be 0 or 1.
> > + *                        (protected by @inner_lock)
> > + * @requested_threads_started: number binder threads started
> > + *                        (protected by @inner_lock)
> > + * @tmp_ref:              temporary reference to indicate proc is in use
> > + *                        (protected by @inner_lock)
> > + * @default_priority:     default scheduler priority
> > + *                        (invariant after initialized)
> > + * @debugfs_entry:        debugfs node
> > + * @alloc:                binder allocator bookkeeping
> > + * @context:              binder_context for this proc
> > + *                        (invariant after initialized)
> > + * @inner_lock:           can nest under outer_lock and/or node lock
> > + * @outer_lock:           no nesting under innor or node lock
> > + *                        Lock order: 1) outer, 2) node, 3) inner
> > + * @binderfs_entry:       process-specific binderfs log file
> > + *
> > + * Bookkeeping structure for binder processes
> > + */
> > +struct binder_proc {
> > +       struct hlist_node proc_node;
> > +       struct rb_root threads;
> > +       struct rb_root nodes;
> > +       struct rb_root refs_by_desc;
> > +       struct rb_root refs_by_node;
> > +       struct list_head waiting_threads;
> > +       int pid;
> > +       struct task_struct *tsk;
> > +       struct hlist_node deferred_work_node;
> > +       int deferred_work;
> > +       bool is_dead;
> > +
> > +       struct list_head todo;
> > +       struct binder_stats stats;
> > +       struct list_head delivered_death;
> > +       int max_threads;
> > +       int requested_threads;
> > +       int requested_threads_started;
> > +       int tmp_ref;
> > +       long default_priority;
> > +       struct dentry *debugfs_entry;
> > +       struct binder_alloc alloc;
> > +       struct binder_context *context;
> > +       spinlock_t inner_lock;
> > +       spinlock_t outer_lock;
> > +       struct dentry *binderfs_entry;
> > +};
> > +
> > +/**
> > + * struct binder_thread - binder thread bookkeeping
> > + * @proc:                 binder process for this thread
> > + *                        (invariant after initialization)
> > + * @rb_node:              element for proc->threads rbtree
> > + *                        (protected by @proc->inner_lock)
> > + * @waiting_thread_node:  element for @proc->waiting_threads list
> > + *                        (protected by @proc->inner_lock)
> > + * @pid:                  PID for this thread
> > + *                        (invariant after initialization)
> > + * @looper:               bitmap of looping state
> > + *                        (only accessed by this thread)
> > + * @looper_needs_return:  looping thread needs to exit driver
> > + *                        (no lock needed)
> > + * @transaction_stack:    stack of in-progress transactions for this thread
> > + *                        (protected by @proc->inner_lock)
> > + * @todo:                 list of work to do for this thread
> > + *                        (protected by @proc->inner_lock)
> > + * @process_todo:         whether work in @todo should be processed
> > + *                        (protected by @proc->inner_lock)
> > + * @return_error:         transaction errors reported by this thread
> > + *                        (only accessed by this thread)
> > + * @reply_error:          transaction errors reported by target thread
> > + *                        (protected by @proc->inner_lock)
> > + * @wait:                 wait queue for thread work
> > + * @stats:                per-thread statistics
> > + *                        (atomics, no lock needed)
> > + * @tmp_ref:              temporary reference to indicate thread is in use
> > + *                        (atomic since @proc->inner_lock cannot
> > + *                        always be acquired)
> > + * @is_dead:              thread is dead and awaiting free
> > + *                        when outstanding transactions are cleaned up
> > + *                        (protected by @proc->inner_lock)
> > + *
> > + * Bookkeeping structure for binder threads.
> > + */
> > +struct binder_thread {
> > +       struct binder_proc *proc;
> > +       struct rb_node rb_node;
> > +       struct list_head waiting_thread_node;
> > +       int pid;
> > +       int looper;              /* only modified by this thread */
> > +       bool looper_need_return; /* can be written by other thread */
> > +       struct binder_transaction *transaction_stack;
> > +       struct list_head todo;
> > +       bool process_todo;
> > +       struct binder_error return_error;
> > +       struct binder_error reply_error;
> > +       wait_queue_head_t wait;
> > +       struct binder_stats stats;
> > +       atomic_t tmp_ref;
> > +       bool is_dead;
> > +};
> > +
> > +struct binder_transaction {
> > +       int debug_id;
> > +       struct binder_work work;
> > +       struct binder_thread *from;
> > +       struct binder_transaction *from_parent;
> > +       struct binder_proc *to_proc;
> > +       struct binder_thread *to_thread;
> > +       struct binder_transaction *to_parent;
> > +       unsigned need_reply:1;
> > +       /* unsigned is_dead:1; */       /* not used at the moment */
> > +
> > +       struct binder_buffer *buffer;
> > +       unsigned int    code;
> > +       unsigned int    flags;
> > +       long    priority;
> > +       long    saved_priority;
> > +       kuid_t  sender_euid;
> > +       struct list_head fd_fixups;
> > +       binder_uintptr_t security_ctx;
> > +       /**
> > +        * @lock:  protects @from, @to_proc, and @to_thread
> > +        *
> > +        * @from, @to_proc, and @to_thread can be set to NULL
> > +        * during thread teardown
> > +        */
> > +       spinlock_t lock;
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +       struct timespec timestamp;
> > +       struct timeval tv;
> > +#endif
> > +};
> > +
> >  extern struct binder_transaction_log binder_transaction_log;
> >  extern struct binder_transaction_log binder_transaction_log_failed;
> > +
> > +extern void set_binder_update_info_cb(void (*fn)(struct binder_transaction *t,
> > +                               struct binder_transaction_log_entry *e));
> > +extern void set_print_transaction_ext_cb(void (*fn)(struct seq_file *m,
> > +                                       struct binder_transaction *t));
> >  #endif /* _LINUX_BINDER_INTERNAL_H */
> > diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
> > new file mode 100644
> > index 0000000..c9626f5
> > --- /dev/null
> > +++ b/drivers/android/binder_latency_tracer.c
> > @@ -0,0 +1,100 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2019 MediaTek Inc.
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <uapi/linux/android/binder.h>
> > +#include "binder_alloc.h"
> > +#include "binder_internal.h"
> > +#include "binder_trace.h"
> > +
> > +/*
> > + * probe_binder_free_transaction - Output info of a delay transaction
> > + * @t:          pointer to the over-time transaction
> > + */
> > +void probe_binder_free_transaction(void *ignore, struct binder_transaction *t)
> > +{
> > +       struct rtc_time tm;
> > +       struct timespec *startime;
> > +       struct timespec cur, sub_t;
> > +
> > +       ktime_get_ts(&cur);
> > +       startime = &t->timestamp;
> > +       sub_t = timespec_sub(cur, *startime);
> > +
> > +       /* if transaction time is over than 2 sec,
> > +        * show timeout warning log.
> > +        */
> > +       if (sub_t.tv_sec < 2)
> > +               return;
> > +
> > +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> > +
> > +       spin_lock(&t->lock);
> > +       pr_info_ratelimited("%d: from %d:%d to %d:%d",
> > +                       t->debug_id,
> > +                       t->from ? t->from->proc->pid : 0,
> > +                       t->from ? t->from->pid : 0,
> > +                       t->to_proc ? t->to_proc->pid : 0,
> > +                       t->to_thread ? t->to_thread->pid : 0);
> > +       spin_unlock(&t->lock);
> > +
> > +       pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> > +                       (unsigned int)sub_t.tv_sec,
> > +                       (sub_t.tv_nsec / NSEC_PER_MSEC),
> > +                       t->code,
> > +                       (unsigned long)startime->tv_sec,
> > +                       (startime->tv_nsec / NSEC_PER_MSEC),
> > +                       (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > +                       tm.tm_hour, tm.tm_min, tm.tm_sec,
> > +                       (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > +}
> > +
> > +static void binder_update_info_cb(struct binder_transaction *t,
> > +                          struct binder_transaction_log_entry *e)
> > +{
> > +       ktime_get_ts(&e->timestamp);
> > +       do_gettimeofday(&e->tv);
> > +       e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
> > +       memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
> > +       memcpy(&t->tv, &e->tv, sizeof(struct timeval));
> > +}
> > +
> > +static void print_binder_transaction_ext(struct seq_file *m,
> > +                                        struct binder_transaction *t)
> > +{
> > +       struct rtc_time tm;
> > +
> > +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> > +       seq_printf(m,
> > +                  " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
> > +                  (unsigned long)t->timestamp.tv_sec,
> > +                  (t->timestamp.tv_nsec / NSEC_PER_USEC),
> > +                  (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > +                  tm.tm_hour, tm.tm_min, tm.tm_sec,
> > +                  (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > +
> > +}
> > +
> > +static int __init init_binder_latency_tracer(void)
> > +{
> > +       register_trace_binder_free_transaction(
> > +                       probe_binder_free_transaction, NULL);
> > +
> > +       set_binder_update_info_cb(binder_update_info_cb);
> > +       set_print_transaction_ext_cb(print_binder_transaction_ext);
> > +       return 0;
> > +}
> > +
> > +static void exit_binder_latency_tracer(void)
> > +{
> > +       unregister_trace_binder_free_transaction(
> > +                       probe_binder_free_transaction, NULL);
> > +}
> > +
> > +module_init(init_binder_latency_tracer);
> > +module_exit(exit_binder_latency_tracer);
> > +
> > +MODULE_LICENSE("GPL v2");
> > +
> > diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> > index 6731c3c..c7c76c1 100644
> > --- a/drivers/android/binder_trace.h
> > +++ b/drivers/android/binder_trace.h
> > @@ -95,6 +95,42 @@
> >                   __entry->thread_todo)
> >  );
> >
> > +TRACE_EVENT(binder_free_transaction,
> > +       TP_PROTO(struct binder_transaction *t),
> > +       TP_ARGS(t),
> > +       TP_STRUCT__entry(
> > +               __field(int, debug_id)
> > +               __field(int, from_proc)
> > +               __field(int, from_thread)
> > +               __field(int, to_proc)
> > +               __field(int, to_thread)
> > +               __field(unsigned int, code)
> > +               __field(unsigned int, flags)
> > +               __field(unsigned long, start_sec)
> > +               __field(unsigned long, start_nsec)
> > +       ),
> > +       TP_fast_assign(
> > +               __entry->debug_id = t->debug_id;
> > +               __entry->from_proc = t->from ? t->from->proc->pid : 0;
> > +               __entry->from_thread = t->from ? t->from->pid : 0;
> > +               __entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
> > +               __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
> > +               __entry->code = t->code;
> > +               __entry->flags = t->flags;
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +               __entry->start_sec = t->timestamp.tv_sec;
> > +               __entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
> > +#else
> > +               __entry->start_sec = 0;
> > +               __entry->start_nsec = 0;
> > +#endif
> > +       ),
> > +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
> > +                 __entry->debug_id, __entry->from_proc, __entry->from_thread,
> > +                 __entry->to_proc, __entry->to_thread, __entry->code,
> > +                 __entry->flags, __entry->start_sec, __entry->start_nsec)
> > +);
> > +
> >  TRACE_EVENT(binder_transaction,
> >         TP_PROTO(bool reply, struct binder_transaction *t,
> >                  struct binder_node *target_node),
> > --
> > 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* binder: transaction latency tracking for user build
  2020-04-15  5:37                 ` [PATCH v2 1/1] " Frankie Chang
  2020-04-15 22:25                   ` Todd Kjos
@ 2020-04-30  8:13                   ` Frankie Chang
  2020-04-30  8:13                     ` [PATCH v3 1/1] " Frankie Chang
  1 sibling, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-04-30  8:13 UTC (permalink / raw)
  To: Todd Kjos, Joel Fernandes, Greg Kroah-Hartman
  Cc: Todd Kjos, wsd_upstream, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Martijn Coenen, Christian Brauner


Frankie Chang (1):
  binder: transaction latency tracking for user build

 drivers/android/Kconfig                 |    8 +
 drivers/android/Makefile                |    1 +
 drivers/android/binder.c                |  408 +-----------------------------
 drivers/android/binder_internal.h       |  416 +++++++++++++++++++++++++++++++
 drivers/android/binder_latency_tracer.c |  105 ++++++++
 drivers/android/binder_trace.h          |   49 ++++
 6 files changed, 583 insertions(+), 404 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v3 1/1] binder: transaction latency tracking for user build
  2020-04-30  8:13                   ` Frankie Chang
@ 2020-04-30  8:13                     ` Frankie Chang
  2020-04-30  8:50                       ` Greg Kroah-Hartman
  2020-04-30  8:51                       ` Greg Kroah-Hartman
  0 siblings, 2 replies; 72+ messages in thread
From: Frankie Chang @ 2020-04-30  8:13 UTC (permalink / raw)
  To: Todd Kjos, Joel Fernandes, Greg Kroah-Hartman
  Cc: Todd Kjos, wsd_upstream, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Frankie Chang, Martijn Coenen,
	Christian Brauner

Record start/end timestamp for binder transaction.
When transaction is completed or transaction is free,
it would be checked if transaction latency over threshold (2 sec),
if yes, printing related information for tracing.

/* Implement details */
- Add tracepoint/trace at free transaction.
  Since the original trace_binder_transaction_received cannot
  precisely present the real finished time of transaction, adding a
  trace_binder_free_transaction at the point of free transaction
  may be more close to it.

- Add latency tracer module to monitor slow transaction.
  The trace_binder_free_transaction would not be enabled
  by default. Monitoring which transaction is too slow to
  cause some of exceptions is important. So we hook the
  tracepoint to call the monitor function.

- Move some struct from core file to header file.
  Need some struct defined in core file in latency trace module
  In addition, moving all structs to header file makes module
  more extendable, and make all these strcuts to be defined
  in the same file.

Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/Kconfig                 |    8 +
 drivers/android/Makefile                |    1 +
 drivers/android/binder.c                |  408 +-----------------------------
 drivers/android/binder_internal.h       |  416 +++++++++++++++++++++++++++++++
 drivers/android/binder_latency_tracer.c |  105 ++++++++
 drivers/android/binder_trace.h          |   49 ++++
 6 files changed, 583 insertions(+), 404 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 6fdf2ab..7ba80eb 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
 	  exhaustively with combinations of various buffer sizes and
 	  alignments.
 
+config BINDER_USER_TRACKING
+	bool "Android Binder transaction tracking"
+	help
+	  Used for track abnormal binder transaction which is over 2 seconds,
+	  when the transaction is done or be free, this transaction would be
+	  checked whether it executed overtime.
+	  If yes, printing out the detail info about it.
+
 endif # if ANDROID
 
 endmenu
diff --git a/drivers/android/Makefile b/drivers/android/Makefile
index c9d3d0c9..552e8ac 100644
--- a/drivers/android/Makefile
+++ b/drivers/android/Makefile
@@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
 obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
 obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
 obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
+obj-$(CONFIG_BINDER_USER_TRACKING)	+= binder_latency_tracer.o
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index a6b2082..b89d75a 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -160,24 +160,6 @@ static int binder_set_stop_on_user_error(const char *val,
 #define to_binder_fd_array_object(hdr) \
 	container_of(hdr, struct binder_fd_array_object, hdr)
 
-enum binder_stat_types {
-	BINDER_STAT_PROC,
-	BINDER_STAT_THREAD,
-	BINDER_STAT_NODE,
-	BINDER_STAT_REF,
-	BINDER_STAT_DEATH,
-	BINDER_STAT_TRANSACTION,
-	BINDER_STAT_TRANSACTION_COMPLETE,
-	BINDER_STAT_COUNT
-};
-
-struct binder_stats {
-	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
-	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
-	atomic_t obj_created[BINDER_STAT_COUNT];
-	atomic_t obj_deleted[BINDER_STAT_COUNT];
-};
-
 static struct binder_stats binder_stats;
 
 static inline void binder_stats_deleted(enum binder_stat_types type)
@@ -213,278 +195,11 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
 	return e;
 }
 
-/**
- * struct binder_work - work enqueued on a worklist
- * @entry:             node enqueued on list
- * @type:              type of work to be performed
- *
- * There are separate work lists for proc, thread, and node (async).
- */
-struct binder_work {
-	struct list_head entry;
-
-	enum {
-		BINDER_WORK_TRANSACTION = 1,
-		BINDER_WORK_TRANSACTION_COMPLETE,
-		BINDER_WORK_RETURN_ERROR,
-		BINDER_WORK_NODE,
-		BINDER_WORK_DEAD_BINDER,
-		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
-		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
-	} type;
-};
-
-struct binder_error {
-	struct binder_work work;
-	uint32_t cmd;
-};
-
-/**
- * struct binder_node - binder node bookkeeping
- * @debug_id:             unique ID for debugging
- *                        (invariant after initialized)
- * @lock:                 lock for node fields
- * @work:                 worklist element for node work
- *                        (protected by @proc->inner_lock)
- * @rb_node:              element for proc->nodes tree
- *                        (protected by @proc->inner_lock)
- * @dead_node:            element for binder_dead_nodes list
- *                        (protected by binder_dead_nodes_lock)
- * @proc:                 binder_proc that owns this node
- *                        (invariant after initialized)
- * @refs:                 list of references on this node
- *                        (protected by @lock)
- * @internal_strong_refs: used to take strong references when
- *                        initiating a transaction
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_weak_refs:      weak user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_strong_refs:    strong user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @tmp_refs:             temporary kernel refs
- *                        (protected by @proc->inner_lock while @proc
- *                        is valid, and by binder_dead_nodes_lock
- *                        if @proc is NULL. During inc/dec and node release
- *                        it is also protected by @lock to provide safety
- *                        as the node dies and @proc becomes NULL)
- * @ptr:                  userspace pointer for node
- *                        (invariant, no lock needed)
- * @cookie:               userspace cookie for node
- *                        (invariant, no lock needed)
- * @has_strong_ref:       userspace notified of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_strong_ref:   userspace has acked notification of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_weak_ref:         userspace notified of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_weak_ref:     userspace has acked notification of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_async_transaction: async transaction to node in progress
- *                        (protected by @lock)
- * @accept_fds:           file descriptor operations supported for node
- *                        (invariant after initialized)
- * @min_priority:         minimum scheduling priority
- *                        (invariant after initialized)
- * @txn_security_ctx:     require sender's security context
- *                        (invariant after initialized)
- * @async_todo:           list of async work items
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder nodes.
- */
-struct binder_node {
-	int debug_id;
-	spinlock_t lock;
-	struct binder_work work;
-	union {
-		struct rb_node rb_node;
-		struct hlist_node dead_node;
-	};
-	struct binder_proc *proc;
-	struct hlist_head refs;
-	int internal_strong_refs;
-	int local_weak_refs;
-	int local_strong_refs;
-	int tmp_refs;
-	binder_uintptr_t ptr;
-	binder_uintptr_t cookie;
-	struct {
-		/*
-		 * bitfield elements protected by
-		 * proc inner_lock
-		 */
-		u8 has_strong_ref:1;
-		u8 pending_strong_ref:1;
-		u8 has_weak_ref:1;
-		u8 pending_weak_ref:1;
-	};
-	struct {
-		/*
-		 * invariant after initialization
-		 */
-		u8 accept_fds:1;
-		u8 txn_security_ctx:1;
-		u8 min_priority;
-	};
-	bool has_async_transaction;
-	struct list_head async_todo;
-};
-
-struct binder_ref_death {
-	/**
-	 * @work: worklist element for death notifications
-	 *        (protected by inner_lock of the proc that
-	 *        this ref belongs to)
-	 */
-	struct binder_work work;
-	binder_uintptr_t cookie;
-};
-
-/**
- * struct binder_ref_data - binder_ref counts and id
- * @debug_id:        unique ID for the ref
- * @desc:            unique userspace handle for ref
- * @strong:          strong ref count (debugging only if not locked)
- * @weak:            weak ref count (debugging only if not locked)
- *
- * Structure to hold ref count and ref id information. Since
- * the actual ref can only be accessed with a lock, this structure
- * is used to return information about the ref to callers of
- * ref inc/dec functions.
- */
-struct binder_ref_data {
-	int debug_id;
-	uint32_t desc;
-	int strong;
-	int weak;
-};
-
-/**
- * struct binder_ref - struct to track references on nodes
- * @data:        binder_ref_data containing id, handle, and current refcounts
- * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
- * @rb_node_node: node for lookup by @node in proc's rb_tree
- * @node_entry:  list entry for node->refs list in target node
- *               (protected by @node->lock)
- * @proc:        binder_proc containing ref
- * @node:        binder_node of target node. When cleaning up a
- *               ref for deletion in binder_cleanup_ref, a non-NULL
- *               @node indicates the node must be freed
- * @death:       pointer to death notification (ref_death) if requested
- *               (protected by @node->lock)
- *
- * Structure to track references from procA to target node (on procB). This
- * structure is unsafe to access without holding @proc->outer_lock.
- */
-struct binder_ref {
-	/* Lookups needed: */
-	/*   node + proc => ref (transaction) */
-	/*   desc + proc => ref (transaction, inc/dec ref) */
-	/*   node => refs + procs (proc exit) */
-	struct binder_ref_data data;
-	struct rb_node rb_node_desc;
-	struct rb_node rb_node_node;
-	struct hlist_node node_entry;
-	struct binder_proc *proc;
-	struct binder_node *node;
-	struct binder_ref_death *death;
-};
-
 enum binder_deferred_state {
 	BINDER_DEFERRED_FLUSH        = 0x01,
 	BINDER_DEFERRED_RELEASE      = 0x02,
 };
 
-/**
- * struct binder_proc - binder process bookkeeping
- * @proc_node:            element for binder_procs list
- * @threads:              rbtree of binder_threads in this proc
- *                        (protected by @inner_lock)
- * @nodes:                rbtree of binder nodes associated with
- *                        this proc ordered by node->ptr
- *                        (protected by @inner_lock)
- * @refs_by_desc:         rbtree of refs ordered by ref->desc
- *                        (protected by @outer_lock)
- * @refs_by_node:         rbtree of refs ordered by ref->node
- *                        (protected by @outer_lock)
- * @waiting_threads:      threads currently waiting for proc work
- *                        (protected by @inner_lock)
- * @pid                   PID of group_leader of process
- *                        (invariant after initialized)
- * @tsk                   task_struct for group_leader of process
- *                        (invariant after initialized)
- * @deferred_work_node:   element for binder_deferred_list
- *                        (protected by binder_deferred_lock)
- * @deferred_work:        bitmap of deferred work to perform
- *                        (protected by binder_deferred_lock)
- * @is_dead:              process is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @inner_lock)
- * @todo:                 list of work for this process
- *                        (protected by @inner_lock)
- * @stats:                per-process binder statistics
- *                        (atomics, no lock needed)
- * @delivered_death:      list of delivered death notification
- *                        (protected by @inner_lock)
- * @max_threads:          cap on number of binder threads
- *                        (protected by @inner_lock)
- * @requested_threads:    number of binder threads requested but not
- *                        yet started. In current implementation, can
- *                        only be 0 or 1.
- *                        (protected by @inner_lock)
- * @requested_threads_started: number binder threads started
- *                        (protected by @inner_lock)
- * @tmp_ref:              temporary reference to indicate proc is in use
- *                        (protected by @inner_lock)
- * @default_priority:     default scheduler priority
- *                        (invariant after initialized)
- * @debugfs_entry:        debugfs node
- * @alloc:                binder allocator bookkeeping
- * @context:              binder_context for this proc
- *                        (invariant after initialized)
- * @inner_lock:           can nest under outer_lock and/or node lock
- * @outer_lock:           no nesting under innor or node lock
- *                        Lock order: 1) outer, 2) node, 3) inner
- * @binderfs_entry:       process-specific binderfs log file
- *
- * Bookkeeping structure for binder processes
- */
-struct binder_proc {
-	struct hlist_node proc_node;
-	struct rb_root threads;
-	struct rb_root nodes;
-	struct rb_root refs_by_desc;
-	struct rb_root refs_by_node;
-	struct list_head waiting_threads;
-	int pid;
-	struct task_struct *tsk;
-	struct hlist_node deferred_work_node;
-	int deferred_work;
-	bool is_dead;
-
-	struct list_head todo;
-	struct binder_stats stats;
-	struct list_head delivered_death;
-	int max_threads;
-	int requested_threads;
-	int requested_threads_started;
-	int tmp_ref;
-	long default_priority;
-	struct dentry *debugfs_entry;
-	struct binder_alloc alloc;
-	struct binder_context *context;
-	spinlock_t inner_lock;
-	spinlock_t outer_lock;
-	struct dentry *binderfs_entry;
-};
-
 enum {
 	BINDER_LOOPER_STATE_REGISTERED  = 0x01,
 	BINDER_LOOPER_STATE_ENTERED     = 0x02,
@@ -495,125 +210,6 @@ enum {
 };
 
 /**
- * struct binder_thread - binder thread bookkeeping
- * @proc:                 binder process for this thread
- *                        (invariant after initialization)
- * @rb_node:              element for proc->threads rbtree
- *                        (protected by @proc->inner_lock)
- * @waiting_thread_node:  element for @proc->waiting_threads list
- *                        (protected by @proc->inner_lock)
- * @pid:                  PID for this thread
- *                        (invariant after initialization)
- * @looper:               bitmap of looping state
- *                        (only accessed by this thread)
- * @looper_needs_return:  looping thread needs to exit driver
- *                        (no lock needed)
- * @transaction_stack:    stack of in-progress transactions for this thread
- *                        (protected by @proc->inner_lock)
- * @todo:                 list of work to do for this thread
- *                        (protected by @proc->inner_lock)
- * @process_todo:         whether work in @todo should be processed
- *                        (protected by @proc->inner_lock)
- * @return_error:         transaction errors reported by this thread
- *                        (only accessed by this thread)
- * @reply_error:          transaction errors reported by target thread
- *                        (protected by @proc->inner_lock)
- * @wait:                 wait queue for thread work
- * @stats:                per-thread statistics
- *                        (atomics, no lock needed)
- * @tmp_ref:              temporary reference to indicate thread is in use
- *                        (atomic since @proc->inner_lock cannot
- *                        always be acquired)
- * @is_dead:              thread is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder threads.
- */
-struct binder_thread {
-	struct binder_proc *proc;
-	struct rb_node rb_node;
-	struct list_head waiting_thread_node;
-	int pid;
-	int looper;              /* only modified by this thread */
-	bool looper_need_return; /* can be written by other thread */
-	struct binder_transaction *transaction_stack;
-	struct list_head todo;
-	bool process_todo;
-	struct binder_error return_error;
-	struct binder_error reply_error;
-	wait_queue_head_t wait;
-	struct binder_stats stats;
-	atomic_t tmp_ref;
-	bool is_dead;
-};
-
-/**
- * struct binder_txn_fd_fixup - transaction fd fixup list element
- * @fixup_entry:          list entry
- * @file:                 struct file to be associated with new fd
- * @offset:               offset in buffer data to this fixup
- *
- * List element for fd fixups in a transaction. Since file
- * descriptors need to be allocated in the context of the
- * target process, we pass each fd to be processed in this
- * struct.
- */
-struct binder_txn_fd_fixup {
-	struct list_head fixup_entry;
-	struct file *file;
-	size_t offset;
-};
-
-struct binder_transaction {
-	int debug_id;
-	struct binder_work work;
-	struct binder_thread *from;
-	struct binder_transaction *from_parent;
-	struct binder_proc *to_proc;
-	struct binder_thread *to_thread;
-	struct binder_transaction *to_parent;
-	unsigned need_reply:1;
-	/* unsigned is_dead:1; */	/* not used at the moment */
-
-	struct binder_buffer *buffer;
-	unsigned int	code;
-	unsigned int	flags;
-	long	priority;
-	long	saved_priority;
-	kuid_t	sender_euid;
-	struct list_head fd_fixups;
-	binder_uintptr_t security_ctx;
-	/**
-	 * @lock:  protects @from, @to_proc, and @to_thread
-	 *
-	 * @from, @to_proc, and @to_thread can be set to NULL
-	 * during thread teardown
-	 */
-	spinlock_t lock;
-};
-
-/**
- * struct binder_object - union of flat binder object types
- * @hdr:   generic object header
- * @fbo:   binder object (nodes and refs)
- * @fdo:   file descriptor object
- * @bbo:   binder buffer pointer
- * @fdao:  file descriptor array
- *
- * Used for type-independent object copies
- */
-struct binder_object {
-	union {
-		struct binder_object_header hdr;
-		struct flat_binder_object fbo;
-		struct binder_fd_object fdo;
-		struct binder_buffer_object bbo;
-		struct binder_fd_array_object fdao;
-	};
-};
-
-/**
  * binder_proc_lock() - Acquire outer lock for given binder_proc
  * @proc:         struct binder_proc to acquire
  *
@@ -1927,6 +1523,7 @@ static void binder_free_transaction(struct binder_transaction *t)
 	 * If the transaction has no target_proc, then
 	 * t->buffer->transaction has already been cleared.
 	 */
+	trace_binder_free_transaction(t);
 	binder_free_txn_fixups(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
@@ -3060,6 +2657,7 @@ static void binder_transaction(struct binder_proc *proc,
 		return_error_line = __LINE__;
 		goto err_alloc_t_failed;
 	}
+	trace_binder_update_info(t, e);
 	INIT_LIST_HEAD(&t->fd_fixups);
 	binder_stats_created(BINDER_STAT_TRANSACTION);
 	spin_lock_init(&t->lock);
@@ -3498,6 +3096,7 @@ static void binder_transaction(struct binder_proc *proc,
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 err_alloc_tcomplete_failed:
+	trace_binder_free_transaction(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
 err_alloc_t_failed:
@@ -5547,6 +5146,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
 		   t->to_thread ? t->to_thread->pid : 0,
 		   t->code, t->flags, t->priority, t->need_reply);
 	spin_unlock(&t->lock);
+	trace_print_binder_transaction_ext(m, t);
 
 	if (proc != to_proc) {
 		/*
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index ae99109..24d7beb 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -12,6 +12,11 @@
 #include <linux/types.h>
 #include <linux/uidgid.h>
 
+#ifdef CONFIG_BINDER_USER_TRACKING
+#include <linux/rtc.h>
+#include <linux/time.h>
+#endif
+
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
 	struct mutex context_mgr_node_lock;
@@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
 	uint32_t return_error;
 	uint32_t return_error_param;
 	char context_name[BINDERFS_MAX_NAME + 1];
+#ifdef CONFIG_BINDER_USER_TRACKING
+	struct timespec timestamp;
+	struct timeval tv;
+#endif
 };
 
 struct binder_transaction_log {
@@ -139,6 +148,413 @@ struct binder_transaction_log {
 	struct binder_transaction_log_entry entry[32];
 };
 
+enum binder_stat_types {
+	BINDER_STAT_PROC,
+	BINDER_STAT_THREAD,
+	BINDER_STAT_NODE,
+	BINDER_STAT_REF,
+	BINDER_STAT_DEATH,
+	BINDER_STAT_TRANSACTION,
+	BINDER_STAT_TRANSACTION_COMPLETE,
+	BINDER_STAT_COUNT
+};
+
+struct binder_stats {
+	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
+	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
+	atomic_t obj_created[BINDER_STAT_COUNT];
+	atomic_t obj_deleted[BINDER_STAT_COUNT];
+};
+
+/**
+ * struct binder_work - work enqueued on a worklist
+ * @entry:             node enqueued on list
+ * @type:              type of work to be performed
+ *
+ * There are separate work lists for proc, thread, and node (async).
+ */
+struct binder_work {
+	struct list_head entry;
+
+	enum {
+		BINDER_WORK_TRANSACTION = 1,
+		BINDER_WORK_TRANSACTION_COMPLETE,
+		BINDER_WORK_RETURN_ERROR,
+		BINDER_WORK_NODE,
+		BINDER_WORK_DEAD_BINDER,
+		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
+		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
+	} type;
+};
+
+struct binder_error {
+	struct binder_work work;
+	uint32_t cmd;
+};
+
+/* struct binder_node - binder node bookkeeping
+ * @debug_id:             unique ID for debugging
+ *                        (invariant after initialized)
+ * @lock:                 lock for node fields
+ * @work:                 worklist element for node work
+ *                        (protected by @proc->inner_lock)
+ * @rb_node:              element for proc->nodes tree
+ *                        (protected by @proc->inner_lock)
+ * @dead_node:            element for binder_dead_nodes list
+ *                        (protected by binder_dead_nodes_lock)
+ * @proc:                 binder_proc that owns this node
+ *                        (invariant after initialized)
+ * @refs:                 list of references on this node
+ *                        (protected by @lock)
+ * @internal_strong_refs: used to take strong references when
+ *                        initiating a transaction
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_weak_refs:      weak user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_strong_refs:    strong user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @tmp_refs:             temporary kernel refs
+ *                        (protected by @proc->inner_lock while @proc
+ *                        is valid, and by binder_dead_nodes_lock
+ *                        if @proc is NULL. During inc/dec and node release
+ *                        it is also protected by @lock to provide safety
+ *                        as the node dies and @proc becomes NULL)
+ * @ptr:                  userspace pointer for node
+ *                        (invariant, no lock needed)
+ * @cookie:               userspace cookie for node
+ *                        (invariant, no lock needed)
+ * @has_strong_ref:       userspace notified of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_strong_ref:   userspace has acked notification of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_weak_ref:         userspace notified of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_weak_ref:     userspace has acked notification of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_async_transaction: async transaction to node in progress
+ *                        (protected by @lock)
+ * @accept_fds:           file descriptor operations supported for node
+ *                        (invariant after initialized)
+ * @min_priority:         minimum scheduling priority
+ *                        (invariant after initialized)
+ * @txn_security_ctx:     require sender's security context
+ *                        (invariant after initialized)
+ * @async_todo:           list of async work items
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder nodes.
+ */
+struct binder_node {
+	int debug_id;
+	spinlock_t lock;
+	struct binder_work work;
+	union {
+		struct rb_node rb_node;
+		struct hlist_node dead_node;
+	};
+	struct binder_proc *proc;
+	struct hlist_head refs;
+	int internal_strong_refs;
+	int local_weak_refs;
+	int local_strong_refs;
+	int tmp_refs;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
+	struct {
+		/*
+		 * bitfield elements protected by
+		 * proc inner_lock
+		 */
+		u8 has_strong_ref:1;
+		u8 pending_strong_ref:1;
+		u8 has_weak_ref:1;
+		u8 pending_weak_ref:1;
+	};
+	struct {
+		/*
+		 * invariant after initialization
+		 */
+		u8 accept_fds:1;
+		u8 txn_security_ctx:1;
+		u8 min_priority;
+	};
+	bool has_async_transaction;
+	struct list_head async_todo;
+};
+
+struct binder_ref_death {
+	/**
+	 * @work: worklist element for death notifications
+	 *        (protected by inner_lock of the proc that
+	 *        this ref belongs to)
+	 */
+	struct binder_work work;
+	binder_uintptr_t cookie;
+};
+
+/**
+ * struct binder_ref_data - binder_ref counts and id
+ * @debug_id:        unique ID for the ref
+ * @desc:            unique userspace handle for ref
+ * @strong:          strong ref count (debugging only if not locked)
+ * @weak:            weak ref count (debugging only if not locked)
+ *
+ * Structure to hold ref count and ref id information. Since
+ * the actual ref can only be accessed with a lock, this structure
+ * is used to return information about the ref to callers of
+ * ref inc/dec functions.
+ */
+struct binder_ref_data {
+	int debug_id;
+	uint32_t desc;
+	int strong;
+	int weak;
+};
+
+/**
+ * struct binder_ref - struct to track references on nodes
+ * @data:        binder_ref_data containing id, handle, and current refcounts
+ * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
+ * @rb_node_node: node for lookup by @node in proc's rb_tree
+ * @node_entry:  list entry for node->refs list in target node
+ *               (protected by @node->lock)
+ * @proc:        binder_proc containing ref
+ * @node:        binder_node of target node. When cleaning up a
+ *               ref for deletion in binder_cleanup_ref, a non-NULL
+ *               @node indicates the node must be freed
+ * @death:       pointer to death notification (ref_death) if requested
+ *               (protected by @node->lock)
+ *
+ * Structure to track references from procA to target node (on procB). This
+ * structure is unsafe to access without holding @proc->outer_lock.
+ */
+struct binder_ref {
+	/* Lookups needed: */
+	/*   node + proc => ref (transaction) */
+	/*   desc + proc => ref (transaction, inc/dec ref) */
+	/*   node => refs + procs (proc exit) */
+	struct binder_ref_data data;
+	struct rb_node rb_node_desc;
+	struct rb_node rb_node_node;
+	struct hlist_node node_entry;
+	struct binder_proc *proc;
+	struct binder_node *node;
+	struct binder_ref_death *death;
+};
+
+/**
+ * struct binder_proc - binder process bookkeeping
+ * @proc_node:            element for binder_procs list
+ * @threads:              rbtree of binder_threads in this proc
+ *                        (protected by @inner_lock)
+ * @nodes:                rbtree of binder nodes associated with
+ *                        this proc ordered by node->ptr
+ *                        (protected by @inner_lock)
+ * @refs_by_desc:         rbtree of refs ordered by ref->desc
+ *                        (protected by @outer_lock)
+ * @refs_by_node:         rbtree of refs ordered by ref->node
+ *                        (protected by @outer_lock)
+ * @waiting_threads:      threads currently waiting for proc work
+ *                        (protected by @inner_lock)
+ * @pid                   PID of group_leader of process
+ *                        (invariant after initialized)
+ * @tsk                   task_struct for group_leader of process
+ *                        (invariant after initialized)
+ * @deferred_work_node:   element for binder_deferred_list
+ *                        (protected by binder_deferred_lock)
+ * @deferred_work:        bitmap of deferred work to perform
+ *                        (protected by binder_deferred_lock)
+ * @is_dead:              process is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @inner_lock)
+ * @todo:                 list of work for this process
+ *                        (protected by @inner_lock)
+ * @stats:                per-process binder statistics
+ *                        (atomics, no lock needed)
+ * @delivered_death:      list of delivered death notification
+ *                        (protected by @inner_lock)
+ * @max_threads:          cap on number of binder threads
+ *                        (protected by @inner_lock)
+ * @requested_threads:    number of binder threads requested but not
+ *                        yet started. In current implementation, can
+ *                        only be 0 or 1.
+ *                        (protected by @inner_lock)
+ * @requested_threads_started: number binder threads started
+ *                        (protected by @inner_lock)
+ * @tmp_ref:              temporary reference to indicate proc is in use
+ *                        (protected by @inner_lock)
+ * @default_priority:     default scheduler priority
+ *                        (invariant after initialized)
+ * @debugfs_entry:        debugfs node
+ * @alloc:                binder allocator bookkeeping
+ * @context:              binder_context for this proc
+ *                        (invariant after initialized)
+ * @inner_lock:           can nest under outer_lock and/or node lock
+ * @outer_lock:           no nesting under innor or node lock
+ *                        Lock order: 1) outer, 2) node, 3) inner
+ * @binderfs_entry:       process-specific binderfs log file
+ *
+ * Bookkeeping structure for binder processes
+ */
+struct binder_proc {
+	struct hlist_node proc_node;
+	struct rb_root threads;
+	struct rb_root nodes;
+	struct rb_root refs_by_desc;
+	struct rb_root refs_by_node;
+	struct list_head waiting_threads;
+	int pid;
+	struct task_struct *tsk;
+	struct hlist_node deferred_work_node;
+	int deferred_work;
+	bool is_dead;
+
+	struct list_head todo;
+	struct binder_stats stats;
+	struct list_head delivered_death;
+	int max_threads;
+	int requested_threads;
+	int requested_threads_started;
+	int tmp_ref;
+	long default_priority;
+	struct dentry *debugfs_entry;
+	struct binder_alloc alloc;
+	struct binder_context *context;
+	spinlock_t inner_lock;
+	spinlock_t outer_lock;
+	struct dentry *binderfs_entry;
+};
+
+/**
+ * struct binder_thread - binder thread bookkeeping
+ * @proc:                 binder process for this thread
+ *                        (invariant after initialization)
+ * @rb_node:              element for proc->threads rbtree
+ *                        (protected by @proc->inner_lock)
+ * @waiting_thread_node:  element for @proc->waiting_threads list
+ *                        (protected by @proc->inner_lock)
+ * @pid:                  PID for this thread
+ *                        (invariant after initialization)
+ * @looper:               bitmap of looping state
+ *                        (only accessed by this thread)
+ * @looper_needs_return:  looping thread needs to exit driver
+ *                        (no lock needed)
+ * @transaction_stack:    stack of in-progress transactions for this thread
+ *                        (protected by @proc->inner_lock)
+ * @todo:                 list of work to do for this thread
+ *                        (protected by @proc->inner_lock)
+ * @process_todo:         whether work in @todo should be processed
+ *                        (protected by @proc->inner_lock)
+ * @return_error:         transaction errors reported by this thread
+ *                        (only accessed by this thread)
+ * @reply_error:          transaction errors reported by target thread
+ *                        (protected by @proc->inner_lock)
+ * @wait:                 wait queue for thread work
+ * @stats:                per-thread statistics
+ *                        (atomics, no lock needed)
+ * @tmp_ref:              temporary reference to indicate thread is in use
+ *                        (atomic since @proc->inner_lock cannot
+ *                        always be acquired)
+ * @is_dead:              thread is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder threads.
+ */
+struct binder_thread {
+	struct binder_proc *proc;
+	struct rb_node rb_node;
+	struct list_head waiting_thread_node;
+	int pid;
+	int looper;              /* only modified by this thread */
+	bool looper_need_return; /* can be written by other thread */
+	struct binder_transaction *transaction_stack;
+	struct list_head todo;
+	bool process_todo;
+	struct binder_error return_error;
+	struct binder_error reply_error;
+	wait_queue_head_t wait;
+	struct binder_stats stats;
+	atomic_t tmp_ref;
+	bool is_dead;
+};
+
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry:          list entry
+ * @file:                 struct file to be associated with new fd
+ * @offset:               offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+	struct list_head fixup_entry;
+	struct file *file;
+	size_t offset;
+};
+
+struct binder_transaction {
+	int debug_id;
+	struct binder_work work;
+	struct binder_thread *from;
+	struct binder_transaction *from_parent;
+	struct binder_proc *to_proc;
+	struct binder_thread *to_thread;
+	struct binder_transaction *to_parent;
+	unsigned need_reply:1;
+	/* unsigned is_dead:1; */       /* not used at the moment */
+
+	struct binder_buffer *buffer;
+	unsigned int    code;
+	unsigned int    flags;
+	long    priority;
+	long    saved_priority;
+	kuid_t  sender_euid;
+	struct list_head fd_fixups;
+	binder_uintptr_t security_ctx;
+	/**
+	 * @lock:  protects @from, @to_proc, and @to_thread
+	 *
+	 * @from, @to_proc, and @to_thread can be set to NULL
+	 * during thread teardown
+	 */
+	spinlock_t lock;
+#ifdef CONFIG_BINDER_USER_TRACKING
+	struct timespec timestamp;
+	struct timeval tv;
+#endif
+};
+
+/**
+ * struct binder_object - union of flat binder object types
+ * @hdr:   generic object header
+ * @fbo:   binder object (nodes and refs)
+ * @fdo:   file descriptor object
+ * @bbo:   binder buffer pointer
+ * @fdao:  file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+	union {
+		struct binder_object_header hdr;
+		struct flat_binder_object fbo;
+		struct binder_fd_object fdo;
+		struct binder_buffer_object bbo;
+		struct binder_fd_array_object fdao;
+	};
+};
+
 extern struct binder_transaction_log binder_transaction_log;
 extern struct binder_transaction_log binder_transaction_log_failed;
 #endif /* _LINUX_BINDER_INTERNAL_H */
diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
new file mode 100644
index 0000000..2fc9d4c
--- /dev/null
+++ b/drivers/android/binder_latency_tracer.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ */
+
+#include <linux/module.h>
+#include <uapi/linux/android/binder.h>
+#include "binder_alloc.h"
+#include "binder_internal.h"
+#include "binder_trace.h"
+
+/*
+ * probe_binder_free_transaction - Output info of a delay transaction
+ * @t:          pointer to the over-time transaction
+ */
+void probe_binder_free_transaction(void *ignore, struct binder_transaction *t)
+{
+	struct rtc_time tm;
+	struct timespec *startime;
+	struct timespec cur, sub_t;
+
+	ktime_get_ts(&cur);
+	startime = &t->timestamp;
+	sub_t = timespec_sub(cur, *startime);
+
+	/* if transaction time is over than 2 sec,
+	 * show timeout warning log.
+	 */
+	if (sub_t.tv_sec < 2)
+		return;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+
+	spin_lock(&t->lock);
+	pr_info_ratelimited("%d: from %d:%d to %d:%d",
+			t->debug_id,
+			t->from ? t->from->proc->pid : 0,
+			t->from ? t->from->pid : 0,
+			t->to_proc ? t->to_proc->pid : 0,
+			t->to_thread ? t->to_thread->pid : 0);
+	spin_unlock(&t->lock);
+
+	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
+			(unsigned int)sub_t.tv_sec,
+			(sub_t.tv_nsec / NSEC_PER_MSEC),
+			t->code,
+			(unsigned long)startime->tv_sec,
+			(startime->tv_nsec / NSEC_PER_MSEC),
+			(tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+			tm.tm_hour, tm.tm_min, tm.tm_sec,
+			(unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+
+static void probe_binder_update_info(void *ignore, struct binder_transaction *t,
+			   struct binder_transaction_log_entry *e)
+{
+	ktime_get_ts(&e->timestamp);
+	do_gettimeofday(&e->tv);
+	e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
+	memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
+	memcpy(&t->tv, &e->tv, sizeof(struct timeval));
+}
+
+static void probe_print_binder_transaction_ext(void *ignore, struct seq_file *m,
+					 struct binder_transaction *t)
+{
+	struct rtc_time tm;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+	seq_printf(m,
+		   " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
+		   (unsigned long)t->timestamp.tv_sec,
+		   (t->timestamp.tv_nsec / NSEC_PER_USEC),
+		   (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+		   tm.tm_hour, tm.tm_min, tm.tm_sec,
+		   (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+
+static int __init init_binder_latency_tracer(void)
+{
+	register_trace_binder_free_transaction(
+			probe_binder_free_transaction, NULL);
+	register_trace_binder_update_info(
+			probe_binder_update_info, NULL);
+	register_trace_print_binder_transaction_ext(
+			probe_print_binder_transaction_ext, NULL);
+
+	return 0;
+}
+
+static void exit_binder_latency_tracer(void)
+{
+	unregister_trace_binder_free_transaction(
+			probe_binder_free_transaction, NULL);
+	unregister_trace_binder_update_info(
+			probe_binder_update_info, NULL);
+	unregister_trace_print_binder_transaction_ext(
+			probe_print_binder_transaction_ext, NULL);
+}
+
+module_init(init_binder_latency_tracer);
+module_exit(exit_binder_latency_tracer);
+
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 6731c3c..e0e1f9c 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -18,6 +18,7 @@
 struct binder_ref_data;
 struct binder_thread;
 struct binder_transaction;
+struct binder_transaction_log_entry;
 
 TRACE_EVENT(binder_ioctl,
 	TP_PROTO(unsigned int cmd, unsigned long arg),
@@ -95,6 +96,54 @@
 		  __entry->thread_todo)
 );
 
+DECLARE_TRACE(binder_update_info,
+	TP_PROTO(struct binder_transaction *t,
+		 struct binder_transaction_log_entry *e),
+	TP_ARGS(t, e)
+);
+
+DECLARE_TRACE(print_binder_transaction_ext,
+	TP_PROTO(struct seq_file *m,
+		 struct binder_transaction *t),
+	TP_ARGS(m, t)
+);
+
+TRACE_EVENT(binder_free_transaction,
+	TP_PROTO(struct binder_transaction *t),
+	TP_ARGS(t),
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, from_proc)
+		__field(int, from_thread)
+		__field(int, to_proc)
+		__field(int, to_thread)
+		__field(unsigned int, code)
+		__field(unsigned int, flags)
+		__field(unsigned long, start_sec)
+		__field(unsigned long, start_nsec)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->from_proc = t->from ? t->from->proc->pid : 0;
+		__entry->from_thread = t->from ? t->from->pid : 0;
+		__entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
+		__entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
+		__entry->code = t->code;
+		__entry->flags = t->flags;
+#ifdef CONFIG_BINDER_USER_TRACKING
+		__entry->start_sec = t->timestamp.tv_sec;
+		__entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
+#else
+		__entry->start_sec = 0;
+		__entry->start_nsec = 0;
+#endif
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
+		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
+		  __entry->to_proc, __entry->to_thread, __entry->code,
+		  __entry->flags, __entry->start_sec, __entry->start_nsec)
+);
+
 TRACE_EVENT(binder_transaction,
 	TP_PROTO(bool reply, struct binder_transaction *t,
 		 struct binder_node *target_node),
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v3 1/1] binder: transaction latency tracking for user build
  2020-04-30  8:13                     ` [PATCH v3 1/1] " Frankie Chang
@ 2020-04-30  8:50                       ` Greg Kroah-Hartman
  2020-04-30  8:51                       ` Greg Kroah-Hartman
  1 sibling, 0 replies; 72+ messages in thread
From: Greg Kroah-Hartman @ 2020-04-30  8:50 UTC (permalink / raw)
  To: Frankie Chang
  Cc: Todd Kjos, wsd_upstream, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Thu, Apr 30, 2020 at 04:13:59PM +0800, Frankie Chang wrote:
> Record start/end timestamp for binder transaction.
> When transaction is completed or transaction is free,
> it would be checked if transaction latency over threshold (2 sec),
> if yes, printing related information for tracing.
> 
> /* Implement details */
> - Add tracepoint/trace at free transaction.
>   Since the original trace_binder_transaction_received cannot
>   precisely present the real finished time of transaction, adding a
>   trace_binder_free_transaction at the point of free transaction
>   may be more close to it.
> 
> - Add latency tracer module to monitor slow transaction.
>   The trace_binder_free_transaction would not be enabled
>   by default. Monitoring which transaction is too slow to
>   cause some of exceptions is important. So we hook the
>   tracepoint to call the monitor function.
> 
> - Move some struct from core file to header file.
>   Need some struct defined in core file in latency trace module
>   In addition, moving all structs to header file makes module
>   more extendable, and make all these strcuts to be defined
>   in the same file.
> 
> Signed-off-by: Frankie Chang <Frankie.Chang@mediatek.com>
> ---
>  drivers/android/Kconfig                 |    8 +
>  drivers/android/Makefile                |    1 +
>  drivers/android/binder.c                |  408 +-----------------------------
>  drivers/android/binder_internal.h       |  416 +++++++++++++++++++++++++++++++
>  drivers/android/binder_latency_tracer.c |  105 ++++++++
>  drivers/android/binder_trace.h          |   49 ++++
>  6 files changed, 583 insertions(+), 404 deletions(-)
>  create mode 100644 drivers/android/binder_latency_tracer.c

What changed from previous versions?  That always needs to go below the
--- line, as is documented in the kernel documentation.

Please fix that up and resend a v4.

thanks,

greg k-h

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v3 1/1] binder: transaction latency tracking for user build
  2020-04-30  8:13                     ` [PATCH v3 1/1] " Frankie Chang
  2020-04-30  8:50                       ` Greg Kroah-Hartman
@ 2020-04-30  8:51                       ` Greg Kroah-Hartman
  2020-05-07  8:10                         ` Frankie Chang
  1 sibling, 1 reply; 72+ messages in thread
From: Greg Kroah-Hartman @ 2020-04-30  8:51 UTC (permalink / raw)
  To: Frankie Chang
  Cc: Todd Kjos, wsd_upstream, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Thu, Apr 30, 2020 at 04:13:59PM +0800, Frankie Chang wrote:
> Record start/end timestamp for binder transaction.
> When transaction is completed or transaction is free,
> it would be checked if transaction latency over threshold (2 sec),
> if yes, printing related information for tracing.
> 
> /* Implement details */
> - Add tracepoint/trace at free transaction.
>   Since the original trace_binder_transaction_received cannot
>   precisely present the real finished time of transaction, adding a
>   trace_binder_free_transaction at the point of free transaction
>   may be more close to it.
> 
> - Add latency tracer module to monitor slow transaction.
>   The trace_binder_free_transaction would not be enabled
>   by default. Monitoring which transaction is too slow to
>   cause some of exceptions is important. So we hook the
>   tracepoint to call the monitor function.
> 
> - Move some struct from core file to header file.
>   Need some struct defined in core file in latency trace module
>   In addition, moving all structs to header file makes module
>   more extendable, and make all these strcuts to be defined
>   in the same file.

Also, this should be split up into a patch series, the first moving
things around, and the rest of the patches each adding a single feature.
As it is, this patch is almost impossible to review.

thanks,

greg k-h

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* binder: transaction latency tracking for user build
  2020-04-30  8:51                       ` Greg Kroah-Hartman
@ 2020-05-07  8:10                         ` Frankie Chang
  2020-05-07  8:10                           ` [PATCH v4 1/3] binder: move structs from core file to header file Frankie Chang
                                             ` (2 more replies)
  0 siblings, 3 replies; 72+ messages in thread
From: Frankie Chang @ 2020-05-07  8:10 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Todd Kjos, Joel Fernandes
  Cc: wsd_upstream, LKML, Arve Hjønnevåg, Jian-Min Liu,
	linux-mediatek, Martijn Coenen, Christian Brauner


Frankie.Chang (3):
  binder: move structs from core file to header file
  binder: add trace at free transaction.
  binder: add transaction latency tracer

 drivers/android/Kconfig                 |   8 +
 drivers/android/Makefile                |   1 +
 drivers/android/binder.c                | 408 +----------------------
 drivers/android/binder_internal.h       | 416 ++++++++++++++++++++++++
 drivers/android/binder_latency_tracer.c | 105 ++++++
 drivers/android/binder_trace.h          |  47 +++
 6 files changed, 581 insertions(+), 404 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v4 1/3] binder: move structs from core file to header file
  2020-05-07  8:10                         ` Frankie Chang
@ 2020-05-07  8:10                           ` Frankie Chang
  2020-05-07  8:10                           ` [PATCH v4 2/3] binder: add trace at free transaction Frankie Chang
  2020-05-07  8:10                           ` [PATCH v4 3/3] binder: add transaction latency tracer Frankie Chang
  2 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-05-07  8:10 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Todd Kjos, Joel Fernandes
  Cc: wsd_upstream, LKML, Arve Hjønnevåg, Jian-Min Liu,
	linux-mediatek, Frankie.Chang, Martijn Coenen, Christian Brauner

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Moving all structs to header file makes module more
extendable, and makes all these structs to be defined
in the same file.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/binder.c          |  404 -------------------------------------
 drivers/android/binder_internal.h |  403 ++++++++++++++++++++++++++++++++++++
 2 files changed, 403 insertions(+), 404 deletions(-)

 Change since v4:
   split up into a patch series

 Change since v3:
   move all structs definition to header file, and make then defined in the same file. 

 Change since v2:
   move some structs definition to header file which needed by transaction latency module.

 Change since v1:
   first patchset

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index a6b2082..1592396 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -160,24 +160,6 @@ static int binder_set_stop_on_user_error(const char *val,
 #define to_binder_fd_array_object(hdr) \
 	container_of(hdr, struct binder_fd_array_object, hdr)
 
-enum binder_stat_types {
-	BINDER_STAT_PROC,
-	BINDER_STAT_THREAD,
-	BINDER_STAT_NODE,
-	BINDER_STAT_REF,
-	BINDER_STAT_DEATH,
-	BINDER_STAT_TRANSACTION,
-	BINDER_STAT_TRANSACTION_COMPLETE,
-	BINDER_STAT_COUNT
-};
-
-struct binder_stats {
-	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
-	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
-	atomic_t obj_created[BINDER_STAT_COUNT];
-	atomic_t obj_deleted[BINDER_STAT_COUNT];
-};
-
 static struct binder_stats binder_stats;
 
 static inline void binder_stats_deleted(enum binder_stat_types type)
@@ -213,278 +195,11 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
 	return e;
 }
 
-/**
- * struct binder_work - work enqueued on a worklist
- * @entry:             node enqueued on list
- * @type:              type of work to be performed
- *
- * There are separate work lists for proc, thread, and node (async).
- */
-struct binder_work {
-	struct list_head entry;
-
-	enum {
-		BINDER_WORK_TRANSACTION = 1,
-		BINDER_WORK_TRANSACTION_COMPLETE,
-		BINDER_WORK_RETURN_ERROR,
-		BINDER_WORK_NODE,
-		BINDER_WORK_DEAD_BINDER,
-		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
-		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
-	} type;
-};
-
-struct binder_error {
-	struct binder_work work;
-	uint32_t cmd;
-};
-
-/**
- * struct binder_node - binder node bookkeeping
- * @debug_id:             unique ID for debugging
- *                        (invariant after initialized)
- * @lock:                 lock for node fields
- * @work:                 worklist element for node work
- *                        (protected by @proc->inner_lock)
- * @rb_node:              element for proc->nodes tree
- *                        (protected by @proc->inner_lock)
- * @dead_node:            element for binder_dead_nodes list
- *                        (protected by binder_dead_nodes_lock)
- * @proc:                 binder_proc that owns this node
- *                        (invariant after initialized)
- * @refs:                 list of references on this node
- *                        (protected by @lock)
- * @internal_strong_refs: used to take strong references when
- *                        initiating a transaction
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_weak_refs:      weak user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_strong_refs:    strong user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @tmp_refs:             temporary kernel refs
- *                        (protected by @proc->inner_lock while @proc
- *                        is valid, and by binder_dead_nodes_lock
- *                        if @proc is NULL. During inc/dec and node release
- *                        it is also protected by @lock to provide safety
- *                        as the node dies and @proc becomes NULL)
- * @ptr:                  userspace pointer for node
- *                        (invariant, no lock needed)
- * @cookie:               userspace cookie for node
- *                        (invariant, no lock needed)
- * @has_strong_ref:       userspace notified of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_strong_ref:   userspace has acked notification of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_weak_ref:         userspace notified of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_weak_ref:     userspace has acked notification of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_async_transaction: async transaction to node in progress
- *                        (protected by @lock)
- * @accept_fds:           file descriptor operations supported for node
- *                        (invariant after initialized)
- * @min_priority:         minimum scheduling priority
- *                        (invariant after initialized)
- * @txn_security_ctx:     require sender's security context
- *                        (invariant after initialized)
- * @async_todo:           list of async work items
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder nodes.
- */
-struct binder_node {
-	int debug_id;
-	spinlock_t lock;
-	struct binder_work work;
-	union {
-		struct rb_node rb_node;
-		struct hlist_node dead_node;
-	};
-	struct binder_proc *proc;
-	struct hlist_head refs;
-	int internal_strong_refs;
-	int local_weak_refs;
-	int local_strong_refs;
-	int tmp_refs;
-	binder_uintptr_t ptr;
-	binder_uintptr_t cookie;
-	struct {
-		/*
-		 * bitfield elements protected by
-		 * proc inner_lock
-		 */
-		u8 has_strong_ref:1;
-		u8 pending_strong_ref:1;
-		u8 has_weak_ref:1;
-		u8 pending_weak_ref:1;
-	};
-	struct {
-		/*
-		 * invariant after initialization
-		 */
-		u8 accept_fds:1;
-		u8 txn_security_ctx:1;
-		u8 min_priority;
-	};
-	bool has_async_transaction;
-	struct list_head async_todo;
-};
-
-struct binder_ref_death {
-	/**
-	 * @work: worklist element for death notifications
-	 *        (protected by inner_lock of the proc that
-	 *        this ref belongs to)
-	 */
-	struct binder_work work;
-	binder_uintptr_t cookie;
-};
-
-/**
- * struct binder_ref_data - binder_ref counts and id
- * @debug_id:        unique ID for the ref
- * @desc:            unique userspace handle for ref
- * @strong:          strong ref count (debugging only if not locked)
- * @weak:            weak ref count (debugging only if not locked)
- *
- * Structure to hold ref count and ref id information. Since
- * the actual ref can only be accessed with a lock, this structure
- * is used to return information about the ref to callers of
- * ref inc/dec functions.
- */
-struct binder_ref_data {
-	int debug_id;
-	uint32_t desc;
-	int strong;
-	int weak;
-};
-
-/**
- * struct binder_ref - struct to track references on nodes
- * @data:        binder_ref_data containing id, handle, and current refcounts
- * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
- * @rb_node_node: node for lookup by @node in proc's rb_tree
- * @node_entry:  list entry for node->refs list in target node
- *               (protected by @node->lock)
- * @proc:        binder_proc containing ref
- * @node:        binder_node of target node. When cleaning up a
- *               ref for deletion in binder_cleanup_ref, a non-NULL
- *               @node indicates the node must be freed
- * @death:       pointer to death notification (ref_death) if requested
- *               (protected by @node->lock)
- *
- * Structure to track references from procA to target node (on procB). This
- * structure is unsafe to access without holding @proc->outer_lock.
- */
-struct binder_ref {
-	/* Lookups needed: */
-	/*   node + proc => ref (transaction) */
-	/*   desc + proc => ref (transaction, inc/dec ref) */
-	/*   node => refs + procs (proc exit) */
-	struct binder_ref_data data;
-	struct rb_node rb_node_desc;
-	struct rb_node rb_node_node;
-	struct hlist_node node_entry;
-	struct binder_proc *proc;
-	struct binder_node *node;
-	struct binder_ref_death *death;
-};
-
 enum binder_deferred_state {
 	BINDER_DEFERRED_FLUSH        = 0x01,
 	BINDER_DEFERRED_RELEASE      = 0x02,
 };
 
-/**
- * struct binder_proc - binder process bookkeeping
- * @proc_node:            element for binder_procs list
- * @threads:              rbtree of binder_threads in this proc
- *                        (protected by @inner_lock)
- * @nodes:                rbtree of binder nodes associated with
- *                        this proc ordered by node->ptr
- *                        (protected by @inner_lock)
- * @refs_by_desc:         rbtree of refs ordered by ref->desc
- *                        (protected by @outer_lock)
- * @refs_by_node:         rbtree of refs ordered by ref->node
- *                        (protected by @outer_lock)
- * @waiting_threads:      threads currently waiting for proc work
- *                        (protected by @inner_lock)
- * @pid                   PID of group_leader of process
- *                        (invariant after initialized)
- * @tsk                   task_struct for group_leader of process
- *                        (invariant after initialized)
- * @deferred_work_node:   element for binder_deferred_list
- *                        (protected by binder_deferred_lock)
- * @deferred_work:        bitmap of deferred work to perform
- *                        (protected by binder_deferred_lock)
- * @is_dead:              process is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @inner_lock)
- * @todo:                 list of work for this process
- *                        (protected by @inner_lock)
- * @stats:                per-process binder statistics
- *                        (atomics, no lock needed)
- * @delivered_death:      list of delivered death notification
- *                        (protected by @inner_lock)
- * @max_threads:          cap on number of binder threads
- *                        (protected by @inner_lock)
- * @requested_threads:    number of binder threads requested but not
- *                        yet started. In current implementation, can
- *                        only be 0 or 1.
- *                        (protected by @inner_lock)
- * @requested_threads_started: number binder threads started
- *                        (protected by @inner_lock)
- * @tmp_ref:              temporary reference to indicate proc is in use
- *                        (protected by @inner_lock)
- * @default_priority:     default scheduler priority
- *                        (invariant after initialized)
- * @debugfs_entry:        debugfs node
- * @alloc:                binder allocator bookkeeping
- * @context:              binder_context for this proc
- *                        (invariant after initialized)
- * @inner_lock:           can nest under outer_lock and/or node lock
- * @outer_lock:           no nesting under innor or node lock
- *                        Lock order: 1) outer, 2) node, 3) inner
- * @binderfs_entry:       process-specific binderfs log file
- *
- * Bookkeeping structure for binder processes
- */
-struct binder_proc {
-	struct hlist_node proc_node;
-	struct rb_root threads;
-	struct rb_root nodes;
-	struct rb_root refs_by_desc;
-	struct rb_root refs_by_node;
-	struct list_head waiting_threads;
-	int pid;
-	struct task_struct *tsk;
-	struct hlist_node deferred_work_node;
-	int deferred_work;
-	bool is_dead;
-
-	struct list_head todo;
-	struct binder_stats stats;
-	struct list_head delivered_death;
-	int max_threads;
-	int requested_threads;
-	int requested_threads_started;
-	int tmp_ref;
-	long default_priority;
-	struct dentry *debugfs_entry;
-	struct binder_alloc alloc;
-	struct binder_context *context;
-	spinlock_t inner_lock;
-	spinlock_t outer_lock;
-	struct dentry *binderfs_entry;
-};
-
 enum {
 	BINDER_LOOPER_STATE_REGISTERED  = 0x01,
 	BINDER_LOOPER_STATE_ENTERED     = 0x02,
@@ -495,125 +210,6 @@ enum {
 };
 
 /**
- * struct binder_thread - binder thread bookkeeping
- * @proc:                 binder process for this thread
- *                        (invariant after initialization)
- * @rb_node:              element for proc->threads rbtree
- *                        (protected by @proc->inner_lock)
- * @waiting_thread_node:  element for @proc->waiting_threads list
- *                        (protected by @proc->inner_lock)
- * @pid:                  PID for this thread
- *                        (invariant after initialization)
- * @looper:               bitmap of looping state
- *                        (only accessed by this thread)
- * @looper_needs_return:  looping thread needs to exit driver
- *                        (no lock needed)
- * @transaction_stack:    stack of in-progress transactions for this thread
- *                        (protected by @proc->inner_lock)
- * @todo:                 list of work to do for this thread
- *                        (protected by @proc->inner_lock)
- * @process_todo:         whether work in @todo should be processed
- *                        (protected by @proc->inner_lock)
- * @return_error:         transaction errors reported by this thread
- *                        (only accessed by this thread)
- * @reply_error:          transaction errors reported by target thread
- *                        (protected by @proc->inner_lock)
- * @wait:                 wait queue for thread work
- * @stats:                per-thread statistics
- *                        (atomics, no lock needed)
- * @tmp_ref:              temporary reference to indicate thread is in use
- *                        (atomic since @proc->inner_lock cannot
- *                        always be acquired)
- * @is_dead:              thread is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder threads.
- */
-struct binder_thread {
-	struct binder_proc *proc;
-	struct rb_node rb_node;
-	struct list_head waiting_thread_node;
-	int pid;
-	int looper;              /* only modified by this thread */
-	bool looper_need_return; /* can be written by other thread */
-	struct binder_transaction *transaction_stack;
-	struct list_head todo;
-	bool process_todo;
-	struct binder_error return_error;
-	struct binder_error reply_error;
-	wait_queue_head_t wait;
-	struct binder_stats stats;
-	atomic_t tmp_ref;
-	bool is_dead;
-};
-
-/**
- * struct binder_txn_fd_fixup - transaction fd fixup list element
- * @fixup_entry:          list entry
- * @file:                 struct file to be associated with new fd
- * @offset:               offset in buffer data to this fixup
- *
- * List element for fd fixups in a transaction. Since file
- * descriptors need to be allocated in the context of the
- * target process, we pass each fd to be processed in this
- * struct.
- */
-struct binder_txn_fd_fixup {
-	struct list_head fixup_entry;
-	struct file *file;
-	size_t offset;
-};
-
-struct binder_transaction {
-	int debug_id;
-	struct binder_work work;
-	struct binder_thread *from;
-	struct binder_transaction *from_parent;
-	struct binder_proc *to_proc;
-	struct binder_thread *to_thread;
-	struct binder_transaction *to_parent;
-	unsigned need_reply:1;
-	/* unsigned is_dead:1; */	/* not used at the moment */
-
-	struct binder_buffer *buffer;
-	unsigned int	code;
-	unsigned int	flags;
-	long	priority;
-	long	saved_priority;
-	kuid_t	sender_euid;
-	struct list_head fd_fixups;
-	binder_uintptr_t security_ctx;
-	/**
-	 * @lock:  protects @from, @to_proc, and @to_thread
-	 *
-	 * @from, @to_proc, and @to_thread can be set to NULL
-	 * during thread teardown
-	 */
-	spinlock_t lock;
-};
-
-/**
- * struct binder_object - union of flat binder object types
- * @hdr:   generic object header
- * @fbo:   binder object (nodes and refs)
- * @fdo:   file descriptor object
- * @bbo:   binder buffer pointer
- * @fdao:  file descriptor array
- *
- * Used for type-independent object copies
- */
-struct binder_object {
-	union {
-		struct binder_object_header hdr;
-		struct flat_binder_object fbo;
-		struct binder_fd_object fdo;
-		struct binder_buffer_object bbo;
-		struct binder_fd_array_object fdao;
-	};
-};
-
-/**
  * binder_proc_lock() - Acquire outer lock for given binder_proc
  * @proc:         struct binder_proc to acquire
  *
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index ae99109..ed61b3e 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -139,6 +139,409 @@ struct binder_transaction_log {
 	struct binder_transaction_log_entry entry[32];
 };
 
+enum binder_stat_types {
+	BINDER_STAT_PROC,
+	BINDER_STAT_THREAD,
+	BINDER_STAT_NODE,
+	BINDER_STAT_REF,
+	BINDER_STAT_DEATH,
+	BINDER_STAT_TRANSACTION,
+	BINDER_STAT_TRANSACTION_COMPLETE,
+	BINDER_STAT_COUNT
+};
+
+struct binder_stats {
+	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
+	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
+	atomic_t obj_created[BINDER_STAT_COUNT];
+	atomic_t obj_deleted[BINDER_STAT_COUNT];
+};
+
+/**
+ * struct binder_work - work enqueued on a worklist
+ * @entry:             node enqueued on list
+ * @type:              type of work to be performed
+ *
+ * There are separate work lists for proc, thread, and node (async).
+ */
+struct binder_work {
+	struct list_head entry;
+
+	enum {
+		BINDER_WORK_TRANSACTION = 1,
+		BINDER_WORK_TRANSACTION_COMPLETE,
+		BINDER_WORK_RETURN_ERROR,
+		BINDER_WORK_NODE,
+		BINDER_WORK_DEAD_BINDER,
+		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
+		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
+	} type;
+};
+
+struct binder_error {
+	struct binder_work work;
+	uint32_t cmd;
+};
+
+/* struct binder_node - binder node bookkeeping
+ * @debug_id:             unique ID for debugging
+ *                        (invariant after initialized)
+ * @lock:                 lock for node fields
+ * @work:                 worklist element for node work
+ *                        (protected by @proc->inner_lock)
+ * @rb_node:              element for proc->nodes tree
+ *                        (protected by @proc->inner_lock)
+ * @dead_node:            element for binder_dead_nodes list
+ *                        (protected by binder_dead_nodes_lock)
+ * @proc:                 binder_proc that owns this node
+ *                        (invariant after initialized)
+ * @refs:                 list of references on this node
+ *                        (protected by @lock)
+ * @internal_strong_refs: used to take strong references when
+ *                        initiating a transaction
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_weak_refs:      weak user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_strong_refs:    strong user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @tmp_refs:             temporary kernel refs
+ *                        (protected by @proc->inner_lock while @proc
+ *                        is valid, and by binder_dead_nodes_lock
+ *                        if @proc is NULL. During inc/dec and node release
+ *                        it is also protected by @lock to provide safety
+ *                        as the node dies and @proc becomes NULL)
+ * @ptr:                  userspace pointer for node
+ *                        (invariant, no lock needed)
+ * @cookie:               userspace cookie for node
+ *                        (invariant, no lock needed)
+ * @has_strong_ref:       userspace notified of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_strong_ref:   userspace has acked notification of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_weak_ref:         userspace notified of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_weak_ref:     userspace has acked notification of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_async_transaction: async transaction to node in progress
+ *                        (protected by @lock)
+ * @accept_fds:           file descriptor operations supported for node
+ *                        (invariant after initialized)
+ * @min_priority:         minimum scheduling priority
+ *                        (invariant after initialized)
+ * @txn_security_ctx:     require sender's security context
+ *                        (invariant after initialized)
+ * @async_todo:           list of async work items
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder nodes.
+ */
+struct binder_node {
+	int debug_id;
+	spinlock_t lock;
+	struct binder_work work;
+	union {
+		struct rb_node rb_node;
+		struct hlist_node dead_node;
+	};
+	struct binder_proc *proc;
+	struct hlist_head refs;
+	int internal_strong_refs;
+	int local_weak_refs;
+	int local_strong_refs;
+	int tmp_refs;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
+	struct {
+		/*
+		 * bitfield elements protected by
+		 * proc inner_lock
+		 */
+		u8 has_strong_ref:1;
+		u8 pending_strong_ref:1;
+		u8 has_weak_ref:1;
+		u8 pending_weak_ref:1;
+	};
+	struct {
+		/*
+		 * invariant after initialization
+		 */
+		u8 accept_fds:1;
+		u8 txn_security_ctx:1;
+		u8 min_priority;
+	};
+	bool has_async_transaction;
+	struct list_head async_todo;
+};
+
+struct binder_ref_death {
+	/**
+	 * @work: worklist element for death notifications
+	 *        (protected by inner_lock of the proc that
+	 *        this ref belongs to)
+	 */
+	struct binder_work work;
+	binder_uintptr_t cookie;
+};
+
+/**
+ * struct binder_ref_data - binder_ref counts and id
+ * @debug_id:        unique ID for the ref
+ * @desc:            unique userspace handle for ref
+ * @strong:          strong ref count (debugging only if not locked)
+ * @weak:            weak ref count (debugging only if not locked)
+ *
+ * Structure to hold ref count and ref id information. Since
+ * the actual ref can only be accessed with a lock, this structure
+ * is used to return information about the ref to callers of
+ * ref inc/dec functions.
+ */
+struct binder_ref_data {
+	int debug_id;
+	uint32_t desc;
+	int strong;
+	int weak;
+};
+
+/**
+ * struct binder_ref - struct to track references on nodes
+ * @data:        binder_ref_data containing id, handle, and current refcounts
+ * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
+ * @rb_node_node: node for lookup by @node in proc's rb_tree
+ * @node_entry:  list entry for node->refs list in target node
+ *               (protected by @node->lock)
+ * @proc:        binder_proc containing ref
+ * @node:        binder_node of target node. When cleaning up a
+ *               ref for deletion in binder_cleanup_ref, a non-NULL
+ *               @node indicates the node must be freed
+ * @death:       pointer to death notification (ref_death) if requested
+ *               (protected by @node->lock)
+ *
+ * Structure to track references from procA to target node (on procB). This
+ * structure is unsafe to access without holding @proc->outer_lock.
+ */
+struct binder_ref {
+	/* Lookups needed: */
+	/*   node + proc => ref (transaction) */
+	/*   desc + proc => ref (transaction, inc/dec ref) */
+	/*   node => refs + procs (proc exit) */
+	struct binder_ref_data data;
+	struct rb_node rb_node_desc;
+	struct rb_node rb_node_node;
+	struct hlist_node node_entry;
+	struct binder_proc *proc;
+	struct binder_node *node;
+	struct binder_ref_death *death;
+};
+
+/**
+ * struct binder_proc - binder process bookkeeping
+ * @proc_node:            element for binder_procs list
+ * @threads:              rbtree of binder_threads in this proc
+ *                        (protected by @inner_lock)
+ * @nodes:                rbtree of binder nodes associated with
+ *                        this proc ordered by node->ptr
+ *                        (protected by @inner_lock)
+ * @refs_by_desc:         rbtree of refs ordered by ref->desc
+ *                        (protected by @outer_lock)
+ * @refs_by_node:         rbtree of refs ordered by ref->node
+ *                        (protected by @outer_lock)
+ * @waiting_threads:      threads currently waiting for proc work
+ *                        (protected by @inner_lock)
+ * @pid                   PID of group_leader of process
+ *                        (invariant after initialized)
+ * @tsk                   task_struct for group_leader of process
+ *                        (invariant after initialized)
+ * @deferred_work_node:   element for binder_deferred_list
+ *                        (protected by binder_deferred_lock)
+ * @deferred_work:        bitmap of deferred work to perform
+ *                        (protected by binder_deferred_lock)
+ * @is_dead:              process is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @inner_lock)
+ * @todo:                 list of work for this process
+ *                        (protected by @inner_lock)
+ * @stats:                per-process binder statistics
+ *                        (atomics, no lock needed)
+ * @delivered_death:      list of delivered death notification
+ *                        (protected by @inner_lock)
+ * @max_threads:          cap on number of binder threads
+ *                        (protected by @inner_lock)
+ * @requested_threads:    number of binder threads requested but not
+ *                        yet started. In current implementation, can
+ *                        only be 0 or 1.
+ *                        (protected by @inner_lock)
+ * @requested_threads_started: number binder threads started
+ *                        (protected by @inner_lock)
+ * @tmp_ref:              temporary reference to indicate proc is in use
+ *                        (protected by @inner_lock)
+ * @default_priority:     default scheduler priority
+ *                        (invariant after initialized)
+ * @debugfs_entry:        debugfs node
+ * @alloc:                binder allocator bookkeeping
+ * @context:              binder_context for this proc
+ *                        (invariant after initialized)
+ * @inner_lock:           can nest under outer_lock and/or node lock
+ * @outer_lock:           no nesting under innor or node lock
+ *                        Lock order: 1) outer, 2) node, 3) inner
+ * @binderfs_entry:       process-specific binderfs log file
+ *
+ * Bookkeeping structure for binder processes
+ */
+struct binder_proc {
+	struct hlist_node proc_node;
+	struct rb_root threads;
+	struct rb_root nodes;
+	struct rb_root refs_by_desc;
+	struct rb_root refs_by_node;
+	struct list_head waiting_threads;
+	int pid;
+	struct task_struct *tsk;
+	struct hlist_node deferred_work_node;
+	int deferred_work;
+	bool is_dead;
+
+	struct list_head todo;
+	struct binder_stats stats;
+	struct list_head delivered_death;
+	int max_threads;
+	int requested_threads;
+	int requested_threads_started;
+	int tmp_ref;
+	long default_priority;
+	struct dentry *debugfs_entry;
+	struct binder_alloc alloc;
+	struct binder_context *context;
+	spinlock_t inner_lock;
+	spinlock_t outer_lock;
+	struct dentry *binderfs_entry;
+};
+
+/**
+ * struct binder_thread - binder thread bookkeeping
+ * @proc:                 binder process for this thread
+ *                        (invariant after initialization)
+ * @rb_node:              element for proc->threads rbtree
+ *                        (protected by @proc->inner_lock)
+ * @waiting_thread_node:  element for @proc->waiting_threads list
+ *                        (protected by @proc->inner_lock)
+ * @pid:                  PID for this thread
+ *                        (invariant after initialization)
+ * @looper:               bitmap of looping state
+ *                        (only accessed by this thread)
+ * @looper_needs_return:  looping thread needs to exit driver
+ *                        (no lock needed)
+ * @transaction_stack:    stack of in-progress transactions for this thread
+ *                        (protected by @proc->inner_lock)
+ * @todo:                 list of work to do for this thread
+ *                        (protected by @proc->inner_lock)
+ * @process_todo:         whether work in @todo should be processed
+ *                        (protected by @proc->inner_lock)
+ * @return_error:         transaction errors reported by this thread
+ *                        (only accessed by this thread)
+ * @reply_error:          transaction errors reported by target thread
+ *                        (protected by @proc->inner_lock)
+ * @wait:                 wait queue for thread work
+ * @stats:                per-thread statistics
+ *                        (atomics, no lock needed)
+ * @tmp_ref:              temporary reference to indicate thread is in use
+ *                        (atomic since @proc->inner_lock cannot
+ *                        always be acquired)
+ * @is_dead:              thread is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder threads.
+ */
+struct binder_thread {
+	struct binder_proc *proc;
+	struct rb_node rb_node;
+	struct list_head waiting_thread_node;
+	int pid;
+	int looper;              /* only modified by this thread */
+	bool looper_need_return; /* can be written by other thread */
+	struct binder_transaction *transaction_stack;
+	struct list_head todo;
+	bool process_todo;
+	struct binder_error return_error;
+	struct binder_error reply_error;
+	wait_queue_head_t wait;
+	struct binder_stats stats;
+	atomic_t tmp_ref;
+	bool is_dead;
+};
+
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry:          list entry
+ * @file:                 struct file to be associated with new fd
+ * @offset:               offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+	struct list_head fixup_entry;
+	struct file *file;
+	size_t offset;
+};
+
+struct binder_transaction {
+	int debug_id;
+	struct binder_work work;
+	struct binder_thread *from;
+	struct binder_transaction *from_parent;
+	struct binder_proc *to_proc;
+	struct binder_thread *to_thread;
+	struct binder_transaction *to_parent;
+	unsigned need_reply:1;
+	/* unsigned is_dead:1; */       /* not used at the moment */
+
+	struct binder_buffer *buffer;
+	unsigned int    code;
+	unsigned int    flags;
+	long    priority;
+	long    saved_priority;
+	kuid_t  sender_euid;
+	struct list_head fd_fixups;
+	binder_uintptr_t security_ctx;
+	/**
+	 * @lock:  protects @from, @to_proc, and @to_thread
+	 *
+	 * @from, @to_proc, and @to_thread can be set to NULL
+	 * during thread teardown
+	 */
+	spinlock_t lock;
+};
+
+/**
+ * struct binder_object - union of flat binder object types
+ * @hdr:   generic object header
+ * @fbo:   binder object (nodes and refs)
+ * @fdo:   file descriptor object
+ * @bbo:   binder buffer pointer
+ * @fdao:  file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+	union {
+		struct binder_object_header hdr;
+		struct flat_binder_object fbo;
+		struct binder_fd_object fdo;
+		struct binder_buffer_object bbo;
+		struct binder_fd_array_object fdao;
+	};
+};
+
 extern struct binder_transaction_log binder_transaction_log;
 extern struct binder_transaction_log binder_transaction_log_failed;
 #endif /* _LINUX_BINDER_INTERNAL_H */
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v4 2/3] binder: add trace at free transaction.
  2020-05-07  8:10                         ` Frankie Chang
  2020-05-07  8:10                           ` [PATCH v4 1/3] binder: move structs from core file to header file Frankie Chang
@ 2020-05-07  8:10                           ` Frankie Chang
  2020-05-07  8:10                           ` [PATCH v4 3/3] binder: add transaction latency tracer Frankie Chang
  2 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-05-07  8:10 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Todd Kjos, Joel Fernandes
  Cc: wsd_upstream, LKML, Arve Hjønnevåg, Jian-Min Liu,
	linux-mediatek, Frankie.Chang, Martijn Coenen, Christian Brauner

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Since the original trace_binder_transaction_received cannot
precisely present the real finished time of transaction, adding a
trace_binder_free_transaction at the point of free transaction
may be more close to it.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/binder.c       |    2 ++
 drivers/android/binder_trace.h |   27 +++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

 Change since v4:
   split up into a patchset series.

 Change since v2:
   add trace/tracepoint at free transaction.

 Change since v1:
   first patchset.

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 1592396..4c3dd98 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1523,6 +1523,7 @@ static void binder_free_transaction(struct binder_transaction *t)
 	 * If the transaction has no target_proc, then
 	 * t->buffer->transaction has already been cleared.
 	 */
+	trace_binder_free_transaction(t);
 	binder_free_txn_fixups(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
@@ -3094,6 +3095,7 @@ static void binder_transaction(struct binder_proc *proc,
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 err_alloc_tcomplete_failed:
+	trace_binder_free_transaction(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
 err_alloc_t_failed:
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 6731c3c..7acc18d 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,33 @@
 		  __entry->thread_todo)
 );
 
+TRACE_EVENT(binder_free_transaction,
+	TP_PROTO(struct binder_transaction *t),
+	TP_ARGS(t),
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, from_proc)
+		__field(int, from_thread)
+		__field(int, to_proc)
+		__field(int, to_thread)
+		__field(unsigned int, code)
+		__field(unsigned int, flags)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->from_proc = t->from ? t->from->proc->pid : 0;
+		__entry->from_thread = t->from ? t->from->pid : 0;
+		__entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
+		__entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
+		__entry->code = t->code;
+		__entry->flags = t->flags;
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
+		  __entry->to_proc, __entry->to_thread, __entry->code,
+		  __entry->flags)
+);
+
 TRACE_EVENT(binder_transaction,
 	TP_PROTO(bool reply, struct binder_transaction *t,
 		 struct binder_node *target_node),
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v4 3/3] binder: add transaction latency tracer
  2020-05-07  8:10                         ` Frankie Chang
  2020-05-07  8:10                           ` [PATCH v4 1/3] binder: move structs from core file to header file Frankie Chang
  2020-05-07  8:10                           ` [PATCH v4 2/3] binder: add trace at free transaction Frankie Chang
@ 2020-05-07  8:10                           ` Frankie Chang
  2020-05-07  8:55                             ` Greg Kroah-Hartman
  2020-05-07 18:21                             ` [PATCH v4 " Todd Kjos
  2 siblings, 2 replies; 72+ messages in thread
From: Frankie Chang @ 2020-05-07  8:10 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Todd Kjos, Joel Fernandes
  Cc: wsd_upstream, LKML, Arve Hjønnevåg, Jian-Min Liu,
	linux-mediatek, Frankie.Chang, Martijn Coenen, Christian Brauner

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Record start/end timestamp for binder transaction.
When transaction is completed or transaction is free,
it would be checked if transaction latency over threshold (2 sec),
if yes, printing related information for tracing.

/* Implement details */
- Add latency tracer module to monitor slow transaction.
  The trace_binder_free_transaction would not be enabled
  by default. Monitoring which transaction is too slow to
  cause some of exceptions is important. So we hook the
  tracepoint to call the monitor function.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/Kconfig                 |    8 +++
 drivers/android/Makefile                |    1 +
 drivers/android/binder.c                |    2 +
 drivers/android/binder_internal.h       |   13 ++++
 drivers/android/binder_latency_tracer.c |  105 +++++++++++++++++++++++++++++++
 drivers/android/binder_trace.h          |   26 +++++++-
 6 files changed, 152 insertions(+), 3 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c

 Change from v4:
   split up into patch series.

 Change from v3:
   use tracepoints for binder_update_info and print_binder_transaction_ext,
   instead of custom registration functions.

 Change from v2:
   create transaction latency module to monitor slow transaction.

 Change from v1:
   first patchset.

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 6fdf2ab..7ba80eb 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
 	  exhaustively with combinations of various buffer sizes and
 	  alignments.
 
+config BINDER_USER_TRACKING
+	bool "Android Binder transaction tracking"
+	help
+	  Used for track abnormal binder transaction which is over 2 seconds,
+	  when the transaction is done or be free, this transaction would be
+	  checked whether it executed overtime.
+	  If yes, printing out the detail info about it.
+
 endif # if ANDROID
 
 endmenu
diff --git a/drivers/android/Makefile b/drivers/android/Makefile
index c9d3d0c9..552e8ac 100644
--- a/drivers/android/Makefile
+++ b/drivers/android/Makefile
@@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
 obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
 obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
 obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
+obj-$(CONFIG_BINDER_USER_TRACKING)	+= binder_latency_tracer.o
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 4c3dd98..b89d75a 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2657,6 +2657,7 @@ static void binder_transaction(struct binder_proc *proc,
 		return_error_line = __LINE__;
 		goto err_alloc_t_failed;
 	}
+	trace_binder_update_info(t, e);
 	INIT_LIST_HEAD(&t->fd_fixups);
 	binder_stats_created(BINDER_STAT_TRANSACTION);
 	spin_lock_init(&t->lock);
@@ -5145,6 +5146,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
 		   t->to_thread ? t->to_thread->pid : 0,
 		   t->code, t->flags, t->priority, t->need_reply);
 	spin_unlock(&t->lock);
+	trace_print_binder_transaction_ext(m, t);
 
 	if (proc != to_proc) {
 		/*
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index ed61b3e..24d7beb 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -12,6 +12,11 @@
 #include <linux/types.h>
 #include <linux/uidgid.h>
 
+#ifdef CONFIG_BINDER_USER_TRACKING
+#include <linux/rtc.h>
+#include <linux/time.h>
+#endif
+
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
 	struct mutex context_mgr_node_lock;
@@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
 	uint32_t return_error;
 	uint32_t return_error_param;
 	char context_name[BINDERFS_MAX_NAME + 1];
+#ifdef CONFIG_BINDER_USER_TRACKING
+	struct timespec timestamp;
+	struct timeval tv;
+#endif
 };
 
 struct binder_transaction_log {
@@ -520,6 +529,10 @@ struct binder_transaction {
 	 * during thread teardown
 	 */
 	spinlock_t lock;
+#ifdef CONFIG_BINDER_USER_TRACKING
+	struct timespec timestamp;
+	struct timeval tv;
+#endif
 };
 
 /**
diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
new file mode 100644
index 0000000..45c14fb
--- /dev/null
+++ b/drivers/android/binder_latency_tracer.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ */
+
+#include <linux/module.h>
+#include <uapi/linux/android/binder.h>
+#include "binder_alloc.h"
+#include "binder_internal.h"
+#include "binder_trace.h"
+
+/*
+ * probe_binder_free_transaction - Output info of a delay transaction
+ * @t:          pointer to the over-time transaction
+ */
+void probe_binder_free_transaction(void *ignore, struct binder_transaction *t)
+{
+	struct rtc_time tm;
+	struct timespec *startime;
+	struct timespec cur, sub_t;
+
+	ktime_get_ts(&cur);
+	startime = &t->timestamp;
+	sub_t = timespec_sub(cur, *startime);
+
+	/* if transaction time is over than 2 sec,
+	 * show timeout warning log.
+	 */
+	if (sub_t.tv_sec < 2)
+		return;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+
+	spin_lock(&t->lock);
+	pr_info_ratelimited("%d: from %d:%d to %d:%d",
+			t->debug_id,
+			t->from ? t->from->proc->pid : 0,
+			t->from ? t->from->pid : 0,
+			t->to_proc ? t->to_proc->pid : 0,
+			t->to_thread ? t->to_thread->pid : 0);
+	spin_unlock(&t->lock);
+
+	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
+			(unsigned int)sub_t.tv_sec,
+			(sub_t.tv_nsec / NSEC_PER_MSEC),
+			t->code,
+			(unsigned long)startime->tv_sec,
+			(startime->tv_nsec / NSEC_PER_MSEC),
+			(tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+			tm.tm_hour, tm.tm_min, tm.tm_sec,
+			(unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+
+static void probe_binder_update_info(void *ignore, struct binder_transaction *t,
+			   struct binder_transaction_log_entry *e)
+{
+	ktime_get_ts(&e->timestamp);
+	do_gettimeofday(&e->tv);
+	e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
+	memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
+	memcpy(&t->tv, &e->tv, sizeof(struct timeval));
+}
+
+static void probe_print_binder_transaction_ext(void *ignore, struct seq_file *m,
+					 struct binder_transaction *t)
+{
+	struct rtc_time tm;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+	seq_printf(m,
+		   " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
+		   (unsigned long)t->timestamp.tv_sec,
+		   (t->timestamp.tv_nsec / NSEC_PER_USEC),
+		   (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+		   tm.tm_hour, tm.tm_min, tm.tm_sec,
+		   (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+
+}
+
+static int __init init_binder_latency_tracer(void)
+{
+	register_trace_binder_free_transaction(
+			probe_binder_free_transaction, NULL);
+	register_trace_binder_update_info(
+			probe_binder_update_info, NULL);
+	register_trace_print_binder_transaction_ext(
+			probe_print_binder_transaction_ext, NULL);
+
+	return 0;
+}
+
+static void exit_binder_latency_tracer(void)
+{
+	unregister_trace_binder_free_transaction(
+			probe_binder_free_transaction, NULL);
+	unregister_trace_binder_update_info(
+			probe_binder_update_info, NULL);
+	unregister_trace_print_binder_transaction_ext(
+			probe_print_binder_transaction_ext, NULL);
+}
+
+module_init(init_binder_latency_tracer);
+module_exit(exit_binder_latency_tracer);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 7acc18d..466993e 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -18,6 +18,7 @@
 struct binder_ref_data;
 struct binder_thread;
 struct binder_transaction;
+struct binder_transaction_log_entry;
 
 TRACE_EVENT(binder_ioctl,
 	TP_PROTO(unsigned int cmd, unsigned long arg),
@@ -95,6 +96,18 @@
 		  __entry->thread_todo)
 );
 
+DECLARE_TRACE(binder_update_info,
+	TP_PROTO(struct binder_transaction *t,
+		 struct binder_transaction_log_entry *e),
+	TP_ARGS(t, e)
+);
+
+DECLARE_TRACE(print_binder_transaction_ext,
+	TP_PROTO(struct seq_file *m,
+		 struct binder_transaction *t),
+	TP_ARGS(m, t)
+);
+
 TRACE_EVENT(binder_free_transaction,
 	TP_PROTO(struct binder_transaction *t),
 	TP_ARGS(t),
@@ -115,11 +128,18 @@
 		__entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
 		__entry->code = t->code;
 		__entry->flags = t->flags;
-	),
-	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+#ifdef CONFIG_BINDER_USER_TRACKING
+		__entry->start_sec = t->timestamp.tv_sec;
+		__entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
+#else
+		__entry->start_sec = 0;
+		__entry->start_nsec = 0;
+#endif
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
 		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
 		  __entry->to_proc, __entry->to_thread, __entry->code,
-		  __entry->flags)
+		  __entry->flags, __entry->start_sec, __entry->start_nsec)
 );
 
 TRACE_EVENT(binder_transaction,
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 3/3] binder: add transaction latency tracer
  2020-05-07  8:10                           ` [PATCH v4 3/3] binder: add transaction latency tracer Frankie Chang
@ 2020-05-07  8:55                             ` Greg Kroah-Hartman
  2020-05-11 12:32                               ` Frankie Chang
  2020-06-10 12:23                               ` [PATCH v5] binder: transaction latency tracking for user build Frankie Chang
  2020-05-07 18:21                             ` [PATCH v4 " Todd Kjos
  1 sibling, 2 replies; 72+ messages in thread
From: Greg Kroah-Hartman @ 2020-05-07  8:55 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, LKML, Arve Hjønnevåg, Jian-Min Liu,
	linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Thu, May 07, 2020 at 04:10:55PM +0800, Frankie Chang wrote:
> From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
> 
> Record start/end timestamp for binder transaction.
> When transaction is completed or transaction is free,
> it would be checked if transaction latency over threshold (2 sec),
> if yes, printing related information for tracing.

Shouldn't that "printing" go to the trace buffer and not to the kernel
information log?

> 
> /* Implement details */
> - Add latency tracer module to monitor slow transaction.
>   The trace_binder_free_transaction would not be enabled
>   by default. Monitoring which transaction is too slow to
>   cause some of exceptions is important. So we hook the
>   tracepoint to call the monitor function.
> 
> Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> ---
>  drivers/android/Kconfig                 |    8 +++
>  drivers/android/Makefile                |    1 +
>  drivers/android/binder.c                |    2 +
>  drivers/android/binder_internal.h       |   13 ++++
>  drivers/android/binder_latency_tracer.c |  105 +++++++++++++++++++++++++++++++
>  drivers/android/binder_trace.h          |   26 +++++++-
>  6 files changed, 152 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/android/binder_latency_tracer.c
> 
>  Change from v4:
>    split up into patch series.
> 
>  Change from v3:
>    use tracepoints for binder_update_info and print_binder_transaction_ext,
>    instead of custom registration functions.
> 
>  Change from v2:
>    create transaction latency module to monitor slow transaction.
> 
>  Change from v1:
>    first patchset.
> 
> diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> index 6fdf2ab..7ba80eb 100644
> --- a/drivers/android/Kconfig
> +++ b/drivers/android/Kconfig
> @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
>  	  exhaustively with combinations of various buffer sizes and
>  	  alignments.
>  
> +config BINDER_USER_TRACKING
> +	bool "Android Binder transaction tracking"
> +	help
> +	  Used for track abnormal binder transaction which is over 2 seconds,
> +	  when the transaction is done or be free, this transaction would be
> +	  checked whether it executed overtime.
> +	  If yes, printing out the detail info about it.
> +
>  endif # if ANDROID
>  
>  endmenu
> diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> index c9d3d0c9..552e8ac 100644
> --- a/drivers/android/Makefile
> +++ b/drivers/android/Makefile
> @@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
>  obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> +obj-$(CONFIG_BINDER_USER_TRACKING)	+= binder_latency_tracer.o
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 4c3dd98..b89d75a 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2657,6 +2657,7 @@ static void binder_transaction(struct binder_proc *proc,
>  		return_error_line = __LINE__;
>  		goto err_alloc_t_failed;
>  	}
> +	trace_binder_update_info(t, e);
>  	INIT_LIST_HEAD(&t->fd_fixups);
>  	binder_stats_created(BINDER_STAT_TRANSACTION);
>  	spin_lock_init(&t->lock);
> @@ -5145,6 +5146,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
>  		   t->to_thread ? t->to_thread->pid : 0,
>  		   t->code, t->flags, t->priority, t->need_reply);
>  	spin_unlock(&t->lock);
> +	trace_print_binder_transaction_ext(m, t);
>  
>  	if (proc != to_proc) {
>  		/*
> diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> index ed61b3e..24d7beb 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -12,6 +12,11 @@
>  #include <linux/types.h>
>  #include <linux/uidgid.h>
>  
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +#include <linux/rtc.h>
> +#include <linux/time.h>
> +#endif
> +
>  struct binder_context {
>  	struct binder_node *binder_context_mgr_node;
>  	struct mutex context_mgr_node_lock;
> @@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
>  	uint32_t return_error;
>  	uint32_t return_error_param;
>  	char context_name[BINDERFS_MAX_NAME + 1];
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +	struct timespec timestamp;
> +	struct timeval tv;
> +#endif
>  };
>  
>  struct binder_transaction_log {
> @@ -520,6 +529,10 @@ struct binder_transaction {
>  	 * during thread teardown
>  	 */
>  	spinlock_t lock;
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +	struct timespec timestamp;
> +	struct timeval tv;
> +#endif
>  };
>  
>  /**
> diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
> new file mode 100644
> index 0000000..45c14fb
> --- /dev/null
> +++ b/drivers/android/binder_latency_tracer.c
> @@ -0,0 +1,105 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2019 MediaTek Inc.
> + */
> +
> +#include <linux/module.h>
> +#include <uapi/linux/android/binder.h>
> +#include "binder_alloc.h"
> +#include "binder_internal.h"
> +#include "binder_trace.h"
> +
> +/*
> + * probe_binder_free_transaction - Output info of a delay transaction
> + * @t:          pointer to the over-time transaction
> + */
> +void probe_binder_free_transaction(void *ignore, struct binder_transaction *t)
> +{
> +	struct rtc_time tm;
> +	struct timespec *startime;
> +	struct timespec cur, sub_t;
> +
> +	ktime_get_ts(&cur);
> +	startime = &t->timestamp;
> +	sub_t = timespec_sub(cur, *startime);
> +
> +	/* if transaction time is over than 2 sec,
> +	 * show timeout warning log.
> +	 */
> +	if (sub_t.tv_sec < 2)
> +		return;

Why is 2 seconds somehow "magic" here?



> +
> +	rtc_time_to_tm(t->tv.tv_sec, &tm);
> +
> +	spin_lock(&t->lock);
> +	pr_info_ratelimited("%d: from %d:%d to %d:%d",
> +			t->debug_id,
> +			t->from ? t->from->proc->pid : 0,
> +			t->from ? t->from->pid : 0,
> +			t->to_proc ? t->to_proc->pid : 0,
> +			t->to_thread ? t->to_thread->pid : 0);
> +	spin_unlock(&t->lock);

Why is the lock ok to give up here and not after the next call?

> +
> +	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> +			(unsigned int)sub_t.tv_sec,
> +			(sub_t.tv_nsec / NSEC_PER_MSEC),
> +			t->code,
> +			(unsigned long)startime->tv_sec,
> +			(startime->tv_nsec / NSEC_PER_MSEC),
> +			(tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> +			tm.tm_hour, tm.tm_min, tm.tm_sec,
> +			(unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> +}
> +
> +static void probe_binder_update_info(void *ignore, struct binder_transaction *t,
> +			   struct binder_transaction_log_entry *e)
> +{
> +	ktime_get_ts(&e->timestamp);
> +	do_gettimeofday(&e->tv);
> +	e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
> +	memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
> +	memcpy(&t->tv, &e->tv, sizeof(struct timeval));

No locking needed?


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 3/3] binder: add transaction latency tracer
  2020-05-07  8:10                           ` [PATCH v4 3/3] binder: add transaction latency tracer Frankie Chang
  2020-05-07  8:55                             ` Greg Kroah-Hartman
@ 2020-05-07 18:21                             ` Todd Kjos
  2020-05-11 12:35                               ` Frankie Chang
  1 sibling, 1 reply; 72+ messages in thread
From: Todd Kjos @ 2020-05-07 18:21 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Thu, May 7, 2020 at 1:11 AM Frankie Chang <Frankie.Chang@mediatek.com> wrote:
>
> From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
>
> Record start/end timestamp for binder transaction.
> When transaction is completed or transaction is free,
> it would be checked if transaction latency over threshold (2 sec),

If this is a hard-coded threshold, provide rationale for why 2 sec is
the right value and it doesn't need to be tunable

> if yes, printing related information for tracing.
>
> /* Implement details */
> - Add latency tracer module to monitor slow transaction.
>   The trace_binder_free_transaction would not be enabled
>   by default. Monitoring which transaction is too slow to
>   cause some of exceptions is important. So we hook the
>   tracepoint to call the monitor function.

Please add a more complete description. This patch adds a module to
monitor transaction latency by attaching to new tracepoints introduced
when transactions are allocated and freed. Describe this in the commit
message.

>
> Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> ---
>  drivers/android/Kconfig                 |    8 +++
>  drivers/android/Makefile                |    1 +
>  drivers/android/binder.c                |    2 +
>  drivers/android/binder_internal.h       |   13 ++++
>  drivers/android/binder_latency_tracer.c |  105 +++++++++++++++++++++++++++++++
>  drivers/android/binder_trace.h          |   26 +++++++-
>  6 files changed, 152 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/android/binder_latency_tracer.c
>
>  Change from v4:
>    split up into patch series.
>
>  Change from v3:
>    use tracepoints for binder_update_info and print_binder_transaction_ext,
>    instead of custom registration functions.
>
>  Change from v2:
>    create transaction latency module to monitor slow transaction.
>
>  Change from v1:
>    first patchset.
>
> diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> index 6fdf2ab..7ba80eb 100644
> --- a/drivers/android/Kconfig
> +++ b/drivers/android/Kconfig
> @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
>           exhaustively with combinations of various buffer sizes and
>           alignments.
>
> +config BINDER_USER_TRACKING

Why not "BINDER_TRANSACTION_LATENCY_TRACKING"?

> +       bool "Android Binder transaction tracking"
> +       help
> +         Used for track abnormal binder transaction which is over 2 seconds,
> +         when the transaction is done or be free, this transaction would be
> +         checked whether it executed overtime.
> +         If yes, printing out the detail info about it.

"If yes, print out the detailed info"

> +
>  endif # if ANDROID
>
>  endmenu
> diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> index c9d3d0c9..552e8ac 100644
> --- a/drivers/android/Makefile
> +++ b/drivers/android/Makefile
> @@ -4,3 +4,4 @@ ccflags-y += -I$(src)                   # needed for trace events
>  obj-$(CONFIG_ANDROID_BINDERFS)         += binderfs.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC)       += binder.o binder_alloc.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> +obj-$(CONFIG_BINDER_USER_TRACKING)     += binder_latency_tracer.o
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 4c3dd98..b89d75a 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2657,6 +2657,7 @@ static void binder_transaction(struct binder_proc *proc,
>                 return_error_line = __LINE__;
>                 goto err_alloc_t_failed;
>         }
> +       trace_binder_update_info(t, e);

Can this be a more descriptive name? Perhaps "trace_binder_txn_create()"

>         INIT_LIST_HEAD(&t->fd_fixups);
>         binder_stats_created(BINDER_STAT_TRANSACTION);
>         spin_lock_init(&t->lock);
> @@ -5145,6 +5146,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
>                    t->to_thread ? t->to_thread->pid : 0,
>                    t->code, t->flags, t->priority, t->need_reply);
>         spin_unlock(&t->lock);
> +       trace_print_binder_transaction_ext(m, t);

Why do you need to trace when dumping out the transaction info?

>
>         if (proc != to_proc) {
>                 /*
> diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> index ed61b3e..24d7beb 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -12,6 +12,11 @@
>  #include <linux/types.h>
>  #include <linux/uidgid.h>
>
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +#include <linux/rtc.h>
> +#include <linux/time.h>
> +#endif
> +
>  struct binder_context {
>         struct binder_node *binder_context_mgr_node;
>         struct mutex context_mgr_node_lock;
> @@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
>         uint32_t return_error;
>         uint32_t return_error_param;
>         char context_name[BINDERFS_MAX_NAME + 1];
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +       struct timespec timestamp;
> +       struct timeval tv;
> +#endif
>  };
>
>  struct binder_transaction_log {
> @@ -520,6 +529,10 @@ struct binder_transaction {
>          * during thread teardown
>          */
>         spinlock_t lock;
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +       struct timespec timestamp;
> +       struct timeval tv;
> +#endif
>  };
>
>  /**
> diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
> new file mode 100644
> index 0000000..45c14fb
> --- /dev/null
> +++ b/drivers/android/binder_latency_tracer.c
> @@ -0,0 +1,105 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2019 MediaTek Inc.
> + */
> +
> +#include <linux/module.h>
> +#include <uapi/linux/android/binder.h>
> +#include "binder_alloc.h"
> +#include "binder_internal.h"
> +#include "binder_trace.h"
> +
> +/*
> + * probe_binder_free_transaction - Output info of a delay transaction
> + * @t:          pointer to the over-time transaction
> + */
> +void probe_binder_free_transaction(void *ignore, struct binder_transaction *t)
> +{
> +       struct rtc_time tm;
> +       struct timespec *startime;
> +       struct timespec cur, sub_t;
> +
> +       ktime_get_ts(&cur);
> +       startime = &t->timestamp;
> +       sub_t = timespec_sub(cur, *startime);
> +
> +       /* if transaction time is over than 2 sec,
> +        * show timeout warning log.
> +        */
> +       if (sub_t.tv_sec < 2)
> +               return;
> +
> +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> +
> +       spin_lock(&t->lock);
> +       pr_info_ratelimited("%d: from %d:%d to %d:%d",
> +                       t->debug_id,
> +                       t->from ? t->from->proc->pid : 0,
> +                       t->from ? t->from->pid : 0,
> +                       t->to_proc ? t->to_proc->pid : 0,
> +                       t->to_thread ? t->to_thread->pid : 0);
> +       spin_unlock(&t->lock);
> +
> +       pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> +                       (unsigned int)sub_t.tv_sec,
> +                       (sub_t.tv_nsec / NSEC_PER_MSEC),
> +                       t->code,
> +                       (unsigned long)startime->tv_sec,
> +                       (startime->tv_nsec / NSEC_PER_MSEC),
> +                       (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> +                       tm.tm_hour, tm.tm_min, tm.tm_sec,
> +                       (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> +}
> +
> +static void probe_binder_update_info(void *ignore, struct binder_transaction *t,
> +                          struct binder_transaction_log_entry *e)
> +{
> +       ktime_get_ts(&e->timestamp);
> +       do_gettimeofday(&e->tv);
> +       e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
> +       memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
> +       memcpy(&t->tv, &e->tv, sizeof(struct timeval));
> +}
> +
> +static void probe_print_binder_transaction_ext(void *ignore, struct seq_file *m,
> +                                        struct binder_transaction *t)
> +{
> +       struct rtc_time tm;
> +
> +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> +       seq_printf(m,
> +                  " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
> +                  (unsigned long)t->timestamp.tv_sec,
> +                  (t->timestamp.tv_nsec / NSEC_PER_USEC),
> +                  (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> +                  tm.tm_hour, tm.tm_min, tm.tm_sec,
> +                  (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> +
> +}
> +
> +static int __init init_binder_latency_tracer(void)
> +{
> +       register_trace_binder_free_transaction(
> +                       probe_binder_free_transaction, NULL);
> +       register_trace_binder_update_info(
> +                       probe_binder_update_info, NULL);
> +       register_trace_print_binder_transaction_ext(
> +                       probe_print_binder_transaction_ext, NULL);

Ah, now the trace in the print path makes sense. Please add a more
detailed description to the commit message. Also add a comment at the
trace point that it is for modules to attach to so additional
information can be printed. Also, make the names of the tracepoints
more descriptive of what they really are ...something like
trace_binder_txn_latency_(alloc|info|free)

> +
> +       return 0;
> +}
> +
> +static void exit_binder_latency_tracer(void)
> +{
> +       unregister_trace_binder_free_transaction(
> +                       probe_binder_free_transaction, NULL);
> +       unregister_trace_binder_update_info(
> +                       probe_binder_update_info, NULL);
> +       unregister_trace_print_binder_transaction_ext(
> +                       probe_print_binder_transaction_ext, NULL);
> +}
> +
> +module_init(init_binder_latency_tracer);
> +module_exit(exit_binder_latency_tracer);
> +
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> index 7acc18d..466993e 100644
> --- a/drivers/android/binder_trace.h
> +++ b/drivers/android/binder_trace.h
> @@ -18,6 +18,7 @@
>  struct binder_ref_data;
>  struct binder_thread;
>  struct binder_transaction;
> +struct binder_transaction_log_entry;
>
>  TRACE_EVENT(binder_ioctl,
>         TP_PROTO(unsigned int cmd, unsigned long arg),
> @@ -95,6 +96,18 @@
>                   __entry->thread_todo)
>  );
>
> +DECLARE_TRACE(binder_update_info,
> +       TP_PROTO(struct binder_transaction *t,
> +                struct binder_transaction_log_entry *e),
> +       TP_ARGS(t, e)
> +);
> +
> +DECLARE_TRACE(print_binder_transaction_ext,
> +       TP_PROTO(struct seq_file *m,
> +                struct binder_transaction *t),
> +       TP_ARGS(m, t)
> +);
> +
>  TRACE_EVENT(binder_free_transaction,
>         TP_PROTO(struct binder_transaction *t),
>         TP_ARGS(t),
> @@ -115,11 +128,18 @@
>                 __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
>                 __entry->code = t->code;
>                 __entry->flags = t->flags;
> -       ),
> -       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> +#ifdef CONFIG_BINDER_USER_TRACKING
> +               __entry->start_sec = t->timestamp.tv_sec;
> +               __entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
> +#else
> +               __entry->start_sec = 0;
> +               __entry->start_nsec = 0;
> +#endif
> +       ),
> +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
>                   __entry->debug_id, __entry->from_proc, __entry->from_thread,
>                   __entry->to_proc, __entry->to_thread, __entry->code,
> -                 __entry->flags)
> +                 __entry->flags, __entry->start_sec, __entry->start_nsec)
>  );
>
>  TRACE_EVENT(binder_transaction,
> --
> 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 3/3] binder: add transaction latency tracer
  2020-05-07  8:55                             ` Greg Kroah-Hartman
@ 2020-05-11 12:32                               ` Frankie Chang
  2020-06-10 12:23                               ` [PATCH v5] binder: transaction latency tracking for user build Frankie Chang
  1 sibling, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-05-11 12:32 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, LKML, Arve Hjønnevåg, Jian-Min Liu,
	linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Thu, 2020-05-07 at 10:55 +0200, Greg Kroah-Hartman wrote:
> On Thu, May 07, 2020 at 04:10:55PM +0800, Frankie Chang wrote:
> > From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
> > 
> > Record start/end timestamp for binder transaction.
> > When transaction is completed or transaction is free,
> > it would be checked if transaction latency over threshold (2 sec),
> > if yes, printing related information for tracing.
> 
> Shouldn't that "printing" go to the trace buffer and not to the kernel
> information log?
> 

Time limitation of recording is the reason why we don't just use trace
here.

In some long time stability test, such as MTBF,
the exception is caused by a series of transactions interaction.
Some abnormal transactions may be pending for a long time ago, they 
could not be recorded due to buffer limited.

> > 
> > /* Implement details */
> > - Add latency tracer module to monitor slow transaction.
> >   The trace_binder_free_transaction would not be enabled
> >   by default. Monitoring which transaction is too slow to
> >   cause some of exceptions is important. So we hook the
> >   tracepoint to call the monitor function.
> > 
> > Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> > ---
> >  drivers/android/Kconfig                 |    8 +++
> >  drivers/android/Makefile                |    1 +
> >  drivers/android/binder.c                |    2 +
> >  drivers/android/binder_internal.h       |   13 ++++
> >  drivers/android/binder_latency_tracer.c |  105 +++++++++++++++++++++++++++++++
> >  drivers/android/binder_trace.h          |   26 +++++++-
> >  6 files changed, 152 insertions(+), 3 deletions(-)
> >  create mode 100644 drivers/android/binder_latency_tracer.c
> > 
> >  Change from v4:
> >    split up into patch series.
> > 
> >  Change from v3:
> >    use tracepoints for binder_update_info and print_binder_transaction_ext,
> >    instead of custom registration functions.
> > 
> >  Change from v2:
> >    create transaction latency module to monitor slow transaction.
> > 
> >  Change from v1:
> >    first patchset.
> > 
> > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > index 6fdf2ab..7ba80eb 100644
> > --- a/drivers/android/Kconfig
> > +++ b/drivers/android/Kconfig
> > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> >  	  exhaustively with combinations of various buffer sizes and
> >  	  alignments.
> >  
> > +config BINDER_USER_TRACKING
> > +	bool "Android Binder transaction tracking"
> > +	help
> > +	  Used for track abnormal binder transaction which is over 2 seconds,
> > +	  when the transaction is done or be free, this transaction would be
> > +	  checked whether it executed overtime.
> > +	  If yes, printing out the detail info about it.
> > +
> >  endif # if ANDROID
> >  
> >  endmenu
> > diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> > index c9d3d0c9..552e8ac 100644
> > --- a/drivers/android/Makefile
> > +++ b/drivers/android/Makefile
> > @@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
> >  obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
> >  obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
> >  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> > +obj-$(CONFIG_BINDER_USER_TRACKING)	+= binder_latency_tracer.o
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index 4c3dd98..b89d75a 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -2657,6 +2657,7 @@ static void binder_transaction(struct binder_proc *proc,
> >  		return_error_line = __LINE__;
> >  		goto err_alloc_t_failed;
> >  	}
> > +	trace_binder_update_info(t, e);
> >  	INIT_LIST_HEAD(&t->fd_fixups);
> >  	binder_stats_created(BINDER_STAT_TRANSACTION);
> >  	spin_lock_init(&t->lock);
> > @@ -5145,6 +5146,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
> >  		   t->to_thread ? t->to_thread->pid : 0,
> >  		   t->code, t->flags, t->priority, t->need_reply);
> >  	spin_unlock(&t->lock);
> > +	trace_print_binder_transaction_ext(m, t);
> >  
> >  	if (proc != to_proc) {
> >  		/*
> > diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> > index ed61b3e..24d7beb 100644
> > --- a/drivers/android/binder_internal.h
> > +++ b/drivers/android/binder_internal.h
> > @@ -12,6 +12,11 @@
> >  #include <linux/types.h>
> >  #include <linux/uidgid.h>
> >  
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +#include <linux/rtc.h>
> > +#include <linux/time.h>
> > +#endif
> > +
> >  struct binder_context {
> >  	struct binder_node *binder_context_mgr_node;
> >  	struct mutex context_mgr_node_lock;
> > @@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
> >  	uint32_t return_error;
> >  	uint32_t return_error_param;
> >  	char context_name[BINDERFS_MAX_NAME + 1];
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +	struct timespec timestamp;
> > +	struct timeval tv;
> > +#endif
> >  };
> >  
> >  struct binder_transaction_log {
> > @@ -520,6 +529,10 @@ struct binder_transaction {
> >  	 * during thread teardown
> >  	 */
> >  	spinlock_t lock;
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +	struct timespec timestamp;
> > +	struct timeval tv;
> > +#endif
> >  };
> >  
> >  /**
> > diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
> > new file mode 100644
> > index 0000000..45c14fb
> > --- /dev/null
> > +++ b/drivers/android/binder_latency_tracer.c
> > @@ -0,0 +1,105 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2019 MediaTek Inc.
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <uapi/linux/android/binder.h>
> > +#include "binder_alloc.h"
> > +#include "binder_internal.h"
> > +#include "binder_trace.h"
> > +
> > +/*
> > + * probe_binder_free_transaction - Output info of a delay transaction
> > + * @t:          pointer to the over-time transaction
> > + */
> > +void probe_binder_free_transaction(void *ignore, struct binder_transaction *t)
> > +{
> > +	struct rtc_time tm;
> > +	struct timespec *startime;
> > +	struct timespec cur, sub_t;
> > +
> > +	ktime_get_ts(&cur);
> > +	startime = &t->timestamp;
> > +	sub_t = timespec_sub(cur, *startime);
> > +
> > +	/* if transaction time is over than 2 sec,
> > +	 * show timeout warning log.
> > +	 */
> > +	if (sub_t.tv_sec < 2)
> > +		return;
> 
> Why is 2 seconds somehow "magic" here?
> 

Some of modules would trigger timeout NE if their binder transaction
don't finish in time, such as audio timeout (5 sec), even BT command
timeout (2 sec), etc.

Therefore, we want to record related transactions which exceed 2 sec. It
could be helpful to debug.

> 
> 
> > +
> > +	rtc_time_to_tm(t->tv.tv_sec, &tm);
> > +
> > +	spin_lock(&t->lock);
> > +	pr_info_ratelimited("%d: from %d:%d to %d:%d",
> > +			t->debug_id,
> > +			t->from ? t->from->proc->pid : 0,
> > +			t->from ? t->from->pid : 0,
> > +			t->to_proc ? t->to_proc->pid : 0,
> > +			t->to_thread ? t->to_thread->pid : 0);
> > +	spin_unlock(&t->lock);
> 
> Why is the lock ok to give up here and not after the next call?
> 

We would give up lock not here but after the next call, thanks for
reminding.

> > +
> > +	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> > +			(unsigned int)sub_t.tv_sec,
> > +			(sub_t.tv_nsec / NSEC_PER_MSEC),
> > +			t->code,
> > +			(unsigned long)startime->tv_sec,
> > +			(startime->tv_nsec / NSEC_PER_MSEC),
> > +			(tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > +			tm.tm_hour, tm.tm_min, tm.tm_sec,
> > +			(unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > +}
> > +
> > +static void probe_binder_update_info(void *ignore, struct binder_transaction *t,
> > +			   struct binder_transaction_log_entry *e)
> > +{
> > +	ktime_get_ts(&e->timestamp);
> > +	do_gettimeofday(&e->tv);
> > +	e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
> > +	memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
> > +	memcpy(&t->tv, &e->tv, sizeof(struct timeval));
> 
> No locking needed?
> 

We would add lock protection here, thanks a lot.


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 3/3] binder: add transaction latency tracer
  2020-05-07 18:21                             ` [PATCH v4 " Todd Kjos
@ 2020-05-11 12:35                               ` Frankie Chang
  0 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-05-11 12:35 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Thu, 2020-05-07 at 11:21 -0700, Todd Kjos wrote:
> On Thu, May 7, 2020 at 1:11 AM Frankie Chang <Frankie.Chang@mediatek.com> wrote:
> >
> > From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
> >
> > Record start/end timestamp for binder transaction.
> > When transaction is completed or transaction is free,
> > it would be checked if transaction latency over threshold (2 sec),
> 
> If this is a hard-coded threshold, provide rationale for why 2 sec is
> the right value and it doesn't need to be tunable
> 

Some of modules would trigger timeout NE if their binder transaction
don't finish in time, such as audio timeout (5 sec), even BT command
timeout (2 sec), etc.

Therefore, we want to record related transactions which exceed 2 sec. It
could be helpful to debug.

> > if yes, printing related information for tracing.
> >
> > /* Implement details */
> > - Add latency tracer module to monitor slow transaction.
> >   The trace_binder_free_transaction would not be enabled
> >   by default. Monitoring which transaction is too slow to
> >   cause some of exceptions is important. So we hook the
> >   tracepoint to call the monitor function.
> 
> Please add a more complete description. This patch adds a module to
> monitor transaction latency by attaching to new tracepoints introduced
> when transactions are allocated and freed. Describe this in the commit
> message.
> 

Okay, we would add these description in next version.

> >
> > Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> > ---
> >  drivers/android/Kconfig                 |    8 +++
> >  drivers/android/Makefile                |    1 +
> >  drivers/android/binder.c                |    2 +
> >  drivers/android/binder_internal.h       |   13 ++++
> >  drivers/android/binder_latency_tracer.c |  105 +++++++++++++++++++++++++++++++
> >  drivers/android/binder_trace.h          |   26 +++++++-
> >  6 files changed, 152 insertions(+), 3 deletions(-)
> >  create mode 100644 drivers/android/binder_latency_tracer.c
> >
> >  Change from v4:
> >    split up into patch series.
> >
> >  Change from v3:
> >    use tracepoints for binder_update_info and print_binder_transaction_ext,
> >    instead of custom registration functions.
> >
> >  Change from v2:
> >    create transaction latency module to monitor slow transaction.
> >
> >  Change from v1:
> >    first patchset.
> >
> > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > index 6fdf2ab..7ba80eb 100644
> > --- a/drivers/android/Kconfig
> > +++ b/drivers/android/Kconfig
> > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> >           exhaustively with combinations of various buffer sizes and
> >           alignments.
> >
> > +config BINDER_USER_TRACKING
> 
> Why not "BINDER_TRANSACTION_LATENCY_TRACKING"?
> 

Thanks for your advice. We would modify the config name to this proper
one.

> > +       bool "Android Binder transaction tracking"
> > +       help
> > +         Used for track abnormal binder transaction which is over 2 seconds,
> > +         when the transaction is done or be free, this transaction would be
> > +         checked whether it executed overtime.
> > +         If yes, printing out the detail info about it.
> 
> "If yes, print out the detailed info"
> 

We would modify it, thanks.

> > +
> >  endif # if ANDROID
> >
> >  endmenu
> > diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> > index c9d3d0c9..552e8ac 100644
> > --- a/drivers/android/Makefile
> > +++ b/drivers/android/Makefile
> > @@ -4,3 +4,4 @@ ccflags-y += -I$(src)                   # needed for trace events
> >  obj-$(CONFIG_ANDROID_BINDERFS)         += binderfs.o
> >  obj-$(CONFIG_ANDROID_BINDER_IPC)       += binder.o binder_alloc.o
> >  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> > +obj-$(CONFIG_BINDER_USER_TRACKING)     += binder_latency_tracer.o
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index 4c3dd98..b89d75a 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -2657,6 +2657,7 @@ static void binder_transaction(struct binder_proc *proc,
> >                 return_error_line = __LINE__;
> >                 goto err_alloc_t_failed;
> >         }
> > +       trace_binder_update_info(t, e);
> 
> Can this be a more descriptive name? Perhaps "trace_binder_txn_create()"
> 

Okay, we would replace the original name with
trace_binder_txn_latency_alloc.

> >         INIT_LIST_HEAD(&t->fd_fixups);
> >         binder_stats_created(BINDER_STAT_TRANSACTION);
> >         spin_lock_init(&t->lock);
> > @@ -5145,6 +5146,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
> >                    t->to_thread ? t->to_thread->pid : 0,
> >                    t->code, t->flags, t->priority, t->need_reply);
> >         spin_unlock(&t->lock);
> > +       trace_print_binder_transaction_ext(m, t);
> 
> Why do you need to trace when dumping out the transaction info?
> 

Because we want to get the start time about this transaction, to check
whether these transactions consume too much time.

Converting kernel time to android time let us easily correspond kernel
log to android log. But it is not necessary if you think that is too
redundant.

> >
> >         if (proc != to_proc) {
> >                 /*
> > diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> > index ed61b3e..24d7beb 100644
> > --- a/drivers/android/binder_internal.h
> > +++ b/drivers/android/binder_internal.h
> > @@ -12,6 +12,11 @@
> >  #include <linux/types.h>
> >  #include <linux/uidgid.h>
> >
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +#include <linux/rtc.h>
> > +#include <linux/time.h>
> > +#endif
> > +
> >  struct binder_context {
> >         struct binder_node *binder_context_mgr_node;
> >         struct mutex context_mgr_node_lock;
> > @@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
> >         uint32_t return_error;
> >         uint32_t return_error_param;
> >         char context_name[BINDERFS_MAX_NAME + 1];
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +       struct timespec timestamp;
> > +       struct timeval tv;
> > +#endif
> >  };
> >
> >  struct binder_transaction_log {
> > @@ -520,6 +529,10 @@ struct binder_transaction {
> >          * during thread teardown
> >          */
> >         spinlock_t lock;
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +       struct timespec timestamp;
> > +       struct timeval tv;
> > +#endif
> >  };
> >
> >  /**
> > diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
> > new file mode 100644
> > index 0000000..45c14fb
> > --- /dev/null
> > +++ b/drivers/android/binder_latency_tracer.c
> > @@ -0,0 +1,105 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2019 MediaTek Inc.
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <uapi/linux/android/binder.h>
> > +#include "binder_alloc.h"
> > +#include "binder_internal.h"
> > +#include "binder_trace.h"
> > +
> > +/*
> > + * probe_binder_free_transaction - Output info of a delay transaction
> > + * @t:          pointer to the over-time transaction
> > + */
> > +void probe_binder_free_transaction(void *ignore, struct binder_transaction *t)
> > +{
> > +       struct rtc_time tm;
> > +       struct timespec *startime;
> > +       struct timespec cur, sub_t;
> > +
> > +       ktime_get_ts(&cur);
> > +       startime = &t->timestamp;
> > +       sub_t = timespec_sub(cur, *startime);
> > +
> > +       /* if transaction time is over than 2 sec,
> > +        * show timeout warning log.
> > +        */
> > +       if (sub_t.tv_sec < 2)
> > +               return;
> > +
> > +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> > +
> > +       spin_lock(&t->lock);
> > +       pr_info_ratelimited("%d: from %d:%d to %d:%d",
> > +                       t->debug_id,
> > +                       t->from ? t->from->proc->pid : 0,
> > +                       t->from ? t->from->pid : 0,
> > +                       t->to_proc ? t->to_proc->pid : 0,
> > +                       t->to_thread ? t->to_thread->pid : 0);
> > +       spin_unlock(&t->lock);
> > +
> > +       pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> > +                       (unsigned int)sub_t.tv_sec,
> > +                       (sub_t.tv_nsec / NSEC_PER_MSEC),
> > +                       t->code,
> > +                       (unsigned long)startime->tv_sec,
> > +                       (startime->tv_nsec / NSEC_PER_MSEC),
> > +                       (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > +                       tm.tm_hour, tm.tm_min, tm.tm_sec,
> > +                       (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > +}
> > +
> > +static void probe_binder_update_info(void *ignore, struct binder_transaction *t,
> > +                          struct binder_transaction_log_entry *e)
> > +{
> > +       ktime_get_ts(&e->timestamp);
> > +       do_gettimeofday(&e->tv);
> > +       e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
> > +       memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
> > +       memcpy(&t->tv, &e->tv, sizeof(struct timeval));
> > +}
> > +
> > +static void probe_print_binder_transaction_ext(void *ignore, struct seq_file *m,
> > +                                        struct binder_transaction *t)
> > +{
> > +       struct rtc_time tm;
> > +
> > +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> > +       seq_printf(m,
> > +                  " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
> > +                  (unsigned long)t->timestamp.tv_sec,
> > +                  (t->timestamp.tv_nsec / NSEC_PER_USEC),
> > +                  (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > +                  tm.tm_hour, tm.tm_min, tm.tm_sec,
> > +                  (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > +
> > +}
> > +
> > +static int __init init_binder_latency_tracer(void)
> > +{
> > +       register_trace_binder_free_transaction(
> > +                       probe_binder_free_transaction, NULL);
> > +       register_trace_binder_update_info(
> > +                       probe_binder_update_info, NULL);
> > +       register_trace_print_binder_transaction_ext(
> > +                       probe_print_binder_transaction_ext, NULL);
> 
> Ah, now the trace in the print path makes sense. Please add a more
> detailed description to the commit message. Also add a comment at the
> trace point that it is for modules to attach to so additional
> information can be printed. Also, make the names of the tracepoints
> more descriptive of what they really are ...something like
> trace_binder_txn_latency_(alloc|info|free)
> 

Yes, we agree that this is a better way to make these tracepoints more
meaningful, and we would change it.

> > +
> > +       return 0;
> > +}
> > +
> > +static void exit_binder_latency_tracer(void)
> > +{
> > +       unregister_trace_binder_free_transaction(
> > +                       probe_binder_free_transaction, NULL);
> > +       unregister_trace_binder_update_info(
> > +                       probe_binder_update_info, NULL);
> > +       unregister_trace_print_binder_transaction_ext(
> > +                       probe_print_binder_transaction_ext, NULL);
> > +}
> > +
> > +module_init(init_binder_latency_tracer);
> > +module_exit(exit_binder_latency_tracer);
> > +
> > +MODULE_LICENSE("GPL v2");
> > diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> > index 7acc18d..466993e 100644
> > --- a/drivers/android/binder_trace.h
> > +++ b/drivers/android/binder_trace.h
> > @@ -18,6 +18,7 @@
> >  struct binder_ref_data;
> >  struct binder_thread;
> >  struct binder_transaction;
> > +struct binder_transaction_log_entry;
> >
> >  TRACE_EVENT(binder_ioctl,
> >         TP_PROTO(unsigned int cmd, unsigned long arg),
> > @@ -95,6 +96,18 @@
> >                   __entry->thread_todo)
> >  );
> >
> > +DECLARE_TRACE(binder_update_info,
> > +       TP_PROTO(struct binder_transaction *t,
> > +                struct binder_transaction_log_entry *e),
> > +       TP_ARGS(t, e)
> > +);
> > +
> > +DECLARE_TRACE(print_binder_transaction_ext,
> > +       TP_PROTO(struct seq_file *m,
> > +                struct binder_transaction *t),
> > +       TP_ARGS(m, t)
> > +);
> > +
> >  TRACE_EVENT(binder_free_transaction,
> >         TP_PROTO(struct binder_transaction *t),
> >         TP_ARGS(t),
> > @@ -115,11 +128,18 @@
> >                 __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
> >                 __entry->code = t->code;
> >                 __entry->flags = t->flags;
> > -       ),
> > -       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> > +#ifdef CONFIG_BINDER_USER_TRACKING
> > +               __entry->start_sec = t->timestamp.tv_sec;
> > +               __entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
> > +#else
> > +               __entry->start_sec = 0;
> > +               __entry->start_nsec = 0;
> > +#endif
> > +       ),
> > +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
> >                   __entry->debug_id, __entry->from_proc, __entry->from_thread,
> >                   __entry->to_proc, __entry->to_thread, __entry->code,
> > -                 __entry->flags)
> > +                 __entry->flags, __entry->start_sec, __entry->start_nsec)
> >  );
> >
> >  TRACE_EVENT(binder_transaction,
> > --
> > 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v5] binder: transaction latency tracking for user build
  2020-05-07  8:55                             ` Greg Kroah-Hartman
  2020-05-11 12:32                               ` Frankie Chang
@ 2020-06-10 12:23                               ` Frankie Chang
  2020-06-10 12:23                                 ` [PATCH v5 1/3] binder: move structs from core file to header file Frankie Chang
                                                   ` (3 more replies)
  1 sibling, 4 replies; 72+ messages in thread
From: Frankie Chang @ 2020-06-10 12:23 UTC (permalink / raw)
  To: Todd Kjos, Greg Kroah-Hartman
  Cc: wsd_upstream, LKML, Arve Hjønnevåg, Jian-Min Liu,
	linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner


Frankie.Chang (3):
  binder: move structs from core file to header file
  binder: add trace at free transaction.
  binder: add transaction latency tracer

 drivers/android/Kconfig                 |   8 +
 drivers/android/Makefile                |   1 +
 drivers/android/binder.c                | 408 +----------------------
 drivers/android/binder_internal.h       | 416 ++++++++++++++++++++++++
 drivers/android/binder_latency_tracer.c | 108 ++++++
 drivers/android/binder_trace.h          |  49 +++
 6 files changed, 586 insertions(+), 404 deletions(-)  create mode 100644 drivers/android/binder_latency_tracer.c

Change from v5:
  - change config name to the proper one, CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING.
  - change tracepoint name to more descriptive one, trace_binder_txn_latency_(alloc|info|free)
  - enhance some lock protection.

Change from v4:
  - split up into patch series.

Change from v3:
  - use tracepoints for binder_update_info and print_binder_transaction_ext,
    instead of custom registration functions.

Change from v2:
  - create transaction latency module to monitor slow transaction.

Change from v1:
  - first patchset.
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v5 1/3] binder: move structs from core file to header file
  2020-06-10 12:23                               ` [PATCH v5] binder: transaction latency tracking for user build Frankie Chang
@ 2020-06-10 12:23                                 ` Frankie Chang
  2020-06-10 12:23                                 ` [PATCH v5 2/3] binder: add trace at free transaction Frankie Chang
                                                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-06-10 12:23 UTC (permalink / raw)
  To: Todd Kjos, Greg Kroah-Hartman
  Cc: wsd_upstream, LKML, Arve Hjønnevåg, Jian-Min Liu,
	linux-mediatek, Joel Fernandes, Frankie.Chang, Martijn Coenen,
	Christian Brauner

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Moving all structs to header file makes module more
extendable, and makes all these structs to be defined
in the same file.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/binder.c          |  404 -------------------------------------
 drivers/android/binder_internal.h |  403 ++++++++++++++++++++++++++++++++++++
 2 files changed, 403 insertions(+), 404 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index a6b2082..1592396 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -160,24 +160,6 @@ static int binder_set_stop_on_user_error(const char *val,
 #define to_binder_fd_array_object(hdr) \
 	container_of(hdr, struct binder_fd_array_object, hdr)
 
-enum binder_stat_types {
-	BINDER_STAT_PROC,
-	BINDER_STAT_THREAD,
-	BINDER_STAT_NODE,
-	BINDER_STAT_REF,
-	BINDER_STAT_DEATH,
-	BINDER_STAT_TRANSACTION,
-	BINDER_STAT_TRANSACTION_COMPLETE,
-	BINDER_STAT_COUNT
-};
-
-struct binder_stats {
-	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
-	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
-	atomic_t obj_created[BINDER_STAT_COUNT];
-	atomic_t obj_deleted[BINDER_STAT_COUNT];
-};
-
 static struct binder_stats binder_stats;
 
 static inline void binder_stats_deleted(enum binder_stat_types type)
@@ -213,278 +195,11 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
 	return e;
 }
 
-/**
- * struct binder_work - work enqueued on a worklist
- * @entry:             node enqueued on list
- * @type:              type of work to be performed
- *
- * There are separate work lists for proc, thread, and node (async).
- */
-struct binder_work {
-	struct list_head entry;
-
-	enum {
-		BINDER_WORK_TRANSACTION = 1,
-		BINDER_WORK_TRANSACTION_COMPLETE,
-		BINDER_WORK_RETURN_ERROR,
-		BINDER_WORK_NODE,
-		BINDER_WORK_DEAD_BINDER,
-		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
-		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
-	} type;
-};
-
-struct binder_error {
-	struct binder_work work;
-	uint32_t cmd;
-};
-
-/**
- * struct binder_node - binder node bookkeeping
- * @debug_id:             unique ID for debugging
- *                        (invariant after initialized)
- * @lock:                 lock for node fields
- * @work:                 worklist element for node work
- *                        (protected by @proc->inner_lock)
- * @rb_node:              element for proc->nodes tree
- *                        (protected by @proc->inner_lock)
- * @dead_node:            element for binder_dead_nodes list
- *                        (protected by binder_dead_nodes_lock)
- * @proc:                 binder_proc that owns this node
- *                        (invariant after initialized)
- * @refs:                 list of references on this node
- *                        (protected by @lock)
- * @internal_strong_refs: used to take strong references when
- *                        initiating a transaction
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_weak_refs:      weak user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_strong_refs:    strong user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @tmp_refs:             temporary kernel refs
- *                        (protected by @proc->inner_lock while @proc
- *                        is valid, and by binder_dead_nodes_lock
- *                        if @proc is NULL. During inc/dec and node release
- *                        it is also protected by @lock to provide safety
- *                        as the node dies and @proc becomes NULL)
- * @ptr:                  userspace pointer for node
- *                        (invariant, no lock needed)
- * @cookie:               userspace cookie for node
- *                        (invariant, no lock needed)
- * @has_strong_ref:       userspace notified of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_strong_ref:   userspace has acked notification of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_weak_ref:         userspace notified of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_weak_ref:     userspace has acked notification of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_async_transaction: async transaction to node in progress
- *                        (protected by @lock)
- * @accept_fds:           file descriptor operations supported for node
- *                        (invariant after initialized)
- * @min_priority:         minimum scheduling priority
- *                        (invariant after initialized)
- * @txn_security_ctx:     require sender's security context
- *                        (invariant after initialized)
- * @async_todo:           list of async work items
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder nodes.
- */
-struct binder_node {
-	int debug_id;
-	spinlock_t lock;
-	struct binder_work work;
-	union {
-		struct rb_node rb_node;
-		struct hlist_node dead_node;
-	};
-	struct binder_proc *proc;
-	struct hlist_head refs;
-	int internal_strong_refs;
-	int local_weak_refs;
-	int local_strong_refs;
-	int tmp_refs;
-	binder_uintptr_t ptr;
-	binder_uintptr_t cookie;
-	struct {
-		/*
-		 * bitfield elements protected by
-		 * proc inner_lock
-		 */
-		u8 has_strong_ref:1;
-		u8 pending_strong_ref:1;
-		u8 has_weak_ref:1;
-		u8 pending_weak_ref:1;
-	};
-	struct {
-		/*
-		 * invariant after initialization
-		 */
-		u8 accept_fds:1;
-		u8 txn_security_ctx:1;
-		u8 min_priority;
-	};
-	bool has_async_transaction;
-	struct list_head async_todo;
-};
-
-struct binder_ref_death {
-	/**
-	 * @work: worklist element for death notifications
-	 *        (protected by inner_lock of the proc that
-	 *        this ref belongs to)
-	 */
-	struct binder_work work;
-	binder_uintptr_t cookie;
-};
-
-/**
- * struct binder_ref_data - binder_ref counts and id
- * @debug_id:        unique ID for the ref
- * @desc:            unique userspace handle for ref
- * @strong:          strong ref count (debugging only if not locked)
- * @weak:            weak ref count (debugging only if not locked)
- *
- * Structure to hold ref count and ref id information. Since
- * the actual ref can only be accessed with a lock, this structure
- * is used to return information about the ref to callers of
- * ref inc/dec functions.
- */
-struct binder_ref_data {
-	int debug_id;
-	uint32_t desc;
-	int strong;
-	int weak;
-};
-
-/**
- * struct binder_ref - struct to track references on nodes
- * @data:        binder_ref_data containing id, handle, and current refcounts
- * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
- * @rb_node_node: node for lookup by @node in proc's rb_tree
- * @node_entry:  list entry for node->refs list in target node
- *               (protected by @node->lock)
- * @proc:        binder_proc containing ref
- * @node:        binder_node of target node. When cleaning up a
- *               ref for deletion in binder_cleanup_ref, a non-NULL
- *               @node indicates the node must be freed
- * @death:       pointer to death notification (ref_death) if requested
- *               (protected by @node->lock)
- *
- * Structure to track references from procA to target node (on procB). This
- * structure is unsafe to access without holding @proc->outer_lock.
- */
-struct binder_ref {
-	/* Lookups needed: */
-	/*   node + proc => ref (transaction) */
-	/*   desc + proc => ref (transaction, inc/dec ref) */
-	/*   node => refs + procs (proc exit) */
-	struct binder_ref_data data;
-	struct rb_node rb_node_desc;
-	struct rb_node rb_node_node;
-	struct hlist_node node_entry;
-	struct binder_proc *proc;
-	struct binder_node *node;
-	struct binder_ref_death *death;
-};
-
 enum binder_deferred_state {
 	BINDER_DEFERRED_FLUSH        = 0x01,
 	BINDER_DEFERRED_RELEASE      = 0x02,
 };
 
-/**
- * struct binder_proc - binder process bookkeeping
- * @proc_node:            element for binder_procs list
- * @threads:              rbtree of binder_threads in this proc
- *                        (protected by @inner_lock)
- * @nodes:                rbtree of binder nodes associated with
- *                        this proc ordered by node->ptr
- *                        (protected by @inner_lock)
- * @refs_by_desc:         rbtree of refs ordered by ref->desc
- *                        (protected by @outer_lock)
- * @refs_by_node:         rbtree of refs ordered by ref->node
- *                        (protected by @outer_lock)
- * @waiting_threads:      threads currently waiting for proc work
- *                        (protected by @inner_lock)
- * @pid                   PID of group_leader of process
- *                        (invariant after initialized)
- * @tsk                   task_struct for group_leader of process
- *                        (invariant after initialized)
- * @deferred_work_node:   element for binder_deferred_list
- *                        (protected by binder_deferred_lock)
- * @deferred_work:        bitmap of deferred work to perform
- *                        (protected by binder_deferred_lock)
- * @is_dead:              process is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @inner_lock)
- * @todo:                 list of work for this process
- *                        (protected by @inner_lock)
- * @stats:                per-process binder statistics
- *                        (atomics, no lock needed)
- * @delivered_death:      list of delivered death notification
- *                        (protected by @inner_lock)
- * @max_threads:          cap on number of binder threads
- *                        (protected by @inner_lock)
- * @requested_threads:    number of binder threads requested but not
- *                        yet started. In current implementation, can
- *                        only be 0 or 1.
- *                        (protected by @inner_lock)
- * @requested_threads_started: number binder threads started
- *                        (protected by @inner_lock)
- * @tmp_ref:              temporary reference to indicate proc is in use
- *                        (protected by @inner_lock)
- * @default_priority:     default scheduler priority
- *                        (invariant after initialized)
- * @debugfs_entry:        debugfs node
- * @alloc:                binder allocator bookkeeping
- * @context:              binder_context for this proc
- *                        (invariant after initialized)
- * @inner_lock:           can nest under outer_lock and/or node lock
- * @outer_lock:           no nesting under innor or node lock
- *                        Lock order: 1) outer, 2) node, 3) inner
- * @binderfs_entry:       process-specific binderfs log file
- *
- * Bookkeeping structure for binder processes
- */
-struct binder_proc {
-	struct hlist_node proc_node;
-	struct rb_root threads;
-	struct rb_root nodes;
-	struct rb_root refs_by_desc;
-	struct rb_root refs_by_node;
-	struct list_head waiting_threads;
-	int pid;
-	struct task_struct *tsk;
-	struct hlist_node deferred_work_node;
-	int deferred_work;
-	bool is_dead;
-
-	struct list_head todo;
-	struct binder_stats stats;
-	struct list_head delivered_death;
-	int max_threads;
-	int requested_threads;
-	int requested_threads_started;
-	int tmp_ref;
-	long default_priority;
-	struct dentry *debugfs_entry;
-	struct binder_alloc alloc;
-	struct binder_context *context;
-	spinlock_t inner_lock;
-	spinlock_t outer_lock;
-	struct dentry *binderfs_entry;
-};
-
 enum {
 	BINDER_LOOPER_STATE_REGISTERED  = 0x01,
 	BINDER_LOOPER_STATE_ENTERED     = 0x02,
@@ -495,125 +210,6 @@ enum {
 };
 
 /**
- * struct binder_thread - binder thread bookkeeping
- * @proc:                 binder process for this thread
- *                        (invariant after initialization)
- * @rb_node:              element for proc->threads rbtree
- *                        (protected by @proc->inner_lock)
- * @waiting_thread_node:  element for @proc->waiting_threads list
- *                        (protected by @proc->inner_lock)
- * @pid:                  PID for this thread
- *                        (invariant after initialization)
- * @looper:               bitmap of looping state
- *                        (only accessed by this thread)
- * @looper_needs_return:  looping thread needs to exit driver
- *                        (no lock needed)
- * @transaction_stack:    stack of in-progress transactions for this thread
- *                        (protected by @proc->inner_lock)
- * @todo:                 list of work to do for this thread
- *                        (protected by @proc->inner_lock)
- * @process_todo:         whether work in @todo should be processed
- *                        (protected by @proc->inner_lock)
- * @return_error:         transaction errors reported by this thread
- *                        (only accessed by this thread)
- * @reply_error:          transaction errors reported by target thread
- *                        (protected by @proc->inner_lock)
- * @wait:                 wait queue for thread work
- * @stats:                per-thread statistics
- *                        (atomics, no lock needed)
- * @tmp_ref:              temporary reference to indicate thread is in use
- *                        (atomic since @proc->inner_lock cannot
- *                        always be acquired)
- * @is_dead:              thread is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder threads.
- */
-struct binder_thread {
-	struct binder_proc *proc;
-	struct rb_node rb_node;
-	struct list_head waiting_thread_node;
-	int pid;
-	int looper;              /* only modified by this thread */
-	bool looper_need_return; /* can be written by other thread */
-	struct binder_transaction *transaction_stack;
-	struct list_head todo;
-	bool process_todo;
-	struct binder_error return_error;
-	struct binder_error reply_error;
-	wait_queue_head_t wait;
-	struct binder_stats stats;
-	atomic_t tmp_ref;
-	bool is_dead;
-};
-
-/**
- * struct binder_txn_fd_fixup - transaction fd fixup list element
- * @fixup_entry:          list entry
- * @file:                 struct file to be associated with new fd
- * @offset:               offset in buffer data to this fixup
- *
- * List element for fd fixups in a transaction. Since file
- * descriptors need to be allocated in the context of the
- * target process, we pass each fd to be processed in this
- * struct.
- */
-struct binder_txn_fd_fixup {
-	struct list_head fixup_entry;
-	struct file *file;
-	size_t offset;
-};
-
-struct binder_transaction {
-	int debug_id;
-	struct binder_work work;
-	struct binder_thread *from;
-	struct binder_transaction *from_parent;
-	struct binder_proc *to_proc;
-	struct binder_thread *to_thread;
-	struct binder_transaction *to_parent;
-	unsigned need_reply:1;
-	/* unsigned is_dead:1; */	/* not used at the moment */
-
-	struct binder_buffer *buffer;
-	unsigned int	code;
-	unsigned int	flags;
-	long	priority;
-	long	saved_priority;
-	kuid_t	sender_euid;
-	struct list_head fd_fixups;
-	binder_uintptr_t security_ctx;
-	/**
-	 * @lock:  protects @from, @to_proc, and @to_thread
-	 *
-	 * @from, @to_proc, and @to_thread can be set to NULL
-	 * during thread teardown
-	 */
-	spinlock_t lock;
-};
-
-/**
- * struct binder_object - union of flat binder object types
- * @hdr:   generic object header
- * @fbo:   binder object (nodes and refs)
- * @fdo:   file descriptor object
- * @bbo:   binder buffer pointer
- * @fdao:  file descriptor array
- *
- * Used for type-independent object copies
- */
-struct binder_object {
-	union {
-		struct binder_object_header hdr;
-		struct flat_binder_object fbo;
-		struct binder_fd_object fdo;
-		struct binder_buffer_object bbo;
-		struct binder_fd_array_object fdao;
-	};
-};
-
-/**
  * binder_proc_lock() - Acquire outer lock for given binder_proc
  * @proc:         struct binder_proc to acquire
  *
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index ae99109..ed61b3e 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -139,6 +139,409 @@ struct binder_transaction_log {
 	struct binder_transaction_log_entry entry[32];
 };
 
+enum binder_stat_types {
+	BINDER_STAT_PROC,
+	BINDER_STAT_THREAD,
+	BINDER_STAT_NODE,
+	BINDER_STAT_REF,
+	BINDER_STAT_DEATH,
+	BINDER_STAT_TRANSACTION,
+	BINDER_STAT_TRANSACTION_COMPLETE,
+	BINDER_STAT_COUNT
+};
+
+struct binder_stats {
+	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
+	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
+	atomic_t obj_created[BINDER_STAT_COUNT];
+	atomic_t obj_deleted[BINDER_STAT_COUNT];
+};
+
+/**
+ * struct binder_work - work enqueued on a worklist
+ * @entry:             node enqueued on list
+ * @type:              type of work to be performed
+ *
+ * There are separate work lists for proc, thread, and node (async).
+ */
+struct binder_work {
+	struct list_head entry;
+
+	enum {
+		BINDER_WORK_TRANSACTION = 1,
+		BINDER_WORK_TRANSACTION_COMPLETE,
+		BINDER_WORK_RETURN_ERROR,
+		BINDER_WORK_NODE,
+		BINDER_WORK_DEAD_BINDER,
+		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
+		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
+	} type;
+};
+
+struct binder_error {
+	struct binder_work work;
+	uint32_t cmd;
+};
+
+/* struct binder_node - binder node bookkeeping
+ * @debug_id:             unique ID for debugging
+ *                        (invariant after initialized)
+ * @lock:                 lock for node fields
+ * @work:                 worklist element for node work
+ *                        (protected by @proc->inner_lock)
+ * @rb_node:              element for proc->nodes tree
+ *                        (protected by @proc->inner_lock)
+ * @dead_node:            element for binder_dead_nodes list
+ *                        (protected by binder_dead_nodes_lock)
+ * @proc:                 binder_proc that owns this node
+ *                        (invariant after initialized)
+ * @refs:                 list of references on this node
+ *                        (protected by @lock)
+ * @internal_strong_refs: used to take strong references when
+ *                        initiating a transaction
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_weak_refs:      weak user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_strong_refs:    strong user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @tmp_refs:             temporary kernel refs
+ *                        (protected by @proc->inner_lock while @proc
+ *                        is valid, and by binder_dead_nodes_lock
+ *                        if @proc is NULL. During inc/dec and node release
+ *                        it is also protected by @lock to provide safety
+ *                        as the node dies and @proc becomes NULL)
+ * @ptr:                  userspace pointer for node
+ *                        (invariant, no lock needed)
+ * @cookie:               userspace cookie for node
+ *                        (invariant, no lock needed)
+ * @has_strong_ref:       userspace notified of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_strong_ref:   userspace has acked notification of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_weak_ref:         userspace notified of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_weak_ref:     userspace has acked notification of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_async_transaction: async transaction to node in progress
+ *                        (protected by @lock)
+ * @accept_fds:           file descriptor operations supported for node
+ *                        (invariant after initialized)
+ * @min_priority:         minimum scheduling priority
+ *                        (invariant after initialized)
+ * @txn_security_ctx:     require sender's security context
+ *                        (invariant after initialized)
+ * @async_todo:           list of async work items
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder nodes.
+ */
+struct binder_node {
+	int debug_id;
+	spinlock_t lock;
+	struct binder_work work;
+	union {
+		struct rb_node rb_node;
+		struct hlist_node dead_node;
+	};
+	struct binder_proc *proc;
+	struct hlist_head refs;
+	int internal_strong_refs;
+	int local_weak_refs;
+	int local_strong_refs;
+	int tmp_refs;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
+	struct {
+		/*
+		 * bitfield elements protected by
+		 * proc inner_lock
+		 */
+		u8 has_strong_ref:1;
+		u8 pending_strong_ref:1;
+		u8 has_weak_ref:1;
+		u8 pending_weak_ref:1;
+	};
+	struct {
+		/*
+		 * invariant after initialization
+		 */
+		u8 accept_fds:1;
+		u8 txn_security_ctx:1;
+		u8 min_priority;
+	};
+	bool has_async_transaction;
+	struct list_head async_todo;
+};
+
+struct binder_ref_death {
+	/**
+	 * @work: worklist element for death notifications
+	 *        (protected by inner_lock of the proc that
+	 *        this ref belongs to)
+	 */
+	struct binder_work work;
+	binder_uintptr_t cookie;
+};
+
+/**
+ * struct binder_ref_data - binder_ref counts and id
+ * @debug_id:        unique ID for the ref
+ * @desc:            unique userspace handle for ref
+ * @strong:          strong ref count (debugging only if not locked)
+ * @weak:            weak ref count (debugging only if not locked)
+ *
+ * Structure to hold ref count and ref id information. Since
+ * the actual ref can only be accessed with a lock, this structure
+ * is used to return information about the ref to callers of
+ * ref inc/dec functions.
+ */
+struct binder_ref_data {
+	int debug_id;
+	uint32_t desc;
+	int strong;
+	int weak;
+};
+
+/**
+ * struct binder_ref - struct to track references on nodes
+ * @data:        binder_ref_data containing id, handle, and current refcounts
+ * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
+ * @rb_node_node: node for lookup by @node in proc's rb_tree
+ * @node_entry:  list entry for node->refs list in target node
+ *               (protected by @node->lock)
+ * @proc:        binder_proc containing ref
+ * @node:        binder_node of target node. When cleaning up a
+ *               ref for deletion in binder_cleanup_ref, a non-NULL
+ *               @node indicates the node must be freed
+ * @death:       pointer to death notification (ref_death) if requested
+ *               (protected by @node->lock)
+ *
+ * Structure to track references from procA to target node (on procB). This
+ * structure is unsafe to access without holding @proc->outer_lock.
+ */
+struct binder_ref {
+	/* Lookups needed: */
+	/*   node + proc => ref (transaction) */
+	/*   desc + proc => ref (transaction, inc/dec ref) */
+	/*   node => refs + procs (proc exit) */
+	struct binder_ref_data data;
+	struct rb_node rb_node_desc;
+	struct rb_node rb_node_node;
+	struct hlist_node node_entry;
+	struct binder_proc *proc;
+	struct binder_node *node;
+	struct binder_ref_death *death;
+};
+
+/**
+ * struct binder_proc - binder process bookkeeping
+ * @proc_node:            element for binder_procs list
+ * @threads:              rbtree of binder_threads in this proc
+ *                        (protected by @inner_lock)
+ * @nodes:                rbtree of binder nodes associated with
+ *                        this proc ordered by node->ptr
+ *                        (protected by @inner_lock)
+ * @refs_by_desc:         rbtree of refs ordered by ref->desc
+ *                        (protected by @outer_lock)
+ * @refs_by_node:         rbtree of refs ordered by ref->node
+ *                        (protected by @outer_lock)
+ * @waiting_threads:      threads currently waiting for proc work
+ *                        (protected by @inner_lock)
+ * @pid                   PID of group_leader of process
+ *                        (invariant after initialized)
+ * @tsk                   task_struct for group_leader of process
+ *                        (invariant after initialized)
+ * @deferred_work_node:   element for binder_deferred_list
+ *                        (protected by binder_deferred_lock)
+ * @deferred_work:        bitmap of deferred work to perform
+ *                        (protected by binder_deferred_lock)
+ * @is_dead:              process is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @inner_lock)
+ * @todo:                 list of work for this process
+ *                        (protected by @inner_lock)
+ * @stats:                per-process binder statistics
+ *                        (atomics, no lock needed)
+ * @delivered_death:      list of delivered death notification
+ *                        (protected by @inner_lock)
+ * @max_threads:          cap on number of binder threads
+ *                        (protected by @inner_lock)
+ * @requested_threads:    number of binder threads requested but not
+ *                        yet started. In current implementation, can
+ *                        only be 0 or 1.
+ *                        (protected by @inner_lock)
+ * @requested_threads_started: number binder threads started
+ *                        (protected by @inner_lock)
+ * @tmp_ref:              temporary reference to indicate proc is in use
+ *                        (protected by @inner_lock)
+ * @default_priority:     default scheduler priority
+ *                        (invariant after initialized)
+ * @debugfs_entry:        debugfs node
+ * @alloc:                binder allocator bookkeeping
+ * @context:              binder_context for this proc
+ *                        (invariant after initialized)
+ * @inner_lock:           can nest under outer_lock and/or node lock
+ * @outer_lock:           no nesting under innor or node lock
+ *                        Lock order: 1) outer, 2) node, 3) inner
+ * @binderfs_entry:       process-specific binderfs log file
+ *
+ * Bookkeeping structure for binder processes
+ */
+struct binder_proc {
+	struct hlist_node proc_node;
+	struct rb_root threads;
+	struct rb_root nodes;
+	struct rb_root refs_by_desc;
+	struct rb_root refs_by_node;
+	struct list_head waiting_threads;
+	int pid;
+	struct task_struct *tsk;
+	struct hlist_node deferred_work_node;
+	int deferred_work;
+	bool is_dead;
+
+	struct list_head todo;
+	struct binder_stats stats;
+	struct list_head delivered_death;
+	int max_threads;
+	int requested_threads;
+	int requested_threads_started;
+	int tmp_ref;
+	long default_priority;
+	struct dentry *debugfs_entry;
+	struct binder_alloc alloc;
+	struct binder_context *context;
+	spinlock_t inner_lock;
+	spinlock_t outer_lock;
+	struct dentry *binderfs_entry;
+};
+
+/**
+ * struct binder_thread - binder thread bookkeeping
+ * @proc:                 binder process for this thread
+ *                        (invariant after initialization)
+ * @rb_node:              element for proc->threads rbtree
+ *                        (protected by @proc->inner_lock)
+ * @waiting_thread_node:  element for @proc->waiting_threads list
+ *                        (protected by @proc->inner_lock)
+ * @pid:                  PID for this thread
+ *                        (invariant after initialization)
+ * @looper:               bitmap of looping state
+ *                        (only accessed by this thread)
+ * @looper_needs_return:  looping thread needs to exit driver
+ *                        (no lock needed)
+ * @transaction_stack:    stack of in-progress transactions for this thread
+ *                        (protected by @proc->inner_lock)
+ * @todo:                 list of work to do for this thread
+ *                        (protected by @proc->inner_lock)
+ * @process_todo:         whether work in @todo should be processed
+ *                        (protected by @proc->inner_lock)
+ * @return_error:         transaction errors reported by this thread
+ *                        (only accessed by this thread)
+ * @reply_error:          transaction errors reported by target thread
+ *                        (protected by @proc->inner_lock)
+ * @wait:                 wait queue for thread work
+ * @stats:                per-thread statistics
+ *                        (atomics, no lock needed)
+ * @tmp_ref:              temporary reference to indicate thread is in use
+ *                        (atomic since @proc->inner_lock cannot
+ *                        always be acquired)
+ * @is_dead:              thread is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder threads.
+ */
+struct binder_thread {
+	struct binder_proc *proc;
+	struct rb_node rb_node;
+	struct list_head waiting_thread_node;
+	int pid;
+	int looper;              /* only modified by this thread */
+	bool looper_need_return; /* can be written by other thread */
+	struct binder_transaction *transaction_stack;
+	struct list_head todo;
+	bool process_todo;
+	struct binder_error return_error;
+	struct binder_error reply_error;
+	wait_queue_head_t wait;
+	struct binder_stats stats;
+	atomic_t tmp_ref;
+	bool is_dead;
+};
+
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry:          list entry
+ * @file:                 struct file to be associated with new fd
+ * @offset:               offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+	struct list_head fixup_entry;
+	struct file *file;
+	size_t offset;
+};
+
+struct binder_transaction {
+	int debug_id;
+	struct binder_work work;
+	struct binder_thread *from;
+	struct binder_transaction *from_parent;
+	struct binder_proc *to_proc;
+	struct binder_thread *to_thread;
+	struct binder_transaction *to_parent;
+	unsigned need_reply:1;
+	/* unsigned is_dead:1; */       /* not used at the moment */
+
+	struct binder_buffer *buffer;
+	unsigned int    code;
+	unsigned int    flags;
+	long    priority;
+	long    saved_priority;
+	kuid_t  sender_euid;
+	struct list_head fd_fixups;
+	binder_uintptr_t security_ctx;
+	/**
+	 * @lock:  protects @from, @to_proc, and @to_thread
+	 *
+	 * @from, @to_proc, and @to_thread can be set to NULL
+	 * during thread teardown
+	 */
+	spinlock_t lock;
+};
+
+/**
+ * struct binder_object - union of flat binder object types
+ * @hdr:   generic object header
+ * @fbo:   binder object (nodes and refs)
+ * @fdo:   file descriptor object
+ * @bbo:   binder buffer pointer
+ * @fdao:  file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+	union {
+		struct binder_object_header hdr;
+		struct flat_binder_object fbo;
+		struct binder_fd_object fdo;
+		struct binder_buffer_object bbo;
+		struct binder_fd_array_object fdao;
+	};
+};
+
 extern struct binder_transaction_log binder_transaction_log;
 extern struct binder_transaction_log binder_transaction_log_failed;
 #endif /* _LINUX_BINDER_INTERNAL_H */
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v5 2/3] binder: add trace at free transaction.
  2020-06-10 12:23                               ` [PATCH v5] binder: transaction latency tracking for user build Frankie Chang
  2020-06-10 12:23                                 ` [PATCH v5 1/3] binder: move structs from core file to header file Frankie Chang
@ 2020-06-10 12:23                                 ` Frankie Chang
  2020-07-20 18:23                                   ` Todd Kjos
  2020-06-10 12:23                                 ` [PATCH v5 3/3] binder: add transaction latency tracer Frankie Chang
  2020-07-02 13:25                                 ` [PATCH v5] binder: transaction latency tracking for user build Frankie Chang
  3 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-06-10 12:23 UTC (permalink / raw)
  To: Todd Kjos, Greg Kroah-Hartman
  Cc: wsd_upstream, LKML, Arve Hjønnevåg, Jian-Min Liu,
	linux-mediatek, Joel Fernandes, Frankie.Chang, Martijn Coenen,
	Christian Brauner

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Since the original trace_binder_transaction_received cannot
precisely present the real finished time of transaction, adding a
trace_binder_txn_latency_free at the point of free transaction
may be more close to it.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/binder.c       |    2 ++
 drivers/android/binder_trace.h |   27 +++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 1592396..5ec9af8 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1523,6 +1523,7 @@ static void binder_free_transaction(struct binder_transaction *t)
 	 * If the transaction has no target_proc, then
 	 * t->buffer->transaction has already been cleared.
 	 */
+	trace_binder_txn_latency_free(t);
 	binder_free_txn_fixups(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
@@ -3094,6 +3095,7 @@ static void binder_transaction(struct binder_proc *proc,
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 err_alloc_tcomplete_failed:
+	trace_binder_txn_latency_free(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
 err_alloc_t_failed:
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 6731c3c..8ac87d1 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,33 @@
 		  __entry->thread_todo)
 );
 
+TRACE_EVENT(binder_txn_latency_free,
+	TP_PROTO(struct binder_transaction *t),
+	TP_ARGS(t),
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, from_proc)
+		__field(int, from_thread)
+		__field(int, to_proc)
+		__field(int, to_thread)
+		__field(unsigned int, code)
+		__field(unsigned int, flags)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->from_proc = t->from ? t->from->proc->pid : 0;
+		__entry->from_thread = t->from ? t->from->pid : 0;
+		__entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
+		__entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
+		__entry->code = t->code;
+		__entry->flags = t->flags;
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
+		  __entry->to_proc, __entry->to_thread, __entry->code,
+		  __entry->flags)
+);
+
 TRACE_EVENT(binder_transaction,
 	TP_PROTO(bool reply, struct binder_transaction *t,
 		 struct binder_node *target_node),
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v5 3/3] binder: add transaction latency tracer
  2020-06-10 12:23                               ` [PATCH v5] binder: transaction latency tracking for user build Frankie Chang
  2020-06-10 12:23                                 ` [PATCH v5 1/3] binder: move structs from core file to header file Frankie Chang
  2020-06-10 12:23                                 ` [PATCH v5 2/3] binder: add trace at free transaction Frankie Chang
@ 2020-06-10 12:23                                 ` Frankie Chang
  2020-07-20 18:56                                   ` Todd Kjos
  2020-07-02 13:25                                 ` [PATCH v5] binder: transaction latency tracking for user build Frankie Chang
  3 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-06-10 12:23 UTC (permalink / raw)
  To: Todd Kjos, Greg Kroah-Hartman
  Cc: wsd_upstream, LKML, Arve Hjønnevåg, Jian-Min Liu,
	linux-mediatek, Joel Fernandes, Frankie.Chang, Martijn Coenen,
	Christian Brauner

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Record start/end timestamp for binder transaction.
When transaction is completed or transaction is free,
it would be checked if transaction latency over threshold (2 sec),
if yes, printing related information for tracing.

/* Implement details */
- Add latency tracer module to monitor transaction
  by attaching to new tracepoints introduced
  when transactions are allocated and freed.
  The trace_binder_txn_latency_free would not be enabled
  by default. Monitoring which transaction is too slow to
  cause some of exceptions is important. So we hook the
  tracepoint to call the monitor function.

- Since some of modules would trigger timeout NE
  if their binder transaction don't finish in time,
  such as audio timeout (5 sec), even BT command
  timeout (2 sec), etc.
  Therefore, setting the timeout threshold as 2 seconds
  could be helpful to debug.

- The reason why printing the related information to
  kernel information log but not trace buffer is that
  some abnormal transactions may be pending for a long
  time ago, they could not be recorded due to buffer
  limited.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/Kconfig                 |    8 +++
 drivers/android/Makefile                |    1 +
 drivers/android/binder.c                |    2 +
 drivers/android/binder_internal.h       |   13 ++++
 drivers/android/binder_latency_tracer.c |  107 +++++++++++++++++++++++++++++++
 drivers/android/binder_trace.h          |   28 +++++++-
 6 files changed, 156 insertions(+), 3 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 6fdf2ab..39d47be 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
 	  exhaustively with combinations of various buffer sizes and
 	  alignments.
 
+config BINDER_TRANSACTION_LATENCY_TRACKING
+	bool "Android Binder transaction tracking"
+	help
+	  Used for track abnormal binder transaction which is over 2 seconds,
+	  when the transaction is done or be free, this transaction would be
+	  checked whether it executed overtime.
+	  If yes, printing out the detailed info.
+
 endif # if ANDROID
 
 endmenu
diff --git a/drivers/android/Makefile b/drivers/android/Makefile
index c9d3d0c9..c2ffdb6 100644
--- a/drivers/android/Makefile
+++ b/drivers/android/Makefile
@@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
 obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
 obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
 obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
+obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)	+= binder_latency_tracer.o
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 5ec9af8..846d69b 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2657,6 +2657,7 @@ static void binder_transaction(struct binder_proc *proc,
 		return_error_line = __LINE__;
 		goto err_alloc_t_failed;
 	}
+	trace_binder_txn_latency_alloc(t, e);
 	INIT_LIST_HEAD(&t->fd_fixups);
 	binder_stats_created(BINDER_STAT_TRANSACTION);
 	spin_lock_init(&t->lock);
@@ -5144,6 +5145,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
 		   to_proc ? to_proc->pid : 0,
 		   t->to_thread ? t->to_thread->pid : 0,
 		   t->code, t->flags, t->priority, t->need_reply);
+	trace_binder_txn_latency_info(m, t);
 	spin_unlock(&t->lock);
 
 	if (proc != to_proc) {
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index ed61b3e..bebc185 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -12,6 +12,11 @@
 #include <linux/types.h>
 #include <linux/uidgid.h>
 
+#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING
+#include <linux/rtc.h>
+#include <linux/time.h>
+#endif
+
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
 	struct mutex context_mgr_node_lock;
@@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
 	uint32_t return_error;
 	uint32_t return_error_param;
 	char context_name[BINDERFS_MAX_NAME + 1];
+#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING
+	struct timespec timestamp;
+	struct timeval tv;
+#endif
 };
 
 struct binder_transaction_log {
@@ -520,6 +529,10 @@ struct binder_transaction {
 	 * during thread teardown
 	 */
 	spinlock_t lock;
+#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING
+	struct timespec timestamp;
+	struct timeval tv;
+#endif
 };
 
 /**
diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
new file mode 100644
index 0000000..1b89634
--- /dev/null
+++ b/drivers/android/binder_latency_tracer.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ */
+
+#include <linux/module.h>
+#include <uapi/linux/android/binder.h>
+#include "binder_alloc.h"
+#include "binder_internal.h"
+#include "binder_trace.h"
+
+/*
+ * probe_binder_txn_latency_free - Output info of a delay transaction
+ * @t:          pointer to the over-time transaction
+ */
+void probe_binder_txn_latency_free(void *ignore, struct binder_transaction *t)
+{
+	struct rtc_time tm;
+	struct timespec *startime;
+	struct timespec cur, sub_t;
+
+	ktime_get_ts(&cur);
+	startime = &t->timestamp;
+	sub_t = timespec_sub(cur, *startime);
+
+	/* if transaction time is over than 2 sec,
+	 * show timeout warning log.
+	 */
+	if (sub_t.tv_sec < 2)
+		return;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+
+	spin_lock(&t->lock);
+	pr_info_ratelimited("%d: from %d:%d to %d:%d",
+			t->debug_id,
+			t->from ? t->from->proc->pid : 0,
+			t->from ? t->from->pid : 0,
+			t->to_proc ? t->to_proc->pid : 0,
+			t->to_thread ? t->to_thread->pid : 0);
+
+	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
+			(unsigned int)sub_t.tv_sec,
+			(sub_t.tv_nsec / NSEC_PER_MSEC),
+			t->code,
+			(unsigned long)startime->tv_sec,
+			(startime->tv_nsec / NSEC_PER_MSEC),
+			(tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+			tm.tm_hour, tm.tm_min, tm.tm_sec,
+			(unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+	spin_unlock(&t->lock);
+}
+
+static void probe_binder_txn_latency_alloc(void *ignore,
+					struct binder_transaction *t,
+					struct binder_transaction_log_entry *e)
+{
+	ktime_get_ts(&e->timestamp);
+	do_gettimeofday(&e->tv);
+	e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
+	spin_lock(&t->lock);
+	memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
+	memcpy(&t->tv, &e->tv, sizeof(struct timeval));
+	spin_unlock(&t->lock);
+}
+
+static void probe_binder_txn_latency_info(void *ignore, struct seq_file *m,
+					struct binder_transaction *t)
+{
+	struct rtc_time tm;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+	seq_printf(m,
+		   " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
+		   (unsigned long)t->timestamp.tv_sec,
+		   (t->timestamp.tv_nsec / NSEC_PER_USEC),
+		   (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+		   tm.tm_hour, tm.tm_min, tm.tm_sec,
+		   (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+
+static int __init init_binder_latency_tracer(void)
+{
+	register_trace_binder_txn_latency_free(
+			probe_binder_txn_latency_free, NULL);
+	register_trace_binder_txn_latency_alloc(
+			probe_binder_txn_latency_alloc, NULL);
+	register_trace_binder_txn_latency_info(
+			probe_binder_txn_latency_info, NULL);
+
+	return 0;
+}
+
+static void exit_binder_latency_tracer(void)
+{
+	unregister_trace_binder_txn_latency_free(
+			probe_binder_txn_latency_free, NULL);
+	unregister_trace_binder_txn_latency_alloc(
+			probe_binder_txn_latency_alloc, NULL);
+	unregister_trace_binder_txn_latency_info(
+			probe_binder_txn_latency_info, NULL);
+}
+
+module_init(init_binder_latency_tracer);
+module_exit(exit_binder_latency_tracer);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 8ac87d1..ca41c7d 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -18,6 +18,7 @@
 struct binder_ref_data;
 struct binder_thread;
 struct binder_transaction;
+struct binder_transaction_log_entry;
 
 TRACE_EVENT(binder_ioctl,
 	TP_PROTO(unsigned int cmd, unsigned long arg),
@@ -95,6 +96,18 @@
 		  __entry->thread_todo)
 );
 
+DECLARE_TRACE(binder_txn_latency_alloc,
+	TP_PROTO(struct binder_transaction *t,
+		 struct binder_transaction_log_entry *e),
+	TP_ARGS(t, e)
+);
+
+DECLARE_TRACE(binder_txn_latency_info,
+	TP_PROTO(struct seq_file *m,
+		 struct binder_transaction *t),
+	TP_ARGS(m, t)
+);
+
 TRACE_EVENT(binder_txn_latency_free,
 	TP_PROTO(struct binder_transaction *t),
 	TP_ARGS(t),
@@ -106,6 +119,8 @@
 		__field(int, to_thread)
 		__field(unsigned int, code)
 		__field(unsigned int, flags)
+		__field(unsigned long, start_sec)
+		__field(unsigned long, start_nsec)
 	),
 	TP_fast_assign(
 		__entry->debug_id = t->debug_id;
@@ -115,11 +130,18 @@
 		__entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
 		__entry->code = t->code;
 		__entry->flags = t->flags;
-	),
-	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING
+		__entry->start_sec = t->timestamp.tv_sec;
+		__entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
+#else
+		__entry->start_sec = 0;
+		__entry->start_nsec = 0;
+#endif
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
 		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
 		  __entry->to_proc, __entry->to_thread, __entry->code,
-		  __entry->flags)
+		  __entry->flags, __entry->start_sec, __entry->start_nsec)
 );
 
 TRACE_EVENT(binder_transaction,
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v5] binder: transaction latency tracking for user build
  2020-06-10 12:23                               ` [PATCH v5] binder: transaction latency tracking for user build Frankie Chang
                                                   ` (2 preceding siblings ...)
  2020-06-10 12:23                                 ` [PATCH v5 3/3] binder: add transaction latency tracer Frankie Chang
@ 2020-07-02 13:25                                 ` Frankie Chang
  2020-07-20 13:40                                   ` Frankie Chang
  3 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-07-02 13:25 UTC (permalink / raw)
  To: Todd Kjos, Greg Kroah-Hartman
  Cc: wsd_upstream, LKML, Arve Hjønnevåg, Jian-Min Liu,
	linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

Hi Greg, Todd and all

Gentle remind of this patch set

Thanks.
Frankie

On Wed, 2020-06-10 at 20:23 +0800, Frankie Chang wrote:
> Frankie.Chang (3):
>   binder: move structs from core file to header file
>   binder: add trace at free transaction.
>   binder: add transaction latency tracer
> 
>  drivers/android/Kconfig                 |   8 +
>  drivers/android/Makefile                |   1 +
>  drivers/android/binder.c                | 408 +----------------------
>  drivers/android/binder_internal.h       | 416 ++++++++++++++++++++++++
>  drivers/android/binder_latency_tracer.c | 108 ++++++
>  drivers/android/binder_trace.h          |  49 +++
>  6 files changed, 586 insertions(+), 404 deletions(-)  create mode 100644 drivers/android/binder_latency_tracer.c
> 
> Change from v5:
>   - change config name to the proper one, CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING.
>   - change tracepoint name to more descriptive one, trace_binder_txn_latency_(alloc|info|free)
>   - enhance some lock protection.
> 
> Change from v4:
>   - split up into patch series.
> 
> Change from v3:
>   - use tracepoints for binder_update_info and print_binder_transaction_ext,
>     instead of custom registration functions.
> 
> Change from v2:
>   - create transaction latency module to monitor slow transaction.
> 
> Change from v1:
>   - first patchset.

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v5] binder: transaction latency tracking for user build
  2020-07-02 13:25                                 ` [PATCH v5] binder: transaction latency tracking for user build Frankie Chang
@ 2020-07-20 13:40                                   ` Frankie Chang
  2020-07-28  3:19                                     ` [PATCH v6] " Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-07-20 13:40 UTC (permalink / raw)
  To: Greg Kroah-Hartman, . Todd Kjos
  Cc: wsd_upstream, LKML, Arve Hjønnevåg, Jian-Min Liu,
	linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

Hi Greg, Todd and all

Gentle ping for this patch set

Thanks

On Thu, 2020-07-02 at 21:25 +0800, Frankie Chang wrote:
> Hi Greg, Todd and all
> 
> Gentle remind of this patch set
> 
> Thanks.
> Frankie
> 
> On Wed, 2020-06-10 at 20:23 +0800, Frankie Chang wrote:
> > Frankie.Chang (3):
> >   binder: move structs from core file to header file
> >   binder: add trace at free transaction.
> >   binder: add transaction latency tracer
> > 
> >  drivers/android/Kconfig                 |   8 +
> >  drivers/android/Makefile                |   1 +
> >  drivers/android/binder.c                | 408 +----------------------
> >  drivers/android/binder_internal.h       | 416 ++++++++++++++++++++++++
> >  drivers/android/binder_latency_tracer.c | 108 ++++++
> >  drivers/android/binder_trace.h          |  49 +++
> >  6 files changed, 586 insertions(+), 404 deletions(-)  create mode 100644 drivers/android/binder_latency_tracer.c
> > 
> > Change from v5:
> >   - change config name to the proper one, CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING.
> >   - change tracepoint name to more descriptive one, trace_binder_txn_latency_(alloc|info|free)
> >   - enhance some lock protection.
> > 
> > Change from v4:
> >   - split up into patch series.
> > 
> > Change from v3:
> >   - use tracepoints for binder_update_info and print_binder_transaction_ext,
> >     instead of custom registration functions.
> > 
> > Change from v2:
> >   - create transaction latency module to monitor slow transaction.
> > 
> > Change from v1:
> >   - first patchset.
> 

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v5 2/3] binder: add trace at free transaction.
  2020-06-10 12:23                                 ` [PATCH v5 2/3] binder: add trace at free transaction Frankie Chang
@ 2020-07-20 18:23                                   ` Todd Kjos
  2020-07-23  2:47                                     ` Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Todd Kjos @ 2020-07-20 18:23 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Wed, Jun 10, 2020 at 5:24 AM Frankie Chang
<Frankie.Chang@mediatek.com> wrote:
>
> From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
>
> Since the original trace_binder_transaction_received cannot
> precisely present the real finished time of transaction, adding a
> trace_binder_txn_latency_free at the point of free transaction
> may be more close to it.
>
> Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> ---
>  drivers/android/binder.c       |    2 ++
>  drivers/android/binder_trace.h |   27 +++++++++++++++++++++++++++
>  2 files changed, 29 insertions(+)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 1592396..5ec9af8 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -1523,6 +1523,7 @@ static void binder_free_transaction(struct binder_transaction *t)
>          * If the transaction has no target_proc, then
>          * t->buffer->transaction has already been cleared.
>          */
> +       trace_binder_txn_latency_free(t);
>         binder_free_txn_fixups(t);
>         kfree(t);
>         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> @@ -3094,6 +3095,7 @@ static void binder_transaction(struct binder_proc *proc,
>         kfree(tcomplete);
>         binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
>  err_alloc_tcomplete_failed:
> +       trace_binder_txn_latency_free(t);
>         kfree(t);
>         binder_stats_deleted(BINDER_STAT_TRANSACTION);
>  err_alloc_t_failed:
> diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> index 6731c3c..8ac87d1 100644
> --- a/drivers/android/binder_trace.h
> +++ b/drivers/android/binder_trace.h
> @@ -95,6 +95,33 @@
>                   __entry->thread_todo)
>  );
>
> +TRACE_EVENT(binder_txn_latency_free,
> +       TP_PROTO(struct binder_transaction *t),
> +       TP_ARGS(t),
> +       TP_STRUCT__entry(
> +               __field(int, debug_id)
> +               __field(int, from_proc)
> +               __field(int, from_thread)
> +               __field(int, to_proc)
> +               __field(int, to_thread)
> +               __field(unsigned int, code)
> +               __field(unsigned int, flags)
> +       ),
> +       TP_fast_assign(
> +               __entry->debug_id = t->debug_id;
> +               __entry->from_proc = t->from ? t->from->proc->pid : 0;
> +               __entry->from_thread = t->from ? t->from->pid : 0;
> +               __entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
> +               __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;

t->to_proc and t->to_thread are not safe to dereference without
holding t->lock. If the target process dies, these fields can be set
to NULL

> +               __entry->code = t->code;
> +               __entry->flags = t->flags;
> +       ),
> +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> +                 __entry->debug_id, __entry->from_proc, __entry->from_thread,
> +                 __entry->to_proc, __entry->to_thread, __entry->code,
> +                 __entry->flags)
> +);
> +
>  TRACE_EVENT(binder_transaction,
>         TP_PROTO(bool reply, struct binder_transaction *t,
>                  struct binder_node *target_node),
> --
> 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v5 3/3] binder: add transaction latency tracer
  2020-06-10 12:23                                 ` [PATCH v5 3/3] binder: add transaction latency tracer Frankie Chang
@ 2020-07-20 18:56                                   ` Todd Kjos
  2020-07-23  3:01                                     ` Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Todd Kjos @ 2020-07-20 18:56 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Wed, Jun 10, 2020 at 5:34 AM Frankie Chang
<Frankie.Chang@mediatek.com> wrote:
>
> From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
>
> Record start/end timestamp for binder transaction.
> When transaction is completed or transaction is free,
> it would be checked if transaction latency over threshold (2 sec),
> if yes, printing related information for tracing.
>
> /* Implement details */
> - Add latency tracer module to monitor transaction
>   by attaching to new tracepoints introduced
>   when transactions are allocated and freed.
>   The trace_binder_txn_latency_free would not be enabled
>   by default. Monitoring which transaction is too slow to
>   cause some of exceptions is important. So we hook the
>   tracepoint to call the monitor function.
>
> - Since some of modules would trigger timeout NE
>   if their binder transaction don't finish in time,
>   such as audio timeout (5 sec), even BT command
>   timeout (2 sec), etc.
>   Therefore, setting the timeout threshold as 2 seconds
>   could be helpful to debug.

Could there be cases that 500ms is too long so 1s should be the
threshold? Hard coded 2 seconds makes this less useful. How about
making it configurable with a default of 2 sec?

>
> - The reason why printing the related information to
>   kernel information log but not trace buffer is that
>   some abnormal transactions may be pending for a long
>   time ago, they could not be recorded due to buffer
>   limited.
>
> Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> ---
>  drivers/android/Kconfig                 |    8 +++
>  drivers/android/Makefile                |    1 +
>  drivers/android/binder.c                |    2 +
>  drivers/android/binder_internal.h       |   13 ++++
>  drivers/android/binder_latency_tracer.c |  107 +++++++++++++++++++++++++++++++
>  drivers/android/binder_trace.h          |   28 +++++++-
>  6 files changed, 156 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/android/binder_latency_tracer.c
>
> diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> index 6fdf2ab..39d47be 100644
> --- a/drivers/android/Kconfig
> +++ b/drivers/android/Kconfig
> @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
>           exhaustively with combinations of various buffer sizes and
>           alignments.
>
> +config BINDER_TRANSACTION_LATENCY_TRACKING
> +       bool "Android Binder transaction tracking"

Any reason this can't be tristate?

> +       help
> +         Used for track abnormal binder transaction which is over 2 seconds,
> +         when the transaction is done or be free, this transaction would be
> +         checked whether it executed overtime.
> +         If yes, printing out the detailed info.
> +
>  endif # if ANDROID
>
>  endmenu
> diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> index c9d3d0c9..c2ffdb6 100644
> --- a/drivers/android/Makefile
> +++ b/drivers/android/Makefile
> @@ -4,3 +4,4 @@ ccflags-y += -I$(src)                   # needed for trace events
>  obj-$(CONFIG_ANDROID_BINDERFS)         += binderfs.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC)       += binder.o binder_alloc.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> +obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)      += binder_latency_tracer.o
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 5ec9af8..846d69b 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2657,6 +2657,7 @@ static void binder_transaction(struct binder_proc *proc,
>                 return_error_line = __LINE__;
>                 goto err_alloc_t_failed;
>         }
> +       trace_binder_txn_latency_alloc(t, e);
>         INIT_LIST_HEAD(&t->fd_fixups);
>         binder_stats_created(BINDER_STAT_TRANSACTION);
>         spin_lock_init(&t->lock);
> @@ -5144,6 +5145,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
>                    to_proc ? to_proc->pid : 0,
>                    t->to_thread ? t->to_thread->pid : 0,
>                    t->code, t->flags, t->priority, t->need_reply);
> +       trace_binder_txn_latency_info(m, t);
>         spin_unlock(&t->lock);
>
>         if (proc != to_proc) {
> diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> index ed61b3e..bebc185 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -12,6 +12,11 @@
>  #include <linux/types.h>
>  #include <linux/uidgid.h>
>
> +#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING
> +#include <linux/rtc.h>
> +#include <linux/time.h>
> +#endif
> +
>  struct binder_context {
>         struct binder_node *binder_context_mgr_node;
>         struct mutex context_mgr_node_lock;
> @@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
>         uint32_t return_error;
>         uint32_t return_error_param;
>         char context_name[BINDERFS_MAX_NAME + 1];
> +#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING

If you make binder_latency_tracer a module, then we could include
these fields unconditionally. Please add comments or give them better
names so it is obvious what they are for.

> +       struct timespec timestamp;
> +       struct timeval tv;
> +#endif
>  };
>
>  struct binder_transaction_log {
> @@ -520,6 +529,10 @@ struct binder_transaction {
>          * during thread teardown
>          */
>         spinlock_t lock;
> +#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING

If you make binder_latency_tracer a module, then we could include
these fields unconditionally. Please add comments or give them better
names so it is obvious what they are for.

> +       struct timespec timestamp;
> +       struct timeval tv;
> +#endif
>  };
>
>  /**
> diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
> new file mode 100644
> index 0000000..1b89634
> --- /dev/null
> +++ b/drivers/android/binder_latency_tracer.c
> @@ -0,0 +1,107 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2019 MediaTek Inc.
> + */
> +
> +#include <linux/module.h>
> +#include <uapi/linux/android/binder.h>
> +#include "binder_alloc.h"
> +#include "binder_internal.h"
> +#include "binder_trace.h"
> +
> +/*
> + * probe_binder_txn_latency_free - Output info of a delay transaction
> + * @t:          pointer to the over-time transaction
> + */
> +void probe_binder_txn_latency_free(void *ignore, struct binder_transaction *t)
> +{
> +       struct rtc_time tm;
> +       struct timespec *startime;
> +       struct timespec cur, sub_t;
> +
> +       ktime_get_ts(&cur);
> +       startime = &t->timestamp;
> +       sub_t = timespec_sub(cur, *startime);
> +
> +       /* if transaction time is over than 2 sec,
> +        * show timeout warning log.
> +        */
> +       if (sub_t.tv_sec < 2)
> +               return;

I still don't get why 2sec is magical. Should this threshold be configurable?

> +
> +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> +
> +       spin_lock(&t->lock);
> +       pr_info_ratelimited("%d: from %d:%d to %d:%d",
> +                       t->debug_id,
> +                       t->from ? t->from->proc->pid : 0,
> +                       t->from ? t->from->pid : 0,
> +                       t->to_proc ? t->to_proc->pid : 0,
> +                       t->to_thread ? t->to_thread->pid : 0);
> +
> +       pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> +                       (unsigned int)sub_t.tv_sec,
> +                       (sub_t.tv_nsec / NSEC_PER_MSEC),
> +                       t->code,
> +                       (unsigned long)startime->tv_sec,
> +                       (startime->tv_nsec / NSEC_PER_MSEC),
> +                       (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> +                       tm.tm_hour, tm.tm_min, tm.tm_sec,
> +                       (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> +       spin_unlock(&t->lock);
> +}
> +
> +static void probe_binder_txn_latency_alloc(void *ignore,
> +                                       struct binder_transaction *t,
> +                                       struct binder_transaction_log_entry *e)
> +{
> +       ktime_get_ts(&e->timestamp);
> +       do_gettimeofday(&e->tv);
> +       e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
> +       spin_lock(&t->lock);
> +       memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
> +       memcpy(&t->tv, &e->tv, sizeof(struct timeval));
> +       spin_unlock(&t->lock);

Why is the lock needed here?

> +}
> +
> +static void probe_binder_txn_latency_info(void *ignore, struct seq_file *m,
> +                                       struct binder_transaction *t)
> +{
> +       struct rtc_time tm;
> +
> +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> +       seq_printf(m,
> +                  " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
> +                  (unsigned long)t->timestamp.tv_sec,
> +                  (t->timestamp.tv_nsec / NSEC_PER_USEC),
> +                  (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> +                  tm.tm_hour, tm.tm_min, tm.tm_sec,
> +                  (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> +}
> +
> +static int __init init_binder_latency_tracer(void)
> +{
> +       register_trace_binder_txn_latency_free(
> +                       probe_binder_txn_latency_free, NULL);
> +       register_trace_binder_txn_latency_alloc(
> +                       probe_binder_txn_latency_alloc, NULL);
> +       register_trace_binder_txn_latency_info(
> +                       probe_binder_txn_latency_info, NULL);
> +
> +       return 0;
> +}
> +
> +static void exit_binder_latency_tracer(void)
> +{
> +       unregister_trace_binder_txn_latency_free(
> +                       probe_binder_txn_latency_free, NULL);
> +       unregister_trace_binder_txn_latency_alloc(
> +                       probe_binder_txn_latency_alloc, NULL);
> +       unregister_trace_binder_txn_latency_info(
> +                       probe_binder_txn_latency_info, NULL);
> +}
> +
> +module_init(init_binder_latency_tracer);
> +module_exit(exit_binder_latency_tracer);
> +
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> index 8ac87d1..ca41c7d 100644
> --- a/drivers/android/binder_trace.h
> +++ b/drivers/android/binder_trace.h
> @@ -18,6 +18,7 @@
>  struct binder_ref_data;
>  struct binder_thread;
>  struct binder_transaction;
> +struct binder_transaction_log_entry;
>
>  TRACE_EVENT(binder_ioctl,
>         TP_PROTO(unsigned int cmd, unsigned long arg),
> @@ -95,6 +96,18 @@
>                   __entry->thread_todo)
>  );
>
> +DECLARE_TRACE(binder_txn_latency_alloc,
> +       TP_PROTO(struct binder_transaction *t,
> +                struct binder_transaction_log_entry *e),
> +       TP_ARGS(t, e)
> +);
> +
> +DECLARE_TRACE(binder_txn_latency_info,
> +       TP_PROTO(struct seq_file *m,
> +                struct binder_transaction *t),
> +       TP_ARGS(m, t)
> +);
> +
>  TRACE_EVENT(binder_txn_latency_free,
>         TP_PROTO(struct binder_transaction *t),
>         TP_ARGS(t),
> @@ -106,6 +119,8 @@
>                 __field(int, to_thread)
>                 __field(unsigned int, code)
>                 __field(unsigned int, flags)
> +               __field(unsigned long, start_sec)
> +               __field(unsigned long, start_nsec)
>         ),
>         TP_fast_assign(
>                 __entry->debug_id = t->debug_id;
> @@ -115,11 +130,18 @@
>                 __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
>                 __entry->code = t->code;
>                 __entry->flags = t->flags;
> -       ),
> -       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> +#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING
> +               __entry->start_sec = t->timestamp.tv_sec;
> +               __entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
> +#else
> +               __entry->start_sec = 0;
> +               __entry->start_nsec = 0;
> +#endif
> +       ),
> +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
>                   __entry->debug_id, __entry->from_proc, __entry->from_thread,
>                   __entry->to_proc, __entry->to_thread, __entry->code,
> -                 __entry->flags)
> +                 __entry->flags, __entry->start_sec, __entry->start_nsec)
>  );
>
>  TRACE_EVENT(binder_transaction,
> --
> 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v5 2/3] binder: add trace at free transaction.
  2020-07-20 18:23                                   ` Todd Kjos
@ 2020-07-23  2:47                                     ` Frankie Chang
  0 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-07-23  2:47 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Mon, 2020-07-20 at 11:23 -0700, Todd Kjos wrote:
> On Wed, Jun 10, 2020 at 5:24 AM Frankie Chang
> <Frankie.Chang@mediatek.com> wrote:
> >
> > From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
> >
> > Since the original trace_binder_transaction_received cannot
> > precisely present the real finished time of transaction, adding a
> > trace_binder_txn_latency_free at the point of free transaction
> > may be more close to it.
> >
> > Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> > ---
> >  drivers/android/binder.c       |    2 ++
> >  drivers/android/binder_trace.h |   27 +++++++++++++++++++++++++++
> >  2 files changed, 29 insertions(+)
> >
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index 1592396..5ec9af8 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -1523,6 +1523,7 @@ static void binder_free_transaction(struct binder_transaction *t)
> >          * If the transaction has no target_proc, then
> >          * t->buffer->transaction has already been cleared.
> >          */
> > +       trace_binder_txn_latency_free(t);
> >         binder_free_txn_fixups(t);
> >         kfree(t);
> >         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> > @@ -3094,6 +3095,7 @@ static void binder_transaction(struct binder_proc *proc,
> >         kfree(tcomplete);
> >         binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
> >  err_alloc_tcomplete_failed:
> > +       trace_binder_txn_latency_free(t);
> >         kfree(t);
> >         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> >  err_alloc_t_failed:
> > diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> > index 6731c3c..8ac87d1 100644
> > --- a/drivers/android/binder_trace.h
> > +++ b/drivers/android/binder_trace.h
> > @@ -95,6 +95,33 @@
> >                   __entry->thread_todo)
> >  );
> >
> > +TRACE_EVENT(binder_txn_latency_free,
> > +       TP_PROTO(struct binder_transaction *t),
> > +       TP_ARGS(t),
> > +       TP_STRUCT__entry(
> > +               __field(int, debug_id)
> > +               __field(int, from_proc)
> > +               __field(int, from_thread)
> > +               __field(int, to_proc)
> > +               __field(int, to_thread)
> > +               __field(unsigned int, code)
> > +               __field(unsigned int, flags)
> > +       ),
> > +       TP_fast_assign(
> > +               __entry->debug_id = t->debug_id;
> > +               __entry->from_proc = t->from ? t->from->proc->pid : 0;
> > +               __entry->from_thread = t->from ? t->from->pid : 0;
> > +               __entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
> > +               __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
> 
> t->to_proc and t->to_thread are not safe to dereference without
> holding t->lock. If the target process dies, these fields can be set
> to NULL
> 
Thanks for remind. I will add lock protection for these t->to_proc &
t->to_thread in v7.

> > +               __entry->code = t->code;
> > +               __entry->flags = t->flags;
> > +       ),
> > +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> > +                 __entry->debug_id, __entry->from_proc, __entry->from_thread,
> > +                 __entry->to_proc, __entry->to_thread, __entry->code,
> > +                 __entry->flags)
> > +);
> > +
> >  TRACE_EVENT(binder_transaction,
> >         TP_PROTO(bool reply, struct binder_transaction *t,
> >                  struct binder_node *target_node),
> > --
> > 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v5 3/3] binder: add transaction latency tracer
  2020-07-20 18:56                                   ` Todd Kjos
@ 2020-07-23  3:01                                     ` Frankie Chang
  0 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-07-23  3:01 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Mon, 2020-07-20 at 11:56 -0700, Todd Kjos wrote:
> On Wed, Jun 10, 2020 at 5:34 AM Frankie Chang
> <Frankie.Chang@mediatek.com> wrote:
> >
> > From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
> >
> > Record start/end timestamp for binder transaction.
> > When transaction is completed or transaction is free,
> > it would be checked if transaction latency over threshold (2 sec),
> > if yes, printing related information for tracing.
> >
> > /* Implement details */
> > - Add latency tracer module to monitor transaction
> >   by attaching to new tracepoints introduced
> >   when transactions are allocated and freed.
> >   The trace_binder_txn_latency_free would not be enabled
> >   by default. Monitoring which transaction is too slow to
> >   cause some of exceptions is important. So we hook the
> >   tracepoint to call the monitor function.
> >
> > - Since some of modules would trigger timeout NE
> >   if their binder transaction don't finish in time,
> >   such as audio timeout (5 sec), even BT command
> >   timeout (2 sec), etc.
> >   Therefore, setting the timeout threshold as 2 seconds
> >   could be helpful to debug.
> 
> Could there be cases that 500ms is too long so 1s should be the
> threshold? Hard coded 2 seconds makes this less useful. How about
> making it configurable with a default of 2 sec?
> 
Okay, it makes sense that making threshold configurable. We will do it.

> >
> > - The reason why printing the related information to
> >   kernel information log but not trace buffer is that
> >   some abnormal transactions may be pending for a long
> >   time ago, they could not be recorded due to buffer
> >   limited.
> >
> > Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> > ---
> >  drivers/android/Kconfig                 |    8 +++
> >  drivers/android/Makefile                |    1 +
> >  drivers/android/binder.c                |    2 +
> >  drivers/android/binder_internal.h       |   13 ++++
> >  drivers/android/binder_latency_tracer.c |  107 +++++++++++++++++++++++++++++++
> >  drivers/android/binder_trace.h          |   28 +++++++-
> >  6 files changed, 156 insertions(+), 3 deletions(-)
> >  create mode 100644 drivers/android/binder_latency_tracer.c
> >
> > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > index 6fdf2ab..39d47be 100644
> > --- a/drivers/android/Kconfig
> > +++ b/drivers/android/Kconfig
> > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> >           exhaustively with combinations of various buffer sizes and
> >           alignments.
> >
> > +config BINDER_TRANSACTION_LATENCY_TRACKING
> > +       bool "Android Binder transaction tracking"
> 
> Any reason this can't be tristate?
> 
It can be tristate, and we would change #ifdef to #if IS_ENABLED()

> > +       help
> > +         Used for track abnormal binder transaction which is over 2 seconds,
> > +         when the transaction is done or be free, this transaction would be
> > +         checked whether it executed overtime.
> > +         If yes, printing out the detailed info.
> > +
> >  endif # if ANDROID
> >
> >  endmenu
> > diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> > index c9d3d0c9..c2ffdb6 100644
> > --- a/drivers/android/Makefile
> > +++ b/drivers/android/Makefile
> > @@ -4,3 +4,4 @@ ccflags-y += -I$(src)                   # needed for trace events
> >  obj-$(CONFIG_ANDROID_BINDERFS)         += binderfs.o
> >  obj-$(CONFIG_ANDROID_BINDER_IPC)       += binder.o binder_alloc.o
> >  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> > +obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)      += binder_latency_tracer.o
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index 5ec9af8..846d69b 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -2657,6 +2657,7 @@ static void binder_transaction(struct binder_proc *proc,
> >                 return_error_line = __LINE__;
> >                 goto err_alloc_t_failed;
> >         }
> > +       trace_binder_txn_latency_alloc(t, e);
> >         INIT_LIST_HEAD(&t->fd_fixups);
> >         binder_stats_created(BINDER_STAT_TRANSACTION);
> >         spin_lock_init(&t->lock);
> > @@ -5144,6 +5145,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
> >                    to_proc ? to_proc->pid : 0,
> >                    t->to_thread ? t->to_thread->pid : 0,
> >                    t->code, t->flags, t->priority, t->need_reply);
> > +       trace_binder_txn_latency_info(m, t);
> >         spin_unlock(&t->lock);
> >
> >         if (proc != to_proc) {
> > diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> > index ed61b3e..bebc185 100644
> > --- a/drivers/android/binder_internal.h
> > +++ b/drivers/android/binder_internal.h
> > @@ -12,6 +12,11 @@
> >  #include <linux/types.h>
> >  #include <linux/uidgid.h>
> >
> > +#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING
> > +#include <linux/rtc.h>
> > +#include <linux/time.h>
> > +#endif
> > +
> >  struct binder_context {
> >         struct binder_node *binder_context_mgr_node;
> >         struct mutex context_mgr_node_lock;
> > @@ -131,6 +136,10 @@ struct binder_transaction_log_entry {
> >         uint32_t return_error;
> >         uint32_t return_error_param;
> >         char context_name[BINDERFS_MAX_NAME + 1];
> > +#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING
> 
> If you make binder_latency_tracer a module, then we could include
> these fields unconditionally. Please add comments or give them better
> names so it is obvious what they are for.
> 
We would add comments to explain what these used for.

> > +       struct timespec timestamp;
> > +       struct timeval tv;
> > +#endif
> >  };
> >
> >  struct binder_transaction_log {
> > @@ -520,6 +529,10 @@ struct binder_transaction {
> >          * during thread teardown
> >          */
> >         spinlock_t lock;
> > +#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING
> 
> If you make binder_latency_tracer a module, then we could include
> these fields unconditionally. Please add comments or give them better
> names so it is obvious what they are for.
> 
We would add comments to explain what these used for.

> > +       struct timespec timestamp;
> > +       struct timeval tv;
> > +#endif
> >  };
> >
> >  /**
> > diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
> > new file mode 100644
> > index 0000000..1b89634
> > --- /dev/null
> > +++ b/drivers/android/binder_latency_tracer.c
> > @@ -0,0 +1,107 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2019 MediaTek Inc.
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <uapi/linux/android/binder.h>
> > +#include "binder_alloc.h"
> > +#include "binder_internal.h"
> > +#include "binder_trace.h"
> > +
> > +/*
> > + * probe_binder_txn_latency_free - Output info of a delay transaction
> > + * @t:          pointer to the over-time transaction
> > + */
> > +void probe_binder_txn_latency_free(void *ignore, struct binder_transaction *t)
> > +{
> > +       struct rtc_time tm;
> > +       struct timespec *startime;
> > +       struct timespec cur, sub_t;
> > +
> > +       ktime_get_ts(&cur);
> > +       startime = &t->timestamp;
> > +       sub_t = timespec_sub(cur, *startime);
> > +
> > +       /* if transaction time is over than 2 sec,
> > +        * show timeout warning log.
> > +        */
> > +       if (sub_t.tv_sec < 2)
> > +               return;
> 
> I still don't get why 2sec is magical. Should this threshold be configurable?
> 
Okay, it makes sense that making threshold configurable. We will do it.

> > +
> > +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> > +
> > +       spin_lock(&t->lock);
> > +       pr_info_ratelimited("%d: from %d:%d to %d:%d",
> > +                       t->debug_id,
> > +                       t->from ? t->from->proc->pid : 0,
> > +                       t->from ? t->from->pid : 0,
> > +                       t->to_proc ? t->to_proc->pid : 0,
> > +                       t->to_thread ? t->to_thread->pid : 0);
> > +
> > +       pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> > +                       (unsigned int)sub_t.tv_sec,
> > +                       (sub_t.tv_nsec / NSEC_PER_MSEC),
> > +                       t->code,
> > +                       (unsigned long)startime->tv_sec,
> > +                       (startime->tv_nsec / NSEC_PER_MSEC),
> > +                       (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > +                       tm.tm_hour, tm.tm_min, tm.tm_sec,
> > +                       (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > +       spin_unlock(&t->lock);
> > +}
> > +
> > +static void probe_binder_txn_latency_alloc(void *ignore,
> > +                                       struct binder_transaction *t,
> > +                                       struct binder_transaction_log_entry *e)
> > +{
> > +       ktime_get_ts(&e->timestamp);
> > +       do_gettimeofday(&e->tv);
> > +       e->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
> > +       spin_lock(&t->lock);
> > +       memcpy(&t->timestamp, &e->timestamp, sizeof(struct timespec));
> > +       memcpy(&t->tv, &e->tv, sizeof(struct timeval));
> > +       spin_unlock(&t->lock);
> 
> Why is the lock needed here?
> 
We used it to protect @t->timestamp and @t->timeval, but it seems that
@t->timestamp and @t->timeval would not be changed in other place. So
we would remove it.

> > +}
> > +
> > +static void probe_binder_txn_latency_info(void *ignore, struct seq_file *m,
> > +                                       struct binder_transaction *t)
> > +{
> > +       struct rtc_time tm;
> > +
> > +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> > +       seq_printf(m,
> > +                  " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
> > +                  (unsigned long)t->timestamp.tv_sec,
> > +                  (t->timestamp.tv_nsec / NSEC_PER_USEC),
> > +                  (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> > +                  tm.tm_hour, tm.tm_min, tm.tm_sec,
> > +                  (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> > +}
> > +
> > +static int __init init_binder_latency_tracer(void)
> > +{
> > +       register_trace_binder_txn_latency_free(
> > +                       probe_binder_txn_latency_free, NULL);
> > +       register_trace_binder_txn_latency_alloc(
> > +                       probe_binder_txn_latency_alloc, NULL);
> > +       register_trace_binder_txn_latency_info(
> > +                       probe_binder_txn_latency_info, NULL);
> > +
> > +       return 0;
> > +}
> > +
> > +static void exit_binder_latency_tracer(void)
> > +{
> > +       unregister_trace_binder_txn_latency_free(
> > +                       probe_binder_txn_latency_free, NULL);
> > +       unregister_trace_binder_txn_latency_alloc(
> > +                       probe_binder_txn_latency_alloc, NULL);
> > +       unregister_trace_binder_txn_latency_info(
> > +                       probe_binder_txn_latency_info, NULL);
> > +}
> > +
> > +module_init(init_binder_latency_tracer);
> > +module_exit(exit_binder_latency_tracer);
> > +
> > +MODULE_LICENSE("GPL v2");
> > diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> > index 8ac87d1..ca41c7d 100644
> > --- a/drivers/android/binder_trace.h
> > +++ b/drivers/android/binder_trace.h
> > @@ -18,6 +18,7 @@
> >  struct binder_ref_data;
> >  struct binder_thread;
> >  struct binder_transaction;
> > +struct binder_transaction_log_entry;
> >
> >  TRACE_EVENT(binder_ioctl,
> >         TP_PROTO(unsigned int cmd, unsigned long arg),
> > @@ -95,6 +96,18 @@
> >                   __entry->thread_todo)
> >  );
> >
> > +DECLARE_TRACE(binder_txn_latency_alloc,
> > +       TP_PROTO(struct binder_transaction *t,
> > +                struct binder_transaction_log_entry *e),
> > +       TP_ARGS(t, e)
> > +);
> > +
> > +DECLARE_TRACE(binder_txn_latency_info,
> > +       TP_PROTO(struct seq_file *m,
> > +                struct binder_transaction *t),
> > +       TP_ARGS(m, t)
> > +);
> > +
> >  TRACE_EVENT(binder_txn_latency_free,
> >         TP_PROTO(struct binder_transaction *t),
> >         TP_ARGS(t),
> > @@ -106,6 +119,8 @@
> >                 __field(int, to_thread)
> >                 __field(unsigned int, code)
> >                 __field(unsigned int, flags)
> > +               __field(unsigned long, start_sec)
> > +               __field(unsigned long, start_nsec)
> >         ),
> >         TP_fast_assign(
> >                 __entry->debug_id = t->debug_id;
> > @@ -115,11 +130,18 @@
> >                 __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
> >                 __entry->code = t->code;
> >                 __entry->flags = t->flags;
> > -       ),
> > -       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> > +#ifdef CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING
> > +               __entry->start_sec = t->timestamp.tv_sec;
> > +               __entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
> > +#else
> > +               __entry->start_sec = 0;
> > +               __entry->start_nsec = 0;
> > +#endif
> > +       ),
> > +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
> >                   __entry->debug_id, __entry->from_proc, __entry->from_thread,
> >                   __entry->to_proc, __entry->to_thread, __entry->code,
> > -                 __entry->flags)
> > +                 __entry->flags, __entry->start_sec, __entry->start_nsec)
> >  );
> >
> >  TRACE_EVENT(binder_transaction,
> > --
> > 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v6] binder: transaction latency tracking for user build
  2020-07-20 13:40                                   ` Frankie Chang
@ 2020-07-28  3:19                                     ` Frankie Chang
  2020-07-28  3:19                                       ` [PATCH v6 1/3] binder: move structs from core file to header file Frankie Chang
                                                         ` (2 more replies)
  0 siblings, 3 replies; 72+ messages in thread
From: Frankie Chang @ 2020-07-28  3:19 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min Liu, linux-mediatek,
	Joel Fernandes, Frankie Chang, Martijn Coenen, Christian Brauner


Change from v6:
  - change CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING type from bool to tristate
  - add comments to @timestamp and @tv under struct binder_transaction
  - make binder_txn_latency threshold configurable
  - enhance lock protection

Change from v5:
  - change config name to the proper one, CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING.
  - change tracepoint name to more descriptive one, trace_binder_txn_latency_(alloc|info|free)
  - enhance some lock protection.

Change from v4:
  - split up into patch series.

Change from v3:
  - use tracepoints for binder_update_info and print_binder_transaction_ext,
    instead of custom registration functions.

Change from v2:
  - create transaction latency module to monitor slow transaction.

Change from v1:
  - first patchset.
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v6 1/3] binder: move structs from core file to header file
  2020-07-28  3:19                                     ` [PATCH v6] " Frankie Chang
@ 2020-07-28  3:19                                       ` Frankie Chang
  2020-07-28  3:20                                       ` [PATCH v6 2/3] binder: add trace at free transaction Frankie Chang
  2020-07-28  3:20                                       ` [PATCH v6 3/3] binder: add transaction latency tracer Frankie Chang
  2 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-07-28  3:19 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min Liu, linux-mediatek,
	Joel Fernandes, Frankie Chang, Martijn Coenen, Christian Brauner

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Moving all structs to header file makes module more
extendable, and makes all these structs to be defined
in the same file.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/binder.c          |  405 -------------------------------------
 drivers/android/binder_internal.h |  404 ++++++++++++++++++++++++++++++++++++
 2 files changed, 404 insertions(+), 405 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index a6b2082..2df146f 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -72,7 +72,6 @@
 
 #include <asm/cacheflush.h>
 
-#include "binder_alloc.h"
 #include "binder_internal.h"
 #include "binder_trace.h"
 
@@ -160,24 +159,6 @@ static int binder_set_stop_on_user_error(const char *val,
 #define to_binder_fd_array_object(hdr) \
 	container_of(hdr, struct binder_fd_array_object, hdr)
 
-enum binder_stat_types {
-	BINDER_STAT_PROC,
-	BINDER_STAT_THREAD,
-	BINDER_STAT_NODE,
-	BINDER_STAT_REF,
-	BINDER_STAT_DEATH,
-	BINDER_STAT_TRANSACTION,
-	BINDER_STAT_TRANSACTION_COMPLETE,
-	BINDER_STAT_COUNT
-};
-
-struct binder_stats {
-	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
-	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
-	atomic_t obj_created[BINDER_STAT_COUNT];
-	atomic_t obj_deleted[BINDER_STAT_COUNT];
-};
-
 static struct binder_stats binder_stats;
 
 static inline void binder_stats_deleted(enum binder_stat_types type)
@@ -213,278 +194,11 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
 	return e;
 }
 
-/**
- * struct binder_work - work enqueued on a worklist
- * @entry:             node enqueued on list
- * @type:              type of work to be performed
- *
- * There are separate work lists for proc, thread, and node (async).
- */
-struct binder_work {
-	struct list_head entry;
-
-	enum {
-		BINDER_WORK_TRANSACTION = 1,
-		BINDER_WORK_TRANSACTION_COMPLETE,
-		BINDER_WORK_RETURN_ERROR,
-		BINDER_WORK_NODE,
-		BINDER_WORK_DEAD_BINDER,
-		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
-		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
-	} type;
-};
-
-struct binder_error {
-	struct binder_work work;
-	uint32_t cmd;
-};
-
-/**
- * struct binder_node - binder node bookkeeping
- * @debug_id:             unique ID for debugging
- *                        (invariant after initialized)
- * @lock:                 lock for node fields
- * @work:                 worklist element for node work
- *                        (protected by @proc->inner_lock)
- * @rb_node:              element for proc->nodes tree
- *                        (protected by @proc->inner_lock)
- * @dead_node:            element for binder_dead_nodes list
- *                        (protected by binder_dead_nodes_lock)
- * @proc:                 binder_proc that owns this node
- *                        (invariant after initialized)
- * @refs:                 list of references on this node
- *                        (protected by @lock)
- * @internal_strong_refs: used to take strong references when
- *                        initiating a transaction
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_weak_refs:      weak user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_strong_refs:    strong user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @tmp_refs:             temporary kernel refs
- *                        (protected by @proc->inner_lock while @proc
- *                        is valid, and by binder_dead_nodes_lock
- *                        if @proc is NULL. During inc/dec and node release
- *                        it is also protected by @lock to provide safety
- *                        as the node dies and @proc becomes NULL)
- * @ptr:                  userspace pointer for node
- *                        (invariant, no lock needed)
- * @cookie:               userspace cookie for node
- *                        (invariant, no lock needed)
- * @has_strong_ref:       userspace notified of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_strong_ref:   userspace has acked notification of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_weak_ref:         userspace notified of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_weak_ref:     userspace has acked notification of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_async_transaction: async transaction to node in progress
- *                        (protected by @lock)
- * @accept_fds:           file descriptor operations supported for node
- *                        (invariant after initialized)
- * @min_priority:         minimum scheduling priority
- *                        (invariant after initialized)
- * @txn_security_ctx:     require sender's security context
- *                        (invariant after initialized)
- * @async_todo:           list of async work items
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder nodes.
- */
-struct binder_node {
-	int debug_id;
-	spinlock_t lock;
-	struct binder_work work;
-	union {
-		struct rb_node rb_node;
-		struct hlist_node dead_node;
-	};
-	struct binder_proc *proc;
-	struct hlist_head refs;
-	int internal_strong_refs;
-	int local_weak_refs;
-	int local_strong_refs;
-	int tmp_refs;
-	binder_uintptr_t ptr;
-	binder_uintptr_t cookie;
-	struct {
-		/*
-		 * bitfield elements protected by
-		 * proc inner_lock
-		 */
-		u8 has_strong_ref:1;
-		u8 pending_strong_ref:1;
-		u8 has_weak_ref:1;
-		u8 pending_weak_ref:1;
-	};
-	struct {
-		/*
-		 * invariant after initialization
-		 */
-		u8 accept_fds:1;
-		u8 txn_security_ctx:1;
-		u8 min_priority;
-	};
-	bool has_async_transaction;
-	struct list_head async_todo;
-};
-
-struct binder_ref_death {
-	/**
-	 * @work: worklist element for death notifications
-	 *        (protected by inner_lock of the proc that
-	 *        this ref belongs to)
-	 */
-	struct binder_work work;
-	binder_uintptr_t cookie;
-};
-
-/**
- * struct binder_ref_data - binder_ref counts and id
- * @debug_id:        unique ID for the ref
- * @desc:            unique userspace handle for ref
- * @strong:          strong ref count (debugging only if not locked)
- * @weak:            weak ref count (debugging only if not locked)
- *
- * Structure to hold ref count and ref id information. Since
- * the actual ref can only be accessed with a lock, this structure
- * is used to return information about the ref to callers of
- * ref inc/dec functions.
- */
-struct binder_ref_data {
-	int debug_id;
-	uint32_t desc;
-	int strong;
-	int weak;
-};
-
-/**
- * struct binder_ref - struct to track references on nodes
- * @data:        binder_ref_data containing id, handle, and current refcounts
- * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
- * @rb_node_node: node for lookup by @node in proc's rb_tree
- * @node_entry:  list entry for node->refs list in target node
- *               (protected by @node->lock)
- * @proc:        binder_proc containing ref
- * @node:        binder_node of target node. When cleaning up a
- *               ref for deletion in binder_cleanup_ref, a non-NULL
- *               @node indicates the node must be freed
- * @death:       pointer to death notification (ref_death) if requested
- *               (protected by @node->lock)
- *
- * Structure to track references from procA to target node (on procB). This
- * structure is unsafe to access without holding @proc->outer_lock.
- */
-struct binder_ref {
-	/* Lookups needed: */
-	/*   node + proc => ref (transaction) */
-	/*   desc + proc => ref (transaction, inc/dec ref) */
-	/*   node => refs + procs (proc exit) */
-	struct binder_ref_data data;
-	struct rb_node rb_node_desc;
-	struct rb_node rb_node_node;
-	struct hlist_node node_entry;
-	struct binder_proc *proc;
-	struct binder_node *node;
-	struct binder_ref_death *death;
-};
-
 enum binder_deferred_state {
 	BINDER_DEFERRED_FLUSH        = 0x01,
 	BINDER_DEFERRED_RELEASE      = 0x02,
 };
 
-/**
- * struct binder_proc - binder process bookkeeping
- * @proc_node:            element for binder_procs list
- * @threads:              rbtree of binder_threads in this proc
- *                        (protected by @inner_lock)
- * @nodes:                rbtree of binder nodes associated with
- *                        this proc ordered by node->ptr
- *                        (protected by @inner_lock)
- * @refs_by_desc:         rbtree of refs ordered by ref->desc
- *                        (protected by @outer_lock)
- * @refs_by_node:         rbtree of refs ordered by ref->node
- *                        (protected by @outer_lock)
- * @waiting_threads:      threads currently waiting for proc work
- *                        (protected by @inner_lock)
- * @pid                   PID of group_leader of process
- *                        (invariant after initialized)
- * @tsk                   task_struct for group_leader of process
- *                        (invariant after initialized)
- * @deferred_work_node:   element for binder_deferred_list
- *                        (protected by binder_deferred_lock)
- * @deferred_work:        bitmap of deferred work to perform
- *                        (protected by binder_deferred_lock)
- * @is_dead:              process is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @inner_lock)
- * @todo:                 list of work for this process
- *                        (protected by @inner_lock)
- * @stats:                per-process binder statistics
- *                        (atomics, no lock needed)
- * @delivered_death:      list of delivered death notification
- *                        (protected by @inner_lock)
- * @max_threads:          cap on number of binder threads
- *                        (protected by @inner_lock)
- * @requested_threads:    number of binder threads requested but not
- *                        yet started. In current implementation, can
- *                        only be 0 or 1.
- *                        (protected by @inner_lock)
- * @requested_threads_started: number binder threads started
- *                        (protected by @inner_lock)
- * @tmp_ref:              temporary reference to indicate proc is in use
- *                        (protected by @inner_lock)
- * @default_priority:     default scheduler priority
- *                        (invariant after initialized)
- * @debugfs_entry:        debugfs node
- * @alloc:                binder allocator bookkeeping
- * @context:              binder_context for this proc
- *                        (invariant after initialized)
- * @inner_lock:           can nest under outer_lock and/or node lock
- * @outer_lock:           no nesting under innor or node lock
- *                        Lock order: 1) outer, 2) node, 3) inner
- * @binderfs_entry:       process-specific binderfs log file
- *
- * Bookkeeping structure for binder processes
- */
-struct binder_proc {
-	struct hlist_node proc_node;
-	struct rb_root threads;
-	struct rb_root nodes;
-	struct rb_root refs_by_desc;
-	struct rb_root refs_by_node;
-	struct list_head waiting_threads;
-	int pid;
-	struct task_struct *tsk;
-	struct hlist_node deferred_work_node;
-	int deferred_work;
-	bool is_dead;
-
-	struct list_head todo;
-	struct binder_stats stats;
-	struct list_head delivered_death;
-	int max_threads;
-	int requested_threads;
-	int requested_threads_started;
-	int tmp_ref;
-	long default_priority;
-	struct dentry *debugfs_entry;
-	struct binder_alloc alloc;
-	struct binder_context *context;
-	spinlock_t inner_lock;
-	spinlock_t outer_lock;
-	struct dentry *binderfs_entry;
-};
-
 enum {
 	BINDER_LOOPER_STATE_REGISTERED  = 0x01,
 	BINDER_LOOPER_STATE_ENTERED     = 0x02,
@@ -495,125 +209,6 @@ enum {
 };
 
 /**
- * struct binder_thread - binder thread bookkeeping
- * @proc:                 binder process for this thread
- *                        (invariant after initialization)
- * @rb_node:              element for proc->threads rbtree
- *                        (protected by @proc->inner_lock)
- * @waiting_thread_node:  element for @proc->waiting_threads list
- *                        (protected by @proc->inner_lock)
- * @pid:                  PID for this thread
- *                        (invariant after initialization)
- * @looper:               bitmap of looping state
- *                        (only accessed by this thread)
- * @looper_needs_return:  looping thread needs to exit driver
- *                        (no lock needed)
- * @transaction_stack:    stack of in-progress transactions for this thread
- *                        (protected by @proc->inner_lock)
- * @todo:                 list of work to do for this thread
- *                        (protected by @proc->inner_lock)
- * @process_todo:         whether work in @todo should be processed
- *                        (protected by @proc->inner_lock)
- * @return_error:         transaction errors reported by this thread
- *                        (only accessed by this thread)
- * @reply_error:          transaction errors reported by target thread
- *                        (protected by @proc->inner_lock)
- * @wait:                 wait queue for thread work
- * @stats:                per-thread statistics
- *                        (atomics, no lock needed)
- * @tmp_ref:              temporary reference to indicate thread is in use
- *                        (atomic since @proc->inner_lock cannot
- *                        always be acquired)
- * @is_dead:              thread is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder threads.
- */
-struct binder_thread {
-	struct binder_proc *proc;
-	struct rb_node rb_node;
-	struct list_head waiting_thread_node;
-	int pid;
-	int looper;              /* only modified by this thread */
-	bool looper_need_return; /* can be written by other thread */
-	struct binder_transaction *transaction_stack;
-	struct list_head todo;
-	bool process_todo;
-	struct binder_error return_error;
-	struct binder_error reply_error;
-	wait_queue_head_t wait;
-	struct binder_stats stats;
-	atomic_t tmp_ref;
-	bool is_dead;
-};
-
-/**
- * struct binder_txn_fd_fixup - transaction fd fixup list element
- * @fixup_entry:          list entry
- * @file:                 struct file to be associated with new fd
- * @offset:               offset in buffer data to this fixup
- *
- * List element for fd fixups in a transaction. Since file
- * descriptors need to be allocated in the context of the
- * target process, we pass each fd to be processed in this
- * struct.
- */
-struct binder_txn_fd_fixup {
-	struct list_head fixup_entry;
-	struct file *file;
-	size_t offset;
-};
-
-struct binder_transaction {
-	int debug_id;
-	struct binder_work work;
-	struct binder_thread *from;
-	struct binder_transaction *from_parent;
-	struct binder_proc *to_proc;
-	struct binder_thread *to_thread;
-	struct binder_transaction *to_parent;
-	unsigned need_reply:1;
-	/* unsigned is_dead:1; */	/* not used at the moment */
-
-	struct binder_buffer *buffer;
-	unsigned int	code;
-	unsigned int	flags;
-	long	priority;
-	long	saved_priority;
-	kuid_t	sender_euid;
-	struct list_head fd_fixups;
-	binder_uintptr_t security_ctx;
-	/**
-	 * @lock:  protects @from, @to_proc, and @to_thread
-	 *
-	 * @from, @to_proc, and @to_thread can be set to NULL
-	 * during thread teardown
-	 */
-	spinlock_t lock;
-};
-
-/**
- * struct binder_object - union of flat binder object types
- * @hdr:   generic object header
- * @fbo:   binder object (nodes and refs)
- * @fdo:   file descriptor object
- * @bbo:   binder buffer pointer
- * @fdao:  file descriptor array
- *
- * Used for type-independent object copies
- */
-struct binder_object {
-	union {
-		struct binder_object_header hdr;
-		struct flat_binder_object fbo;
-		struct binder_fd_object fdo;
-		struct binder_buffer_object bbo;
-		struct binder_fd_array_object fdao;
-	};
-};
-
-/**
  * binder_proc_lock() - Acquire outer lock for given binder_proc
  * @proc:         struct binder_proc to acquire
  *
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index ae99109..5b65413 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -11,6 +11,7 @@
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/uidgid.h>
+#include "binder_alloc.h"
 
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
@@ -139,6 +140,409 @@ struct binder_transaction_log {
 	struct binder_transaction_log_entry entry[32];
 };
 
+enum binder_stat_types {
+	BINDER_STAT_PROC,
+	BINDER_STAT_THREAD,
+	BINDER_STAT_NODE,
+	BINDER_STAT_REF,
+	BINDER_STAT_DEATH,
+	BINDER_STAT_TRANSACTION,
+	BINDER_STAT_TRANSACTION_COMPLETE,
+	BINDER_STAT_COUNT
+};
+
+struct binder_stats {
+	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
+	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
+	atomic_t obj_created[BINDER_STAT_COUNT];
+	atomic_t obj_deleted[BINDER_STAT_COUNT];
+};
+
+/**
+ * struct binder_work - work enqueued on a worklist
+ * @entry:             node enqueued on list
+ * @type:              type of work to be performed
+ *
+ * There are separate work lists for proc, thread, and node (async).
+ */
+struct binder_work {
+	struct list_head entry;
+
+	enum {
+		BINDER_WORK_TRANSACTION = 1,
+		BINDER_WORK_TRANSACTION_COMPLETE,
+		BINDER_WORK_RETURN_ERROR,
+		BINDER_WORK_NODE,
+		BINDER_WORK_DEAD_BINDER,
+		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
+		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
+	} type;
+};
+
+struct binder_error {
+	struct binder_work work;
+	uint32_t cmd;
+};
+
+/* struct binder_node - binder node bookkeeping
+ * @debug_id:             unique ID for debugging
+ *                        (invariant after initialized)
+ * @lock:                 lock for node fields
+ * @work:                 worklist element for node work
+ *                        (protected by @proc->inner_lock)
+ * @rb_node:              element for proc->nodes tree
+ *                        (protected by @proc->inner_lock)
+ * @dead_node:            element for binder_dead_nodes list
+ *                        (protected by binder_dead_nodes_lock)
+ * @proc:                 binder_proc that owns this node
+ *                        (invariant after initialized)
+ * @refs:                 list of references on this node
+ *                        (protected by @lock)
+ * @internal_strong_refs: used to take strong references when
+ *                        initiating a transaction
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_weak_refs:      weak user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_strong_refs:    strong user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @tmp_refs:             temporary kernel refs
+ *                        (protected by @proc->inner_lock while @proc
+ *                        is valid, and by binder_dead_nodes_lock
+ *                        if @proc is NULL. During inc/dec and node release
+ *                        it is also protected by @lock to provide safety
+ *                        as the node dies and @proc becomes NULL)
+ * @ptr:                  userspace pointer for node
+ *                        (invariant, no lock needed)
+ * @cookie:               userspace cookie for node
+ *                        (invariant, no lock needed)
+ * @has_strong_ref:       userspace notified of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_strong_ref:   userspace has acked notification of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_weak_ref:         userspace notified of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_weak_ref:     userspace has acked notification of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_async_transaction: async transaction to node in progress
+ *                        (protected by @lock)
+ * @accept_fds:           file descriptor operations supported for node
+ *                        (invariant after initialized)
+ * @min_priority:         minimum scheduling priority
+ *                        (invariant after initialized)
+ * @txn_security_ctx:     require sender's security context
+ *                        (invariant after initialized)
+ * @async_todo:           list of async work items
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder nodes.
+ */
+struct binder_node {
+	int debug_id;
+	spinlock_t lock;
+	struct binder_work work;
+	union {
+		struct rb_node rb_node;
+		struct hlist_node dead_node;
+	};
+	struct binder_proc *proc;
+	struct hlist_head refs;
+	int internal_strong_refs;
+	int local_weak_refs;
+	int local_strong_refs;
+	int tmp_refs;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
+	struct {
+		/*
+		 * bitfield elements protected by
+		 * proc inner_lock
+		 */
+		u8 has_strong_ref:1;
+		u8 pending_strong_ref:1;
+		u8 has_weak_ref:1;
+		u8 pending_weak_ref:1;
+	};
+	struct {
+		/*
+		 * invariant after initialization
+		 */
+		u8 accept_fds:1;
+		u8 txn_security_ctx:1;
+		u8 min_priority;
+	};
+	bool has_async_transaction;
+	struct list_head async_todo;
+};
+
+struct binder_ref_death {
+	/**
+	 * @work: worklist element for death notifications
+	 *        (protected by inner_lock of the proc that
+	 *        this ref belongs to)
+	 */
+	struct binder_work work;
+	binder_uintptr_t cookie;
+};
+
+/**
+ * struct binder_ref_data - binder_ref counts and id
+ * @debug_id:        unique ID for the ref
+ * @desc:            unique userspace handle for ref
+ * @strong:          strong ref count (debugging only if not locked)
+ * @weak:            weak ref count (debugging only if not locked)
+ *
+ * Structure to hold ref count and ref id information. Since
+ * the actual ref can only be accessed with a lock, this structure
+ * is used to return information about the ref to callers of
+ * ref inc/dec functions.
+ */
+struct binder_ref_data {
+	int debug_id;
+	uint32_t desc;
+	int strong;
+	int weak;
+};
+
+/**
+ * struct binder_ref - struct to track references on nodes
+ * @data:        binder_ref_data containing id, handle, and current refcounts
+ * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
+ * @rb_node_node: node for lookup by @node in proc's rb_tree
+ * @node_entry:  list entry for node->refs list in target node
+ *               (protected by @node->lock)
+ * @proc:        binder_proc containing ref
+ * @node:        binder_node of target node. When cleaning up a
+ *               ref for deletion in binder_cleanup_ref, a non-NULL
+ *               @node indicates the node must be freed
+ * @death:       pointer to death notification (ref_death) if requested
+ *               (protected by @node->lock)
+ *
+ * Structure to track references from procA to target node (on procB). This
+ * structure is unsafe to access without holding @proc->outer_lock.
+ */
+struct binder_ref {
+	/* Lookups needed: */
+	/*   node + proc => ref (transaction) */
+	/*   desc + proc => ref (transaction, inc/dec ref) */
+	/*   node => refs + procs (proc exit) */
+	struct binder_ref_data data;
+	struct rb_node rb_node_desc;
+	struct rb_node rb_node_node;
+	struct hlist_node node_entry;
+	struct binder_proc *proc;
+	struct binder_node *node;
+	struct binder_ref_death *death;
+};
+
+/**
+ * struct binder_proc - binder process bookkeeping
+ * @proc_node:            element for binder_procs list
+ * @threads:              rbtree of binder_threads in this proc
+ *                        (protected by @inner_lock)
+ * @nodes:                rbtree of binder nodes associated with
+ *                        this proc ordered by node->ptr
+ *                        (protected by @inner_lock)
+ * @refs_by_desc:         rbtree of refs ordered by ref->desc
+ *                        (protected by @outer_lock)
+ * @refs_by_node:         rbtree of refs ordered by ref->node
+ *                        (protected by @outer_lock)
+ * @waiting_threads:      threads currently waiting for proc work
+ *                        (protected by @inner_lock)
+ * @pid                   PID of group_leader of process
+ *                        (invariant after initialized)
+ * @tsk                   task_struct for group_leader of process
+ *                        (invariant after initialized)
+ * @deferred_work_node:   element for binder_deferred_list
+ *                        (protected by binder_deferred_lock)
+ * @deferred_work:        bitmap of deferred work to perform
+ *                        (protected by binder_deferred_lock)
+ * @is_dead:              process is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @inner_lock)
+ * @todo:                 list of work for this process
+ *                        (protected by @inner_lock)
+ * @stats:                per-process binder statistics
+ *                        (atomics, no lock needed)
+ * @delivered_death:      list of delivered death notification
+ *                        (protected by @inner_lock)
+ * @max_threads:          cap on number of binder threads
+ *                        (protected by @inner_lock)
+ * @requested_threads:    number of binder threads requested but not
+ *                        yet started. In current implementation, can
+ *                        only be 0 or 1.
+ *                        (protected by @inner_lock)
+ * @requested_threads_started: number binder threads started
+ *                        (protected by @inner_lock)
+ * @tmp_ref:              temporary reference to indicate proc is in use
+ *                        (protected by @inner_lock)
+ * @default_priority:     default scheduler priority
+ *                        (invariant after initialized)
+ * @debugfs_entry:        debugfs node
+ * @alloc:                binder allocator bookkeeping
+ * @context:              binder_context for this proc
+ *                        (invariant after initialized)
+ * @inner_lock:           can nest under outer_lock and/or node lock
+ * @outer_lock:           no nesting under innor or node lock
+ *                        Lock order: 1) outer, 2) node, 3) inner
+ * @binderfs_entry:       process-specific binderfs log file
+ *
+ * Bookkeeping structure for binder processes
+ */
+struct binder_proc {
+	struct hlist_node proc_node;
+	struct rb_root threads;
+	struct rb_root nodes;
+	struct rb_root refs_by_desc;
+	struct rb_root refs_by_node;
+	struct list_head waiting_threads;
+	int pid;
+	struct task_struct *tsk;
+	struct hlist_node deferred_work_node;
+	int deferred_work;
+	bool is_dead;
+
+	struct list_head todo;
+	struct binder_stats stats;
+	struct list_head delivered_death;
+	int max_threads;
+	int requested_threads;
+	int requested_threads_started;
+	int tmp_ref;
+	long default_priority;
+	struct dentry *debugfs_entry;
+	struct binder_alloc alloc;
+	struct binder_context *context;
+	spinlock_t inner_lock;
+	spinlock_t outer_lock;
+	struct dentry *binderfs_entry;
+};
+
+/**
+ * struct binder_thread - binder thread bookkeeping
+ * @proc:                 binder process for this thread
+ *                        (invariant after initialization)
+ * @rb_node:              element for proc->threads rbtree
+ *                        (protected by @proc->inner_lock)
+ * @waiting_thread_node:  element for @proc->waiting_threads list
+ *                        (protected by @proc->inner_lock)
+ * @pid:                  PID for this thread
+ *                        (invariant after initialization)
+ * @looper:               bitmap of looping state
+ *                        (only accessed by this thread)
+ * @looper_needs_return:  looping thread needs to exit driver
+ *                        (no lock needed)
+ * @transaction_stack:    stack of in-progress transactions for this thread
+ *                        (protected by @proc->inner_lock)
+ * @todo:                 list of work to do for this thread
+ *                        (protected by @proc->inner_lock)
+ * @process_todo:         whether work in @todo should be processed
+ *                        (protected by @proc->inner_lock)
+ * @return_error:         transaction errors reported by this thread
+ *                        (only accessed by this thread)
+ * @reply_error:          transaction errors reported by target thread
+ *                        (protected by @proc->inner_lock)
+ * @wait:                 wait queue for thread work
+ * @stats:                per-thread statistics
+ *                        (atomics, no lock needed)
+ * @tmp_ref:              temporary reference to indicate thread is in use
+ *                        (atomic since @proc->inner_lock cannot
+ *                        always be acquired)
+ * @is_dead:              thread is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder threads.
+ */
+struct binder_thread {
+	struct binder_proc *proc;
+	struct rb_node rb_node;
+	struct list_head waiting_thread_node;
+	int pid;
+	int looper;              /* only modified by this thread */
+	bool looper_need_return; /* can be written by other thread */
+	struct binder_transaction *transaction_stack;
+	struct list_head todo;
+	bool process_todo;
+	struct binder_error return_error;
+	struct binder_error reply_error;
+	wait_queue_head_t wait;
+	struct binder_stats stats;
+	atomic_t tmp_ref;
+	bool is_dead;
+};
+
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry:          list entry
+ * @file:                 struct file to be associated with new fd
+ * @offset:               offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+	struct list_head fixup_entry;
+	struct file *file;
+	size_t offset;
+};
+
+struct binder_transaction {
+	int debug_id;
+	struct binder_work work;
+	struct binder_thread *from;
+	struct binder_transaction *from_parent;
+	struct binder_proc *to_proc;
+	struct binder_thread *to_thread;
+	struct binder_transaction *to_parent;
+	unsigned need_reply:1;
+	/* unsigned is_dead:1; */       /* not used at the moment */
+
+	struct binder_buffer *buffer;
+	unsigned int    code;
+	unsigned int    flags;
+	long    priority;
+	long    saved_priority;
+	kuid_t  sender_euid;
+	struct list_head fd_fixups;
+	binder_uintptr_t security_ctx;
+	/**
+	 * @lock:  protects @from, @to_proc, and @to_thread
+	 *
+	 * @from, @to_proc, and @to_thread can be set to NULL
+	 * during thread teardown
+	 */
+	spinlock_t lock;
+};
+
+/**
+ * struct binder_object - union of flat binder object types
+ * @hdr:   generic object header
+ * @fbo:   binder object (nodes and refs)
+ * @fdo:   file descriptor object
+ * @bbo:   binder buffer pointer
+ * @fdao:  file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+	union {
+		struct binder_object_header hdr;
+		struct flat_binder_object fbo;
+		struct binder_fd_object fdo;
+		struct binder_buffer_object bbo;
+		struct binder_fd_array_object fdao;
+	};
+};
+
 extern struct binder_transaction_log binder_transaction_log;
 extern struct binder_transaction_log binder_transaction_log_failed;
 #endif /* _LINUX_BINDER_INTERNAL_H */
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v6 2/3] binder: add trace at free transaction.
  2020-07-28  3:19                                     ` [PATCH v6] " Frankie Chang
  2020-07-28  3:19                                       ` [PATCH v6 1/3] binder: move structs from core file to header file Frankie Chang
@ 2020-07-28  3:20                                       ` Frankie Chang
  2020-07-31 18:50                                         ` Todd Kjos
  2020-07-28  3:20                                       ` [PATCH v6 3/3] binder: add transaction latency tracer Frankie Chang
  2 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-07-28  3:20 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min Liu, linux-mediatek,
	Joel Fernandes, Frankie Chang, Martijn Coenen, Christian Brauner

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Since the original trace_binder_transaction_received cannot
precisely present the real finished time of transaction, adding a
trace_binder_txn_latency_free at the point of free transaction
may be more close to it.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/binder.c       |    6 ++++++
 drivers/android/binder_trace.h |   27 +++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 2df146f..1e6fc40 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1522,6 +1522,9 @@ static void binder_free_transaction(struct binder_transaction *t)
 	 * If the transaction has no target_proc, then
 	 * t->buffer->transaction has already been cleared.
 	 */
+	spin_lock(&t->lock);
+	trace_binder_txn_latency_free(t);
+	spin_unlock(&t->lock);
 	binder_free_txn_fixups(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
@@ -3093,6 +3096,9 @@ static void binder_transaction(struct binder_proc *proc,
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 err_alloc_tcomplete_failed:
+	spin_lock(&t->lock);
+	trace_binder_txn_latency_free(t);
+	spin_unlock(&t->lock);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
 err_alloc_t_failed:
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 6731c3c..8ac87d1 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,33 @@
 		  __entry->thread_todo)
 );
 
+TRACE_EVENT(binder_txn_latency_free,
+	TP_PROTO(struct binder_transaction *t),
+	TP_ARGS(t),
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, from_proc)
+		__field(int, from_thread)
+		__field(int, to_proc)
+		__field(int, to_thread)
+		__field(unsigned int, code)
+		__field(unsigned int, flags)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->from_proc = t->from ? t->from->proc->pid : 0;
+		__entry->from_thread = t->from ? t->from->pid : 0;
+		__entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
+		__entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
+		__entry->code = t->code;
+		__entry->flags = t->flags;
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
+		  __entry->to_proc, __entry->to_thread, __entry->code,
+		  __entry->flags)
+);
+
 TRACE_EVENT(binder_transaction,
 	TP_PROTO(bool reply, struct binder_transaction *t,
 		 struct binder_node *target_node),
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v6 3/3] binder: add transaction latency tracer
  2020-07-28  3:19                                     ` [PATCH v6] " Frankie Chang
  2020-07-28  3:19                                       ` [PATCH v6 1/3] binder: move structs from core file to header file Frankie Chang
  2020-07-28  3:20                                       ` [PATCH v6 2/3] binder: add trace at free transaction Frankie Chang
@ 2020-07-28  3:20                                       ` Frankie Chang
  2 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-07-28  3:20 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min Liu, linux-mediatek,
	Joel Fernandes, Frankie Chang, Martijn Coenen, Christian Brauner

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Record start/end timestamp for binder transaction.
When transaction is completed or transaction is free,
it would be checked if transaction latency over threshold
(default 2 sec), if yes, printing related information for tracing.

/* Implement details */
- Add latency tracer module to monitor transaction
  by attaching to new tracepoints introduced
  when transactions are allocated and freed.
  The trace_binder_txn_latency_free would not be enabled
  by default. Monitoring which transaction is too slow to
  cause some of exceptions is important. So we hook the
  tracepoint to call the monitor function.

- Since some of modules would trigger timeout NE
  if their binder transaction don't finish in time,
  such as audio timeout (5 sec), even BT command
  timeout (2 sec), etc.
  Therefore, setting the timeout threshold as default
  2 seconds could be helpful to debug.
  But this timeout threshold is configurable, to let
  all users determine the more suitable threshold.

- The reason why printing the related information to
  kernel information log but not trace buffer is that
  some abnormal transactions may be pending for a long
  time ago, they could not be recorded due to buffer
  limited.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/Kconfig                 |    8 +++
 drivers/android/Makefile                |    1 +
 drivers/android/binder.c                |    2 +
 drivers/android/binder_internal.h       |   13 ++++
 drivers/android/binder_latency_tracer.c |  112 +++++++++++++++++++++++++++++++
 drivers/android/binder_trace.h          |   26 ++++++-
 6 files changed, 159 insertions(+), 3 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 6fdf2ab..91fff1e 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
 	  exhaustively with combinations of various buffer sizes and
 	  alignments.
 
+config BINDER_TRANSACTION_LATENCY_TRACKING
+	tristate "Android Binder transaction tracking"
+	help
+	  Used for track abnormal binder transaction which is over threshold,
+	  when the transaction is done or be free, this transaction would be
+	  checked whether it executed overtime.
+	  If yes, printing out the detailed info.
+
 endif # if ANDROID
 
 endmenu
diff --git a/drivers/android/Makefile b/drivers/android/Makefile
index c9d3d0c9..c2ffdb6 100644
--- a/drivers/android/Makefile
+++ b/drivers/android/Makefile
@@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
 obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
 obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
 obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
+obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)	+= binder_latency_tracer.o
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 1e6fc40..0956403 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2658,6 +2658,7 @@ static void binder_transaction(struct binder_proc *proc,
 		return_error_line = __LINE__;
 		goto err_alloc_t_failed;
 	}
+	trace_binder_txn_latency_alloc(t);
 	INIT_LIST_HEAD(&t->fd_fixups);
 	binder_stats_created(BINDER_STAT_TRANSACTION);
 	spin_lock_init(&t->lock);
@@ -5147,6 +5148,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
 		   to_proc ? to_proc->pid : 0,
 		   t->to_thread ? t->to_thread->pid : 0,
 		   t->code, t->flags, t->priority, t->need_reply);
+	trace_binder_txn_latency_info(m, t);
 	spin_unlock(&t->lock);
 
 	if (proc != to_proc) {
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index 5b65413..596db00 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -13,6 +13,11 @@
 #include <linux/uidgid.h>
 #include "binder_alloc.h"
 
+#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
+#include <linux/rtc.h>
+#include <linux/time.h>
+#endif
+
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
 	struct mutex context_mgr_node_lock;
@@ -521,6 +526,14 @@ struct binder_transaction {
 	 * during thread teardown
 	 */
 	spinlock_t lock;
+	/**
+	 * @timestamp and @tv are used to record the time
+	 * that the binder transaction startup
+	 */
+#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
+	struct timespec64 timestamp;
+	struct timeval tv;
+#endif
 };
 
 /**
diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
new file mode 100644
index 0000000..b339ae1
--- /dev/null
+++ b/drivers/android/binder_latency_tracer.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ */
+
+#include <linux/module.h>
+#include <uapi/linux/android/binder.h>
+#include "binder_internal.h"
+#include "binder_trace.h"
+
+/**
+ * The reason setting the binder_txn_latency_threshold to 2 sec
+ * is that most of timeout abort is greater or equal to 2 sec.
+ * Making it configurable to let all users determine which
+ * threshold is more suitable.
+ */
+static uint32_t binder_txn_latency_threshold = 2;
+module_param_named(threshold, binder_txn_latency_threshold,
+			uint, 0644);
+
+/*
+ * probe_binder_txn_latency_free - Output info of a delay transaction
+ * @t:          pointer to the over-time transaction
+ */
+void probe_binder_txn_latency_free(void *ignore, struct binder_transaction *t)
+{
+	struct rtc_time tm;
+	struct timespec64 *startime;
+	struct timespec64 cur, sub_t;
+
+	ktime_get_ts64(&cur);
+	startime = &t->timestamp;
+	sub_t = timespec64_sub(cur, *startime);
+
+	/* if transaction time is over than binder_txn_latency_threshold (sec),
+	 * show timeout warning log.
+	 */
+	if (sub_t.tv_sec < binder_txn_latency_threshold)
+		return;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+
+	pr_info_ratelimited("%d: from %d:%d to %d:%d",
+			t->debug_id,
+			t->from ? t->from->proc->pid : 0,
+			t->from ? t->from->pid : 0,
+			t->to_proc ? t->to_proc->pid : 0,
+			t->to_thread ? t->to_thread->pid : 0);
+
+	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
+			(unsigned int)sub_t.tv_sec,
+			(sub_t.tv_nsec / NSEC_PER_MSEC),
+			t->code,
+			(unsigned long)startime->tv_sec,
+			(startime->tv_nsec / NSEC_PER_MSEC),
+			(tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+			tm.tm_hour, tm.tm_min, tm.tm_sec,
+			(unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+
+static void probe_binder_txn_latency_alloc(void *ignore,
+					struct binder_transaction *t)
+{
+	struct timespec64 now;
+	ktime_get_ts64(&t->timestamp);
+	ktime_get_real_ts64(&now);
+	t->tv.tv_sec = now.tv_sec;
+	t->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
+	t->tv.tv_usec = now.tv_nsec/1000;
+}
+
+static void probe_binder_txn_latency_info(void *ignore, struct seq_file *m,
+					struct binder_transaction *t)
+{
+	struct rtc_time tm;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+	seq_printf(m,
+		   " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
+		   (unsigned long)t->timestamp.tv_sec,
+		   (t->timestamp.tv_nsec / NSEC_PER_USEC),
+		   (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+		   tm.tm_hour, tm.tm_min, tm.tm_sec,
+		   (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+
+static int __init init_binder_latency_tracer(void)
+{
+	register_trace_binder_txn_latency_free(
+			probe_binder_txn_latency_free, NULL);
+	register_trace_binder_txn_latency_alloc(
+			probe_binder_txn_latency_alloc, NULL);
+	register_trace_binder_txn_latency_info(
+			probe_binder_txn_latency_info, NULL);
+
+	return 0;
+}
+
+static void exit_binder_latency_tracer(void)
+{
+	unregister_trace_binder_txn_latency_free(
+			probe_binder_txn_latency_free, NULL);
+	unregister_trace_binder_txn_latency_alloc(
+			probe_binder_txn_latency_alloc, NULL);
+	unregister_trace_binder_txn_latency_info(
+			probe_binder_txn_latency_info, NULL);
+}
+
+module_init(init_binder_latency_tracer);
+module_exit(exit_binder_latency_tracer);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 8ac87d1..405d493 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,17 @@
 		  __entry->thread_todo)
 );
 
+DECLARE_TRACE(binder_txn_latency_alloc,
+	TP_PROTO(struct binder_transaction *t),
+	TP_ARGS(t, e)
+);
+
+DECLARE_TRACE(binder_txn_latency_info,
+	TP_PROTO(struct seq_file *m,
+		 struct binder_transaction *t),
+	TP_ARGS(m, t)
+);
+
 TRACE_EVENT(binder_txn_latency_free,
 	TP_PROTO(struct binder_transaction *t),
 	TP_ARGS(t),
@@ -106,6 +117,8 @@
 		__field(int, to_thread)
 		__field(unsigned int, code)
 		__field(unsigned int, flags)
+		__field(unsigned long, start_sec)
+		__field(unsigned long, start_nsec)
 	),
 	TP_fast_assign(
 		__entry->debug_id = t->debug_id;
@@ -115,11 +128,18 @@
 		__entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
 		__entry->code = t->code;
 		__entry->flags = t->flags;
-	),
-	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
+		__entry->start_sec = t->timestamp.tv_sec;
+		__entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
+#else
+		__entry->start_sec = 0;
+		__entry->start_nsec = 0;
+#endif
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
 		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
 		  __entry->to_proc, __entry->to_thread, __entry->code,
-		  __entry->flags)
+		  __entry->flags, __entry->start_sec, __entry->start_nsec)
 );
 
 TRACE_EVENT(binder_transaction,
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v6 2/3] binder: add trace at free transaction.
  2020-07-28  3:20                                       ` [PATCH v6 2/3] binder: add trace at free transaction Frankie Chang
@ 2020-07-31 18:50                                         ` Todd Kjos
  2020-08-03  3:11                                           ` Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Todd Kjos @ 2020-07-31 18:50 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Mon, Jul 27, 2020 at 8:28 PM Frankie Chang
<Frankie.Chang@mediatek.com> wrote:
>
> From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
>
> Since the original trace_binder_transaction_received cannot
> precisely present the real finished time of transaction, adding a
> trace_binder_txn_latency_free at the point of free transaction
> may be more close to it.
>
> Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> ---
>  drivers/android/binder.c       |    6 ++++++
>  drivers/android/binder_trace.h |   27 +++++++++++++++++++++++++++
>  2 files changed, 33 insertions(+)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 2df146f..1e6fc40 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -1522,6 +1522,9 @@ static void binder_free_transaction(struct binder_transaction *t)
>          * If the transaction has no target_proc, then
>          * t->buffer->transaction has already been cleared.
>          */
> +       spin_lock(&t->lock);
> +       trace_binder_txn_latency_free(t);
> +       spin_unlock(&t->lock);

Hmm. I don't prefer taking the lock just to call a trace. It doesn't
make clear why the lock has to be taken. I'd prefer something like:

if (trace_binder_txn_latency_free_enabled()) {
  int to_proc, to_thread;

  spin_lock(&t->lock);
  to_proc = t->to_proc ? t->to_proc->pid : 0;
  to_thread = t->to_thread ? t->to_thread->pid : 0;
  spin_unlock(&t->lock);
  trace_binder_txn_latency_free(t, to_proc, to_pid);
}

And then the trace would use the passed-in values instead of accessing
via t->to_proc/to_thread.

>         binder_free_txn_fixups(t);
>         kfree(t);
>         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> @@ -3093,6 +3096,9 @@ static void binder_transaction(struct binder_proc *proc,
>         kfree(tcomplete);
>         binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
>  err_alloc_tcomplete_failed:
> +       spin_lock(&t->lock);
> +       trace_binder_txn_latency_free(t);
> +       spin_unlock(&t->lock);
>         kfree(t);
>         binder_stats_deleted(BINDER_STAT_TRANSACTION);
>  err_alloc_t_failed:
> diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> index 6731c3c..8ac87d1 100644
> --- a/drivers/android/binder_trace.h
> +++ b/drivers/android/binder_trace.h
> @@ -95,6 +95,33 @@
>                   __entry->thread_todo)
>  );
>
> +TRACE_EVENT(binder_txn_latency_free,
> +       TP_PROTO(struct binder_transaction *t),
> +       TP_ARGS(t),
> +       TP_STRUCT__entry(
> +               __field(int, debug_id)
> +               __field(int, from_proc)
> +               __field(int, from_thread)
> +               __field(int, to_proc)
> +               __field(int, to_thread)
> +               __field(unsigned int, code)
> +               __field(unsigned int, flags)
> +       ),
> +       TP_fast_assign(
> +               __entry->debug_id = t->debug_id;
> +               __entry->from_proc = t->from ? t->from->proc->pid : 0;
> +               __entry->from_thread = t->from ? t->from->pid : 0;
> +               __entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
> +               __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
> +               __entry->code = t->code;
> +               __entry->flags = t->flags;
> +       ),
> +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> +                 __entry->debug_id, __entry->from_proc, __entry->from_thread,
> +                 __entry->to_proc, __entry->to_thread, __entry->code,
> +                 __entry->flags)
> +);
> +
>  TRACE_EVENT(binder_transaction,
>         TP_PROTO(bool reply, struct binder_transaction *t,
>                  struct binder_node *target_node),
> --
> 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v6 2/3] binder: add trace at free transaction.
  2020-07-31 18:50                                         ` Todd Kjos
@ 2020-08-03  3:11                                           ` Frankie Chang
  2020-08-03 15:12                                             ` Todd Kjos
  0 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-08-03  3:11 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Fri, 2020-07-31 at 11:50 -0700, Todd Kjos wrote:
> On Mon, Jul 27, 2020 at 8:28 PM Frankie Chang
> <Frankie.Chang@mediatek.com> wrote:
> >
> > From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
> >
> > Since the original trace_binder_transaction_received cannot
> > precisely present the real finished time of transaction, adding a
> > trace_binder_txn_latency_free at the point of free transaction
> > may be more close to it.
> >
> > Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> > ---
> >  drivers/android/binder.c       |    6 ++++++
> >  drivers/android/binder_trace.h |   27 +++++++++++++++++++++++++++
> >  2 files changed, 33 insertions(+)
> >
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index 2df146f..1e6fc40 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -1522,6 +1522,9 @@ static void binder_free_transaction(struct binder_transaction *t)
> >          * If the transaction has no target_proc, then
> >          * t->buffer->transaction has already been cleared.
> >          */
> > +       spin_lock(&t->lock);
> > +       trace_binder_txn_latency_free(t);
> > +       spin_unlock(&t->lock);
> 
> Hmm. I don't prefer taking the lock just to call a trace. It doesn't
> make clear why the lock has to be taken. I'd prefer something like:
> 
> if (trace_binder_txn_latency_free_enabled()) {
c
> }
> 
> And then the trace would use the passed-in values instead of accessing
> via t->to_proc/to_thread.
> 
Then we still add lock protection in the hook function, when trace is
disable ?

Or we also pass these to hook function, no matter the trace is enable or
not.I think this way is more clear that the lock protects @from,
@to_proc and @to_thread.Then, there is no need to add the lock in hook
function.

int from_proc, from_thread, to_proc, to_thread;
 
spin_lock(&t->lock);
from_proc = t->from ? t->from->proc->pid : 0;
from_thread = t->from ? t->from->pid :0;
to_proc = t->to_proc ? t->to_proc->pid : 0;
to_thread = t->to_thread ? t->to_thread->pid : 0;
spin_unlock(&t->lock);
trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc,
to_pid);

> >         binder_free_txn_fixups(t);
> >         kfree(t);
> >         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> > @@ -3093,6 +3096,9 @@ static void binder_transaction(struct binder_proc *proc,
> >         kfree(tcomplete);
> >         binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
> >  err_alloc_tcomplete_failed:
> > +       spin_lock(&t->lock);
> > +       trace_binder_txn_latency_free(t);
> > +       spin_unlock(&t->lock);
> >         kfree(t);
> >         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> >  err_alloc_t_failed:
> > diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> > index 6731c3c..8ac87d1 100644
> > --- a/drivers/android/binder_trace.h
> > +++ b/drivers/android/binder_trace.h
> > @@ -95,6 +95,33 @@
> >                   __entry->thread_todo)
> >  );
> >
> > +TRACE_EVENT(binder_txn_latency_free,
> > +       TP_PROTO(struct binder_transaction *t),
> > +       TP_ARGS(t),
> > +       TP_STRUCT__entry(
> > +               __field(int, debug_id)
> > +               __field(int, from_proc)
> > +               __field(int, from_thread)
> > +               __field(int, to_proc)
> > +               __field(int, to_thread)
> > +               __field(unsigned int, code)
> > +               __field(unsigned int, flags)
> > +       ),
> > +       TP_fast_assign(
> > +               __entry->debug_id = t->debug_id;
> > +               __entry->from_proc = t->from ? t->from->proc->pid : 0;
> > +               __entry->from_thread = t->from ? t->from->pid : 0;
> > +               __entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
> > +               __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
> > +               __entry->code = t->code;
> > +               __entry->flags = t->flags;
> > +       ),
> > +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> > +                 __entry->debug_id, __entry->from_proc, __entry->from_thread,
> > +                 __entry->to_proc, __entry->to_thread, __entry->code,
> > +                 __entry->flags)
> > +);
> > +
> >  TRACE_EVENT(binder_transaction,
> >         TP_PROTO(bool reply, struct binder_transaction *t,
> >                  struct binder_node *target_node),
> > --
> > 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v6 2/3] binder: add trace at free transaction.
  2020-08-03  3:11                                           ` Frankie Chang
@ 2020-08-03 15:12                                             ` Todd Kjos
  2020-08-04  2:45                                               ` Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Todd Kjos @ 2020-08-03 15:12 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Sun, Aug 2, 2020 at 8:11 PM Frankie Chang <Frankie.Chang@mediatek.com> wrote:
>
> On Fri, 2020-07-31 at 11:50 -0700, Todd Kjos wrote:
> > On Mon, Jul 27, 2020 at 8:28 PM Frankie Chang
> > <Frankie.Chang@mediatek.com> wrote:
> > >
> > > From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
> > >
> > > Since the original trace_binder_transaction_received cannot
> > > precisely present the real finished time of transaction, adding a
> > > trace_binder_txn_latency_free at the point of free transaction
> > > may be more close to it.
> > >
> > > Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> > > ---
> > >  drivers/android/binder.c       |    6 ++++++
> > >  drivers/android/binder_trace.h |   27 +++++++++++++++++++++++++++
> > >  2 files changed, 33 insertions(+)
> > >
> > > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > > index 2df146f..1e6fc40 100644
> > > --- a/drivers/android/binder.c
> > > +++ b/drivers/android/binder.c
> > > @@ -1522,6 +1522,9 @@ static void binder_free_transaction(struct binder_transaction *t)
> > >          * If the transaction has no target_proc, then
> > >          * t->buffer->transaction has already been cleared.
> > >          */
> > > +       spin_lock(&t->lock);
> > > +       trace_binder_txn_latency_free(t);
> > > +       spin_unlock(&t->lock);
> >
> > Hmm. I don't prefer taking the lock just to call a trace. It doesn't
> > make clear why the lock has to be taken. I'd prefer something like:
> >
> > if (trace_binder_txn_latency_free_enabled()) {
> c
> > }
> >
> > And then the trace would use the passed-in values instead of accessing
> > via t->to_proc/to_thread.
> >
> Then we still add lock protection in the hook function, when trace is
> disable ?

I don't understand... in the example I gave, the trace doesn't get
called if disabled. What do you mean to "add lock protection when the
trace is disabled()"?

>
> Or we also pass these to hook function, no matter the trace is enable or

What do you mean by "hook" function? If something has attached to the
trace, then xxx_enabled() will return true.

> not.I think this way is more clear that the lock protects @from,
> @to_proc and @to_thread.Then, there is no need to add the lock in hook
> function.

Why is it clearer (other than the fact that I missed including t->from
under the lock)?

>
> int from_proc, from_thread, to_proc, to_thread;
>
> spin_lock(&t->lock);
> from_proc = t->from ? t->from->proc->pid : 0;
> from_thread = t->from ? t->from->pid :0;
> to_proc = t->to_proc ? t->to_proc->pid : 0;
> to_thread = t->to_thread ? t->to_thread->pid : 0;
> spin_unlock(&t->lock);
> trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc,
> to_pid);

The main feedback is I'd like to see the fields dereferenced in the
same context as the lock acquisition instead of acquiring the lock and
calling the trace function, so this code would be fine. There will be
very little contention for t->lock so using xxx_enabled() is optional.

Since trace_binder_txn_latency_free() is called twice,  it would make
sense to have a helper function to do the above.

>
> > >         binder_free_txn_fixups(t);
> > >         kfree(t);
> > >         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> > > @@ -3093,6 +3096,9 @@ static void binder_transaction(struct binder_proc *proc,
> > >         kfree(tcomplete);
> > >         binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
> > >  err_alloc_tcomplete_failed:
> > > +       spin_lock(&t->lock);
> > > +       trace_binder_txn_latency_free(t);
> > > +       spin_unlock(&t->lock);
> > >         kfree(t);
> > >         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> > >  err_alloc_t_failed:
> > > diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> > > index 6731c3c..8ac87d1 100644
> > > --- a/drivers/android/binder_trace.h
> > > +++ b/drivers/android/binder_trace.h
> > > @@ -95,6 +95,33 @@
> > >                   __entry->thread_todo)
> > >  );
> > >
> > > +TRACE_EVENT(binder_txn_latency_free,
> > > +       TP_PROTO(struct binder_transaction *t),
> > > +       TP_ARGS(t),
> > > +       TP_STRUCT__entry(
> > > +               __field(int, debug_id)
> > > +               __field(int, from_proc)
> > > +               __field(int, from_thread)
> > > +               __field(int, to_proc)
> > > +               __field(int, to_thread)
> > > +               __field(unsigned int, code)
> > > +               __field(unsigned int, flags)
> > > +       ),
> > > +       TP_fast_assign(
> > > +               __entry->debug_id = t->debug_id;
> > > +               __entry->from_proc = t->from ? t->from->proc->pid : 0;
> > > +               __entry->from_thread = t->from ? t->from->pid : 0;
> > > +               __entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
> > > +               __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
> > > +               __entry->code = t->code;
> > > +               __entry->flags = t->flags;
> > > +       ),
> > > +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> > > +                 __entry->debug_id, __entry->from_proc, __entry->from_thread,
> > > +                 __entry->to_proc, __entry->to_thread, __entry->code,
> > > +                 __entry->flags)
> > > +);
> > > +
> > >  TRACE_EVENT(binder_transaction,
> > >         TP_PROTO(bool reply, struct binder_transaction *t,
> > >                  struct binder_node *target_node),
> > > --
> > > 1.7.9.5
>

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v6 2/3] binder: add trace at free transaction.
  2020-08-03 15:12                                             ` Todd Kjos
@ 2020-08-04  2:45                                               ` Frankie Chang
  2020-08-04 13:59                                                 ` [PATCH v7] binder: transaction latency tracking for user build Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-08-04  2:45 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Mon, 2020-08-03 at 08:12 -0700, Todd Kjos wrote:
> On Sun, Aug 2, 2020 at 8:11 PM Frankie Chang <Frankie.Chang@mediatek.com> wrote:
> >
> > On Fri, 2020-07-31 at 11:50 -0700, Todd Kjos wrote:
> > > On Mon, Jul 27, 2020 at 8:28 PM Frankie Chang
> > > <Frankie.Chang@mediatek.com> wrote:
> > > >
> > > > From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
> > > >
> > > > Since the original trace_binder_transaction_received cannot
> > > > precisely present the real finished time of transaction, adding a
> > > > trace_binder_txn_latency_free at the point of free transaction
> > > > may be more close to it.
> > > >
> > > > Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> > > > ---
> > > >  drivers/android/binder.c       |    6 ++++++
> > > >  drivers/android/binder_trace.h |   27 +++++++++++++++++++++++++++
> > > >  2 files changed, 33 insertions(+)
> > > >
> > > > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > > > index 2df146f..1e6fc40 100644
> > > > --- a/drivers/android/binder.c
> > > > +++ b/drivers/android/binder.c
> > > > @@ -1522,6 +1522,9 @@ static void binder_free_transaction(struct binder_transaction *t)
> > > >          * If the transaction has no target_proc, then
> > > >          * t->buffer->transaction has already been cleared.
> > > >          */
> > > > +       spin_lock(&t->lock);
> > > > +       trace_binder_txn_latency_free(t);
> > > > +       spin_unlock(&t->lock);
> > >
> > > Hmm. I don't prefer taking the lock just to call a trace. It doesn't
> > > make clear why the lock has to be taken. I'd prefer something like:
> > >
> > > if (trace_binder_txn_latency_free_enabled()) {
> > c
> > > }
> > >
> > > And then the trace would use the passed-in values instead of accessing
> > > via t->to_proc/to_thread.
> > >
> > Then we still add lock protection in the hook function, when trace is
> > disable ?
> 
> I don't understand... in the example I gave, the trace doesn't get
> called if disabled. What do you mean to "add lock protection when the
> trace is disabled()"?
> 
> >
> > Or we also pass these to hook function, no matter the trace is enable or
> 
> What do you mean by "hook" function? If something has attached to the
> trace, then xxx_enabled() will return true.
> 
I'm sorry for that I misunderstand this XXX_enabled(). 

> > not.I think this way is more clear that the lock protects @from,
> > @to_proc and @to_thread.Then, there is no need to add the lock in hook
> > function.
> 
> Why is it clearer (other than the fact that I missed including t->from
> under the lock)?
> 
I think your example is clear enough.

> >
> > int from_proc, from_thread, to_proc, to_thread;
> >
> > spin_lock(&t->lock);
> > from_proc = t->from ? t->from->proc->pid : 0;
> > from_thread = t->from ? t->from->pid :0;
> > to_proc = t->to_proc ? t->to_proc->pid : 0;
> > to_thread = t->to_thread ? t->to_thread->pid : 0;
> > spin_unlock(&t->lock);
> > trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc,
> > to_pid);
> 
> The main feedback is I'd like to see the fields dereferenced in the
> same context as the lock acquisition instead of acquiring the lock and
> calling the trace function, so this code would be fine. There will be
> very little contention for t->lock so using xxx_enabled() is optional.
> 
> Since trace_binder_txn_latency_free() is called twice,  it would make
> sense to have a helper function to do the above.
> 
Okay, I will make a helper function to do this in next version patch.
Very thanks for your help for this.

> >
> > > >         binder_free_txn_fixups(t);
> > > >         kfree(t);
> > > >         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> > > > @@ -3093,6 +3096,9 @@ static void binder_transaction(struct binder_proc *proc,
> > > >         kfree(tcomplete);
> > > >         binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
> > > >  err_alloc_tcomplete_failed:
> > > > +       spin_lock(&t->lock);
> > > > +       trace_binder_txn_latency_free(t);
> > > > +       spin_unlock(&t->lock);
> > > >         kfree(t);
> > > >         binder_stats_deleted(BINDER_STAT_TRANSACTION);
> > > >  err_alloc_t_failed:
> > > > diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> > > > index 6731c3c..8ac87d1 100644
> > > > --- a/drivers/android/binder_trace.h
> > > > +++ b/drivers/android/binder_trace.h
> > > > @@ -95,6 +95,33 @@
> > > >                   __entry->thread_todo)
> > > >  );
> > > >
> > > > +TRACE_EVENT(binder_txn_latency_free,
> > > > +       TP_PROTO(struct binder_transaction *t),
> > > > +       TP_ARGS(t),
> > > > +       TP_STRUCT__entry(
> > > > +               __field(int, debug_id)
> > > > +               __field(int, from_proc)
> > > > +               __field(int, from_thread)
> > > > +               __field(int, to_proc)
> > > > +               __field(int, to_thread)
> > > > +               __field(unsigned int, code)
> > > > +               __field(unsigned int, flags)
> > > > +       ),
> > > > +       TP_fast_assign(
> > > > +               __entry->debug_id = t->debug_id;
> > > > +               __entry->from_proc = t->from ? t->from->proc->pid : 0;
> > > > +               __entry->from_thread = t->from ? t->from->pid : 0;
> > > > +               __entry->to_proc = t->to_proc ? t->to_proc->pid : 0;
> > > > +               __entry->to_thread = t->to_thread ? t->to_thread->pid : 0;
> > > > +               __entry->code = t->code;
> > > > +               __entry->flags = t->flags;
> > > > +       ),
> > > > +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> > > > +                 __entry->debug_id, __entry->from_proc, __entry->from_thread,
> > > > +                 __entry->to_proc, __entry->to_thread, __entry->code,
> > > > +                 __entry->flags)
> > > > +);
> > > > +
> > > >  TRACE_EVENT(binder_transaction,
> > > >         TP_PROTO(bool reply, struct binder_transaction *t,
> > > >                  struct binder_node *target_node),
> > > > --
> > > > 1.7.9.5
> >

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v7] binder: transaction latency tracking for user build
  2020-08-04  2:45                                               ` Frankie Chang
@ 2020-08-04 13:59                                                 ` Frankie Chang
  2020-08-04 13:59                                                   ` [PATCH v7 1/3] binder: move structs from core file to header file Frankie Chang
                                                                     ` (3 more replies)
  0 siblings, 4 replies; 72+ messages in thread
From: Frankie Chang @ 2020-08-04 13:59 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min Liu, linux-mediatek,
	Joel Fernandes, Frankie Chang, Martijn Coenen, Christian Brauner


Frankie.Chang (3):
  binder: move structs from core file to header file
  binder: add trace at free transaction.
  binder: add transaction latency tracer

 drivers/android/Kconfig                 |    8 +
 drivers/android/Makefile                |    1 +
 drivers/android/binder.c                |  425 ++-----------------------------
 drivers/android/binder_internal.h       |  417 ++++++++++++++++++++++++++++++
 drivers/android/binder_latency_tracer.c |  112 ++++++++
 drivers/android/binder_trace.h          |   49 ++++
 6 files changed, 607 insertions(+), 405 deletions(-)  create mode 100644 drivers/android/binder_latency_tracer.c

Change from v7:
  - Use the passed-in values instead of accessing via t->from/to_proc/to_thread
    for trace_binder_txn_latency_free, when trace_binder_txn_latency_free_enable() return true.
  - make a helper function to do the above.

Change from v6:
  - change CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING type from bool to tristate
  - add comments to @timestamp and @tv under struct binder_transaction
  - make binder_txn_latency threshold configurable
  - enhance lock protection

Change from v5:
  - change config name to the proper one, CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING.
  - change tracepoint name to more descriptive one, trace_binder_txn_latency_(alloc|info|free)
  - enhance some lock protection.

Change from v4:
  - split up into patch series.

Change from v3:
  - use tracepoints for binder_update_info and print_binder_transaction_ext,
    instead of custom registration functions.

Change from v2:
  - create transaction latency module to monitor slow transaction.

Change from v1:
  - first patchset.
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v7 1/3] binder: move structs from core file to header file
  2020-08-04 13:59                                                 ` [PATCH v7] binder: transaction latency tracking for user build Frankie Chang
@ 2020-08-04 13:59                                                   ` Frankie Chang
  2020-08-04 15:24                                                     ` Todd Kjos
  2020-08-04 13:59                                                   ` [PATCH v7 2/3] binder: add trace at free transaction Frankie Chang
                                                                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-08-04 13:59 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min Liu, linux-mediatek,
	Joel Fernandes, Frankie Chang, Martijn Coenen, Christian Brauner

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Moving all structs to header file makes module more
extendable, and makes all these structs to be defined
in the same file.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/binder.c          |  405 -------------------------------------
 drivers/android/binder_internal.h |  404 ++++++++++++++++++++++++++++++++++++
 2 files changed, 404 insertions(+), 405 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index a6b2082..2df146f 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -72,7 +72,6 @@
 
 #include <asm/cacheflush.h>
 
-#include "binder_alloc.h"
 #include "binder_internal.h"
 #include "binder_trace.h"
 
@@ -160,24 +159,6 @@ static int binder_set_stop_on_user_error(const char *val,
 #define to_binder_fd_array_object(hdr) \
 	container_of(hdr, struct binder_fd_array_object, hdr)
 
-enum binder_stat_types {
-	BINDER_STAT_PROC,
-	BINDER_STAT_THREAD,
-	BINDER_STAT_NODE,
-	BINDER_STAT_REF,
-	BINDER_STAT_DEATH,
-	BINDER_STAT_TRANSACTION,
-	BINDER_STAT_TRANSACTION_COMPLETE,
-	BINDER_STAT_COUNT
-};
-
-struct binder_stats {
-	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
-	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
-	atomic_t obj_created[BINDER_STAT_COUNT];
-	atomic_t obj_deleted[BINDER_STAT_COUNT];
-};
-
 static struct binder_stats binder_stats;
 
 static inline void binder_stats_deleted(enum binder_stat_types type)
@@ -213,278 +194,11 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
 	return e;
 }
 
-/**
- * struct binder_work - work enqueued on a worklist
- * @entry:             node enqueued on list
- * @type:              type of work to be performed
- *
- * There are separate work lists for proc, thread, and node (async).
- */
-struct binder_work {
-	struct list_head entry;
-
-	enum {
-		BINDER_WORK_TRANSACTION = 1,
-		BINDER_WORK_TRANSACTION_COMPLETE,
-		BINDER_WORK_RETURN_ERROR,
-		BINDER_WORK_NODE,
-		BINDER_WORK_DEAD_BINDER,
-		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
-		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
-	} type;
-};
-
-struct binder_error {
-	struct binder_work work;
-	uint32_t cmd;
-};
-
-/**
- * struct binder_node - binder node bookkeeping
- * @debug_id:             unique ID for debugging
- *                        (invariant after initialized)
- * @lock:                 lock for node fields
- * @work:                 worklist element for node work
- *                        (protected by @proc->inner_lock)
- * @rb_node:              element for proc->nodes tree
- *                        (protected by @proc->inner_lock)
- * @dead_node:            element for binder_dead_nodes list
- *                        (protected by binder_dead_nodes_lock)
- * @proc:                 binder_proc that owns this node
- *                        (invariant after initialized)
- * @refs:                 list of references on this node
- *                        (protected by @lock)
- * @internal_strong_refs: used to take strong references when
- *                        initiating a transaction
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_weak_refs:      weak user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_strong_refs:    strong user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @tmp_refs:             temporary kernel refs
- *                        (protected by @proc->inner_lock while @proc
- *                        is valid, and by binder_dead_nodes_lock
- *                        if @proc is NULL. During inc/dec and node release
- *                        it is also protected by @lock to provide safety
- *                        as the node dies and @proc becomes NULL)
- * @ptr:                  userspace pointer for node
- *                        (invariant, no lock needed)
- * @cookie:               userspace cookie for node
- *                        (invariant, no lock needed)
- * @has_strong_ref:       userspace notified of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_strong_ref:   userspace has acked notification of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_weak_ref:         userspace notified of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_weak_ref:     userspace has acked notification of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_async_transaction: async transaction to node in progress
- *                        (protected by @lock)
- * @accept_fds:           file descriptor operations supported for node
- *                        (invariant after initialized)
- * @min_priority:         minimum scheduling priority
- *                        (invariant after initialized)
- * @txn_security_ctx:     require sender's security context
- *                        (invariant after initialized)
- * @async_todo:           list of async work items
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder nodes.
- */
-struct binder_node {
-	int debug_id;
-	spinlock_t lock;
-	struct binder_work work;
-	union {
-		struct rb_node rb_node;
-		struct hlist_node dead_node;
-	};
-	struct binder_proc *proc;
-	struct hlist_head refs;
-	int internal_strong_refs;
-	int local_weak_refs;
-	int local_strong_refs;
-	int tmp_refs;
-	binder_uintptr_t ptr;
-	binder_uintptr_t cookie;
-	struct {
-		/*
-		 * bitfield elements protected by
-		 * proc inner_lock
-		 */
-		u8 has_strong_ref:1;
-		u8 pending_strong_ref:1;
-		u8 has_weak_ref:1;
-		u8 pending_weak_ref:1;
-	};
-	struct {
-		/*
-		 * invariant after initialization
-		 */
-		u8 accept_fds:1;
-		u8 txn_security_ctx:1;
-		u8 min_priority;
-	};
-	bool has_async_transaction;
-	struct list_head async_todo;
-};
-
-struct binder_ref_death {
-	/**
-	 * @work: worklist element for death notifications
-	 *        (protected by inner_lock of the proc that
-	 *        this ref belongs to)
-	 */
-	struct binder_work work;
-	binder_uintptr_t cookie;
-};
-
-/**
- * struct binder_ref_data - binder_ref counts and id
- * @debug_id:        unique ID for the ref
- * @desc:            unique userspace handle for ref
- * @strong:          strong ref count (debugging only if not locked)
- * @weak:            weak ref count (debugging only if not locked)
- *
- * Structure to hold ref count and ref id information. Since
- * the actual ref can only be accessed with a lock, this structure
- * is used to return information about the ref to callers of
- * ref inc/dec functions.
- */
-struct binder_ref_data {
-	int debug_id;
-	uint32_t desc;
-	int strong;
-	int weak;
-};
-
-/**
- * struct binder_ref - struct to track references on nodes
- * @data:        binder_ref_data containing id, handle, and current refcounts
- * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
- * @rb_node_node: node for lookup by @node in proc's rb_tree
- * @node_entry:  list entry for node->refs list in target node
- *               (protected by @node->lock)
- * @proc:        binder_proc containing ref
- * @node:        binder_node of target node. When cleaning up a
- *               ref for deletion in binder_cleanup_ref, a non-NULL
- *               @node indicates the node must be freed
- * @death:       pointer to death notification (ref_death) if requested
- *               (protected by @node->lock)
- *
- * Structure to track references from procA to target node (on procB). This
- * structure is unsafe to access without holding @proc->outer_lock.
- */
-struct binder_ref {
-	/* Lookups needed: */
-	/*   node + proc => ref (transaction) */
-	/*   desc + proc => ref (transaction, inc/dec ref) */
-	/*   node => refs + procs (proc exit) */
-	struct binder_ref_data data;
-	struct rb_node rb_node_desc;
-	struct rb_node rb_node_node;
-	struct hlist_node node_entry;
-	struct binder_proc *proc;
-	struct binder_node *node;
-	struct binder_ref_death *death;
-};
-
 enum binder_deferred_state {
 	BINDER_DEFERRED_FLUSH        = 0x01,
 	BINDER_DEFERRED_RELEASE      = 0x02,
 };
 
-/**
- * struct binder_proc - binder process bookkeeping
- * @proc_node:            element for binder_procs list
- * @threads:              rbtree of binder_threads in this proc
- *                        (protected by @inner_lock)
- * @nodes:                rbtree of binder nodes associated with
- *                        this proc ordered by node->ptr
- *                        (protected by @inner_lock)
- * @refs_by_desc:         rbtree of refs ordered by ref->desc
- *                        (protected by @outer_lock)
- * @refs_by_node:         rbtree of refs ordered by ref->node
- *                        (protected by @outer_lock)
- * @waiting_threads:      threads currently waiting for proc work
- *                        (protected by @inner_lock)
- * @pid                   PID of group_leader of process
- *                        (invariant after initialized)
- * @tsk                   task_struct for group_leader of process
- *                        (invariant after initialized)
- * @deferred_work_node:   element for binder_deferred_list
- *                        (protected by binder_deferred_lock)
- * @deferred_work:        bitmap of deferred work to perform
- *                        (protected by binder_deferred_lock)
- * @is_dead:              process is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @inner_lock)
- * @todo:                 list of work for this process
- *                        (protected by @inner_lock)
- * @stats:                per-process binder statistics
- *                        (atomics, no lock needed)
- * @delivered_death:      list of delivered death notification
- *                        (protected by @inner_lock)
- * @max_threads:          cap on number of binder threads
- *                        (protected by @inner_lock)
- * @requested_threads:    number of binder threads requested but not
- *                        yet started. In current implementation, can
- *                        only be 0 or 1.
- *                        (protected by @inner_lock)
- * @requested_threads_started: number binder threads started
- *                        (protected by @inner_lock)
- * @tmp_ref:              temporary reference to indicate proc is in use
- *                        (protected by @inner_lock)
- * @default_priority:     default scheduler priority
- *                        (invariant after initialized)
- * @debugfs_entry:        debugfs node
- * @alloc:                binder allocator bookkeeping
- * @context:              binder_context for this proc
- *                        (invariant after initialized)
- * @inner_lock:           can nest under outer_lock and/or node lock
- * @outer_lock:           no nesting under innor or node lock
- *                        Lock order: 1) outer, 2) node, 3) inner
- * @binderfs_entry:       process-specific binderfs log file
- *
- * Bookkeeping structure for binder processes
- */
-struct binder_proc {
-	struct hlist_node proc_node;
-	struct rb_root threads;
-	struct rb_root nodes;
-	struct rb_root refs_by_desc;
-	struct rb_root refs_by_node;
-	struct list_head waiting_threads;
-	int pid;
-	struct task_struct *tsk;
-	struct hlist_node deferred_work_node;
-	int deferred_work;
-	bool is_dead;
-
-	struct list_head todo;
-	struct binder_stats stats;
-	struct list_head delivered_death;
-	int max_threads;
-	int requested_threads;
-	int requested_threads_started;
-	int tmp_ref;
-	long default_priority;
-	struct dentry *debugfs_entry;
-	struct binder_alloc alloc;
-	struct binder_context *context;
-	spinlock_t inner_lock;
-	spinlock_t outer_lock;
-	struct dentry *binderfs_entry;
-};
-
 enum {
 	BINDER_LOOPER_STATE_REGISTERED  = 0x01,
 	BINDER_LOOPER_STATE_ENTERED     = 0x02,
@@ -495,125 +209,6 @@ enum {
 };
 
 /**
- * struct binder_thread - binder thread bookkeeping
- * @proc:                 binder process for this thread
- *                        (invariant after initialization)
- * @rb_node:              element for proc->threads rbtree
- *                        (protected by @proc->inner_lock)
- * @waiting_thread_node:  element for @proc->waiting_threads list
- *                        (protected by @proc->inner_lock)
- * @pid:                  PID for this thread
- *                        (invariant after initialization)
- * @looper:               bitmap of looping state
- *                        (only accessed by this thread)
- * @looper_needs_return:  looping thread needs to exit driver
- *                        (no lock needed)
- * @transaction_stack:    stack of in-progress transactions for this thread
- *                        (protected by @proc->inner_lock)
- * @todo:                 list of work to do for this thread
- *                        (protected by @proc->inner_lock)
- * @process_todo:         whether work in @todo should be processed
- *                        (protected by @proc->inner_lock)
- * @return_error:         transaction errors reported by this thread
- *                        (only accessed by this thread)
- * @reply_error:          transaction errors reported by target thread
- *                        (protected by @proc->inner_lock)
- * @wait:                 wait queue for thread work
- * @stats:                per-thread statistics
- *                        (atomics, no lock needed)
- * @tmp_ref:              temporary reference to indicate thread is in use
- *                        (atomic since @proc->inner_lock cannot
- *                        always be acquired)
- * @is_dead:              thread is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder threads.
- */
-struct binder_thread {
-	struct binder_proc *proc;
-	struct rb_node rb_node;
-	struct list_head waiting_thread_node;
-	int pid;
-	int looper;              /* only modified by this thread */
-	bool looper_need_return; /* can be written by other thread */
-	struct binder_transaction *transaction_stack;
-	struct list_head todo;
-	bool process_todo;
-	struct binder_error return_error;
-	struct binder_error reply_error;
-	wait_queue_head_t wait;
-	struct binder_stats stats;
-	atomic_t tmp_ref;
-	bool is_dead;
-};
-
-/**
- * struct binder_txn_fd_fixup - transaction fd fixup list element
- * @fixup_entry:          list entry
- * @file:                 struct file to be associated with new fd
- * @offset:               offset in buffer data to this fixup
- *
- * List element for fd fixups in a transaction. Since file
- * descriptors need to be allocated in the context of the
- * target process, we pass each fd to be processed in this
- * struct.
- */
-struct binder_txn_fd_fixup {
-	struct list_head fixup_entry;
-	struct file *file;
-	size_t offset;
-};
-
-struct binder_transaction {
-	int debug_id;
-	struct binder_work work;
-	struct binder_thread *from;
-	struct binder_transaction *from_parent;
-	struct binder_proc *to_proc;
-	struct binder_thread *to_thread;
-	struct binder_transaction *to_parent;
-	unsigned need_reply:1;
-	/* unsigned is_dead:1; */	/* not used at the moment */
-
-	struct binder_buffer *buffer;
-	unsigned int	code;
-	unsigned int	flags;
-	long	priority;
-	long	saved_priority;
-	kuid_t	sender_euid;
-	struct list_head fd_fixups;
-	binder_uintptr_t security_ctx;
-	/**
-	 * @lock:  protects @from, @to_proc, and @to_thread
-	 *
-	 * @from, @to_proc, and @to_thread can be set to NULL
-	 * during thread teardown
-	 */
-	spinlock_t lock;
-};
-
-/**
- * struct binder_object - union of flat binder object types
- * @hdr:   generic object header
- * @fbo:   binder object (nodes and refs)
- * @fdo:   file descriptor object
- * @bbo:   binder buffer pointer
- * @fdao:  file descriptor array
- *
- * Used for type-independent object copies
- */
-struct binder_object {
-	union {
-		struct binder_object_header hdr;
-		struct flat_binder_object fbo;
-		struct binder_fd_object fdo;
-		struct binder_buffer_object bbo;
-		struct binder_fd_array_object fdao;
-	};
-};
-
-/**
  * binder_proc_lock() - Acquire outer lock for given binder_proc
  * @proc:         struct binder_proc to acquire
  *
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index ae99109..5b65413 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -11,6 +11,7 @@
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/uidgid.h>
+#include "binder_alloc.h"
 
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
@@ -139,6 +140,409 @@ struct binder_transaction_log {
 	struct binder_transaction_log_entry entry[32];
 };
 
+enum binder_stat_types {
+	BINDER_STAT_PROC,
+	BINDER_STAT_THREAD,
+	BINDER_STAT_NODE,
+	BINDER_STAT_REF,
+	BINDER_STAT_DEATH,
+	BINDER_STAT_TRANSACTION,
+	BINDER_STAT_TRANSACTION_COMPLETE,
+	BINDER_STAT_COUNT
+};
+
+struct binder_stats {
+	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
+	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
+	atomic_t obj_created[BINDER_STAT_COUNT];
+	atomic_t obj_deleted[BINDER_STAT_COUNT];
+};
+
+/**
+ * struct binder_work - work enqueued on a worklist
+ * @entry:             node enqueued on list
+ * @type:              type of work to be performed
+ *
+ * There are separate work lists for proc, thread, and node (async).
+ */
+struct binder_work {
+	struct list_head entry;
+
+	enum {
+		BINDER_WORK_TRANSACTION = 1,
+		BINDER_WORK_TRANSACTION_COMPLETE,
+		BINDER_WORK_RETURN_ERROR,
+		BINDER_WORK_NODE,
+		BINDER_WORK_DEAD_BINDER,
+		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
+		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
+	} type;
+};
+
+struct binder_error {
+	struct binder_work work;
+	uint32_t cmd;
+};
+
+/* struct binder_node - binder node bookkeeping
+ * @debug_id:             unique ID for debugging
+ *                        (invariant after initialized)
+ * @lock:                 lock for node fields
+ * @work:                 worklist element for node work
+ *                        (protected by @proc->inner_lock)
+ * @rb_node:              element for proc->nodes tree
+ *                        (protected by @proc->inner_lock)
+ * @dead_node:            element for binder_dead_nodes list
+ *                        (protected by binder_dead_nodes_lock)
+ * @proc:                 binder_proc that owns this node
+ *                        (invariant after initialized)
+ * @refs:                 list of references on this node
+ *                        (protected by @lock)
+ * @internal_strong_refs: used to take strong references when
+ *                        initiating a transaction
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_weak_refs:      weak user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_strong_refs:    strong user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @tmp_refs:             temporary kernel refs
+ *                        (protected by @proc->inner_lock while @proc
+ *                        is valid, and by binder_dead_nodes_lock
+ *                        if @proc is NULL. During inc/dec and node release
+ *                        it is also protected by @lock to provide safety
+ *                        as the node dies and @proc becomes NULL)
+ * @ptr:                  userspace pointer for node
+ *                        (invariant, no lock needed)
+ * @cookie:               userspace cookie for node
+ *                        (invariant, no lock needed)
+ * @has_strong_ref:       userspace notified of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_strong_ref:   userspace has acked notification of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_weak_ref:         userspace notified of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_weak_ref:     userspace has acked notification of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_async_transaction: async transaction to node in progress
+ *                        (protected by @lock)
+ * @accept_fds:           file descriptor operations supported for node
+ *                        (invariant after initialized)
+ * @min_priority:         minimum scheduling priority
+ *                        (invariant after initialized)
+ * @txn_security_ctx:     require sender's security context
+ *                        (invariant after initialized)
+ * @async_todo:           list of async work items
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder nodes.
+ */
+struct binder_node {
+	int debug_id;
+	spinlock_t lock;
+	struct binder_work work;
+	union {
+		struct rb_node rb_node;
+		struct hlist_node dead_node;
+	};
+	struct binder_proc *proc;
+	struct hlist_head refs;
+	int internal_strong_refs;
+	int local_weak_refs;
+	int local_strong_refs;
+	int tmp_refs;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
+	struct {
+		/*
+		 * bitfield elements protected by
+		 * proc inner_lock
+		 */
+		u8 has_strong_ref:1;
+		u8 pending_strong_ref:1;
+		u8 has_weak_ref:1;
+		u8 pending_weak_ref:1;
+	};
+	struct {
+		/*
+		 * invariant after initialization
+		 */
+		u8 accept_fds:1;
+		u8 txn_security_ctx:1;
+		u8 min_priority;
+	};
+	bool has_async_transaction;
+	struct list_head async_todo;
+};
+
+struct binder_ref_death {
+	/**
+	 * @work: worklist element for death notifications
+	 *        (protected by inner_lock of the proc that
+	 *        this ref belongs to)
+	 */
+	struct binder_work work;
+	binder_uintptr_t cookie;
+};
+
+/**
+ * struct binder_ref_data - binder_ref counts and id
+ * @debug_id:        unique ID for the ref
+ * @desc:            unique userspace handle for ref
+ * @strong:          strong ref count (debugging only if not locked)
+ * @weak:            weak ref count (debugging only if not locked)
+ *
+ * Structure to hold ref count and ref id information. Since
+ * the actual ref can only be accessed with a lock, this structure
+ * is used to return information about the ref to callers of
+ * ref inc/dec functions.
+ */
+struct binder_ref_data {
+	int debug_id;
+	uint32_t desc;
+	int strong;
+	int weak;
+};
+
+/**
+ * struct binder_ref - struct to track references on nodes
+ * @data:        binder_ref_data containing id, handle, and current refcounts
+ * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
+ * @rb_node_node: node for lookup by @node in proc's rb_tree
+ * @node_entry:  list entry for node->refs list in target node
+ *               (protected by @node->lock)
+ * @proc:        binder_proc containing ref
+ * @node:        binder_node of target node. When cleaning up a
+ *               ref for deletion in binder_cleanup_ref, a non-NULL
+ *               @node indicates the node must be freed
+ * @death:       pointer to death notification (ref_death) if requested
+ *               (protected by @node->lock)
+ *
+ * Structure to track references from procA to target node (on procB). This
+ * structure is unsafe to access without holding @proc->outer_lock.
+ */
+struct binder_ref {
+	/* Lookups needed: */
+	/*   node + proc => ref (transaction) */
+	/*   desc + proc => ref (transaction, inc/dec ref) */
+	/*   node => refs + procs (proc exit) */
+	struct binder_ref_data data;
+	struct rb_node rb_node_desc;
+	struct rb_node rb_node_node;
+	struct hlist_node node_entry;
+	struct binder_proc *proc;
+	struct binder_node *node;
+	struct binder_ref_death *death;
+};
+
+/**
+ * struct binder_proc - binder process bookkeeping
+ * @proc_node:            element for binder_procs list
+ * @threads:              rbtree of binder_threads in this proc
+ *                        (protected by @inner_lock)
+ * @nodes:                rbtree of binder nodes associated with
+ *                        this proc ordered by node->ptr
+ *                        (protected by @inner_lock)
+ * @refs_by_desc:         rbtree of refs ordered by ref->desc
+ *                        (protected by @outer_lock)
+ * @refs_by_node:         rbtree of refs ordered by ref->node
+ *                        (protected by @outer_lock)
+ * @waiting_threads:      threads currently waiting for proc work
+ *                        (protected by @inner_lock)
+ * @pid                   PID of group_leader of process
+ *                        (invariant after initialized)
+ * @tsk                   task_struct for group_leader of process
+ *                        (invariant after initialized)
+ * @deferred_work_node:   element for binder_deferred_list
+ *                        (protected by binder_deferred_lock)
+ * @deferred_work:        bitmap of deferred work to perform
+ *                        (protected by binder_deferred_lock)
+ * @is_dead:              process is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @inner_lock)
+ * @todo:                 list of work for this process
+ *                        (protected by @inner_lock)
+ * @stats:                per-process binder statistics
+ *                        (atomics, no lock needed)
+ * @delivered_death:      list of delivered death notification
+ *                        (protected by @inner_lock)
+ * @max_threads:          cap on number of binder threads
+ *                        (protected by @inner_lock)
+ * @requested_threads:    number of binder threads requested but not
+ *                        yet started. In current implementation, can
+ *                        only be 0 or 1.
+ *                        (protected by @inner_lock)
+ * @requested_threads_started: number binder threads started
+ *                        (protected by @inner_lock)
+ * @tmp_ref:              temporary reference to indicate proc is in use
+ *                        (protected by @inner_lock)
+ * @default_priority:     default scheduler priority
+ *                        (invariant after initialized)
+ * @debugfs_entry:        debugfs node
+ * @alloc:                binder allocator bookkeeping
+ * @context:              binder_context for this proc
+ *                        (invariant after initialized)
+ * @inner_lock:           can nest under outer_lock and/or node lock
+ * @outer_lock:           no nesting under innor or node lock
+ *                        Lock order: 1) outer, 2) node, 3) inner
+ * @binderfs_entry:       process-specific binderfs log file
+ *
+ * Bookkeeping structure for binder processes
+ */
+struct binder_proc {
+	struct hlist_node proc_node;
+	struct rb_root threads;
+	struct rb_root nodes;
+	struct rb_root refs_by_desc;
+	struct rb_root refs_by_node;
+	struct list_head waiting_threads;
+	int pid;
+	struct task_struct *tsk;
+	struct hlist_node deferred_work_node;
+	int deferred_work;
+	bool is_dead;
+
+	struct list_head todo;
+	struct binder_stats stats;
+	struct list_head delivered_death;
+	int max_threads;
+	int requested_threads;
+	int requested_threads_started;
+	int tmp_ref;
+	long default_priority;
+	struct dentry *debugfs_entry;
+	struct binder_alloc alloc;
+	struct binder_context *context;
+	spinlock_t inner_lock;
+	spinlock_t outer_lock;
+	struct dentry *binderfs_entry;
+};
+
+/**
+ * struct binder_thread - binder thread bookkeeping
+ * @proc:                 binder process for this thread
+ *                        (invariant after initialization)
+ * @rb_node:              element for proc->threads rbtree
+ *                        (protected by @proc->inner_lock)
+ * @waiting_thread_node:  element for @proc->waiting_threads list
+ *                        (protected by @proc->inner_lock)
+ * @pid:                  PID for this thread
+ *                        (invariant after initialization)
+ * @looper:               bitmap of looping state
+ *                        (only accessed by this thread)
+ * @looper_needs_return:  looping thread needs to exit driver
+ *                        (no lock needed)
+ * @transaction_stack:    stack of in-progress transactions for this thread
+ *                        (protected by @proc->inner_lock)
+ * @todo:                 list of work to do for this thread
+ *                        (protected by @proc->inner_lock)
+ * @process_todo:         whether work in @todo should be processed
+ *                        (protected by @proc->inner_lock)
+ * @return_error:         transaction errors reported by this thread
+ *                        (only accessed by this thread)
+ * @reply_error:          transaction errors reported by target thread
+ *                        (protected by @proc->inner_lock)
+ * @wait:                 wait queue for thread work
+ * @stats:                per-thread statistics
+ *                        (atomics, no lock needed)
+ * @tmp_ref:              temporary reference to indicate thread is in use
+ *                        (atomic since @proc->inner_lock cannot
+ *                        always be acquired)
+ * @is_dead:              thread is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder threads.
+ */
+struct binder_thread {
+	struct binder_proc *proc;
+	struct rb_node rb_node;
+	struct list_head waiting_thread_node;
+	int pid;
+	int looper;              /* only modified by this thread */
+	bool looper_need_return; /* can be written by other thread */
+	struct binder_transaction *transaction_stack;
+	struct list_head todo;
+	bool process_todo;
+	struct binder_error return_error;
+	struct binder_error reply_error;
+	wait_queue_head_t wait;
+	struct binder_stats stats;
+	atomic_t tmp_ref;
+	bool is_dead;
+};
+
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry:          list entry
+ * @file:                 struct file to be associated with new fd
+ * @offset:               offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+	struct list_head fixup_entry;
+	struct file *file;
+	size_t offset;
+};
+
+struct binder_transaction {
+	int debug_id;
+	struct binder_work work;
+	struct binder_thread *from;
+	struct binder_transaction *from_parent;
+	struct binder_proc *to_proc;
+	struct binder_thread *to_thread;
+	struct binder_transaction *to_parent;
+	unsigned need_reply:1;
+	/* unsigned is_dead:1; */       /* not used at the moment */
+
+	struct binder_buffer *buffer;
+	unsigned int    code;
+	unsigned int    flags;
+	long    priority;
+	long    saved_priority;
+	kuid_t  sender_euid;
+	struct list_head fd_fixups;
+	binder_uintptr_t security_ctx;
+	/**
+	 * @lock:  protects @from, @to_proc, and @to_thread
+	 *
+	 * @from, @to_proc, and @to_thread can be set to NULL
+	 * during thread teardown
+	 */
+	spinlock_t lock;
+};
+
+/**
+ * struct binder_object - union of flat binder object types
+ * @hdr:   generic object header
+ * @fbo:   binder object (nodes and refs)
+ * @fdo:   file descriptor object
+ * @bbo:   binder buffer pointer
+ * @fdao:  file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+	union {
+		struct binder_object_header hdr;
+		struct flat_binder_object fbo;
+		struct binder_fd_object fdo;
+		struct binder_buffer_object bbo;
+		struct binder_fd_array_object fdao;
+	};
+};
+
 extern struct binder_transaction_log binder_transaction_log;
 extern struct binder_transaction_log binder_transaction_log_failed;
 #endif /* _LINUX_BINDER_INTERNAL_H */
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v7 2/3] binder: add trace at free transaction.
  2020-08-04 13:59                                                 ` [PATCH v7] binder: transaction latency tracking for user build Frankie Chang
  2020-08-04 13:59                                                   ` [PATCH v7 1/3] binder: move structs from core file to header file Frankie Chang
@ 2020-08-04 13:59                                                   ` Frankie Chang
  2020-08-04 15:26                                                     ` Todd Kjos
  2020-08-04 13:59                                                   ` [PATCH v7 3/3] binder: add transaction latency tracer Frankie Chang
  2020-09-03 16:21                                                   ` [PATCH v7] binder: transaction latency tracking for user build Greg Kroah-Hartman
  3 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-08-04 13:59 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min Liu, linux-mediatek,
	Joel Fernandes, Frankie Chang, Martijn Coenen, Christian Brauner

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Since the original trace_binder_transaction_received cannot
precisely present the real finished time of transaction, adding a
trace_binder_txn_latency_free at the point of free transaction
may be more close to it.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/binder.c       |   18 ++++++++++++++++++
 drivers/android/binder_trace.h |   29 +++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 2df146f..1bfadc2 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1508,6 +1508,20 @@ static void binder_free_txn_fixups(struct binder_transaction *t)
 	}
 }
 
+static void binder_txn_latency_free(struct binder_transaction *t)
+{
+	int from_proc, from_thread, to_proc, to_thread;
+
+	spin_lock(&t->lock);
+	from_proc = t->from ? t->from->proc->pid : 0;
+	from_thread = t->from ? t->from->pid : 0;
+	to_proc = t->to_proc ? t->to_proc->pid : 0;
+	to_thread = t->to_thread ? t->to_thread->pid : 0;
+	spin_unlock(&t->lock);
+
+	trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc, to_thread);
+}
+
 static void binder_free_transaction(struct binder_transaction *t)
 {
 	struct binder_proc *target_proc = t->to_proc;
@@ -1518,6 +1532,8 @@ static void binder_free_transaction(struct binder_transaction *t)
 			t->buffer->transaction = NULL;
 		binder_inner_proc_unlock(target_proc);
 	}
+	if (trace_binder_txn_latency_free_enabled())
+		binder_txn_latency_free(t);
 	/*
 	 * If the transaction has no target_proc, then
 	 * t->buffer->transaction has already been cleared.
@@ -3093,6 +3109,8 @@ static void binder_transaction(struct binder_proc *proc,
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 err_alloc_tcomplete_failed:
+	if (trace_binder_txn_latency_free_enabled())
+		binder_txn_latency_free(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
 err_alloc_t_failed:
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 6731c3c..eb2c53c 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,35 @@
 		  __entry->thread_todo)
 );
 
+TRACE_EVENT(binder_txn_latency_free,
+	TP_PROTO(struct binder_transaction *t
+		 int from_proc, int from_thread
+		 int to_proc, int to_thread),
+	TP_ARGS(t, from_proc, from_thread, to_proc, to_thread),
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, from_proc)
+		__field(int, from_thread)
+		__field(int, to_proc)
+		__field(int, to_thread)
+		__field(unsigned int, code)
+		__field(unsigned int, flags)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->from_proc = from_proc;
+		__entry->from_thread = from_thread;
+		__entry->to_proc = to_proc;
+		__entry->to_thread = to_thread;
+		__entry->code = t->code;
+		__entry->flags = t->flags;
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
+		  __entry->to_proc, __entry->to_thread, __entry->code,
+		  __entry->flags)
+);
+
 TRACE_EVENT(binder_transaction,
 	TP_PROTO(bool reply, struct binder_transaction *t,
 		 struct binder_node *target_node),
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v7 3/3] binder: add transaction latency tracer
  2020-08-04 13:59                                                 ` [PATCH v7] binder: transaction latency tracking for user build Frankie Chang
  2020-08-04 13:59                                                   ` [PATCH v7 1/3] binder: move structs from core file to header file Frankie Chang
  2020-08-04 13:59                                                   ` [PATCH v7 2/3] binder: add trace at free transaction Frankie Chang
@ 2020-08-04 13:59                                                   ` Frankie Chang
  2020-08-04 15:28                                                     ` Todd Kjos
  2020-09-07 14:41                                                     ` peter enderborg
  2020-09-03 16:21                                                   ` [PATCH v7] binder: transaction latency tracking for user build Greg Kroah-Hartman
  3 siblings, 2 replies; 72+ messages in thread
From: Frankie Chang @ 2020-08-04 13:59 UTC (permalink / raw)
  To: Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min Liu, linux-mediatek,
	Joel Fernandes, Frankie Chang, Martijn Coenen, Christian Brauner

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Record start/end timestamp for binder transaction.
When transaction is completed or transaction is free,
it would be checked if transaction latency over threshold
(default 2 sec), if yes, printing related information for tracing.

/* Implement details */
- Add latency tracer module to monitor transaction
  by attaching to new tracepoints introduced
  when transactions are allocated and freed.
  The trace_binder_txn_latency_free would not be enabled
  by default. Monitoring which transaction is too slow to
  cause some of exceptions is important. So we hook the
  tracepoint to call the monitor function.

- Since some of modules would trigger timeout NE
  if their binder transaction don't finish in time,
  such as audio timeout (5 sec), even BT command
  timeout (2 sec), etc.
  Therefore, setting the timeout threshold as default
  2 seconds could be helpful to debug.
  But this timeout threshold is configurable, to let
  all users determine the more suitable threshold.

- The reason why printing the related information to
  kernel information log but not trace buffer is that
  some abnormal transactions may be pending for a long
  time ago, they could not be recorded due to buffer
  limited.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
---
 drivers/android/Kconfig                 |    8 +++
 drivers/android/Makefile                |    1 +
 drivers/android/binder.c                |    2 +
 drivers/android/binder_internal.h       |   13 ++++
 drivers/android/binder_latency_tracer.c |  112 +++++++++++++++++++++++++++++++
 drivers/android/binder_trace.h          |   26 ++++++-
 6 files changed, 159 insertions(+), 3 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 6fdf2ab..91fff1e 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
 	  exhaustively with combinations of various buffer sizes and
 	  alignments.
 
+config BINDER_TRANSACTION_LATENCY_TRACKING
+	tristate "Android Binder transaction tracking"
+	help
+	  Used for track abnormal binder transaction which is over threshold,
+	  when the transaction is done or be free, this transaction would be
+	  checked whether it executed overtime.
+	  If yes, printing out the detailed info.
+
 endif # if ANDROID
 
 endmenu
diff --git a/drivers/android/Makefile b/drivers/android/Makefile
index c9d3d0c9..c2ffdb6 100644
--- a/drivers/android/Makefile
+++ b/drivers/android/Makefile
@@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
 obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
 obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
 obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
+obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)	+= binder_latency_tracer.o
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 1bfadc2..22f7cc6 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2671,6 +2671,7 @@ static void binder_transaction(struct binder_proc *proc,
 		return_error_line = __LINE__;
 		goto err_alloc_t_failed;
 	}
+	trace_binder_txn_latency_alloc(t);
 	INIT_LIST_HEAD(&t->fd_fixups);
 	binder_stats_created(BINDER_STAT_TRANSACTION);
 	spin_lock_init(&t->lock);
@@ -5159,6 +5160,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
 		   to_proc ? to_proc->pid : 0,
 		   t->to_thread ? t->to_thread->pid : 0,
 		   t->code, t->flags, t->priority, t->need_reply);
+	trace_binder_txn_latency_info(m, t);
 	spin_unlock(&t->lock);
 
 	if (proc != to_proc) {
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index 5b65413..596db00 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -13,6 +13,11 @@
 #include <linux/uidgid.h>
 #include "binder_alloc.h"
 
+#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
+#include <linux/rtc.h>
+#include <linux/time.h>
+#endif
+
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
 	struct mutex context_mgr_node_lock;
@@ -521,6 +526,14 @@ struct binder_transaction {
 	 * during thread teardown
 	 */
 	spinlock_t lock;
+	/**
+	 * @timestamp and @tv are used to record the time
+	 * that the binder transaction startup
+	 */
+#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
+	struct timespec64 timestamp;
+	struct timeval tv;
+#endif
 };
 
 /**
diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
new file mode 100644
index 0000000..61ae75f
--- /dev/null
+++ b/drivers/android/binder_latency_tracer.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ */
+
+#include <linux/module.h>
+#include <uapi/linux/android/binder.h>
+#include "binder_internal.h"
+#include "binder_trace.h"
+
+/**
+ * The reason setting the binder_txn_latency_threshold to 2 sec
+ * is that most of timeout abort is greater or equal to 2 sec.
+ * Making it configurable to let all users determine which
+ * threshold is more suitable.
+ */
+static uint32_t binder_txn_latency_threshold = 2;
+module_param_named(threshold, binder_txn_latency_threshold,
+			uint, 0644);
+
+/*
+ * probe_binder_txn_latency_free - Output info of a delay transaction
+ * @t:          pointer to the over-time transaction
+ */
+void probe_binder_txn_latency_free(void *ignore, struct binder_transaction *t,
+					int from_proc, int from_thread,
+					int to_proc, int to_thread)
+{
+	struct rtc_time tm;
+	struct timespec64 *startime;
+	struct timespec64 cur, sub_t;
+
+	ktime_get_ts64(&cur);
+	startime = &t->timestamp;
+	sub_t = timespec64_sub(cur, *startime);
+
+	/* if transaction time is over than binder_txn_latency_threshold (sec),
+	 * show timeout warning log.
+	 */
+	if (sub_t.tv_sec < binder_txn_latency_threshold)
+		return;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+
+	pr_info_ratelimited("%d: from %d:%d to %d:%d",
+			t->debug_id, from_proc, from_thread,
+			to_proc, to_thread);
+
+	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
+			(unsigned int)sub_t.tv_sec,
+			(sub_t.tv_nsec / NSEC_PER_MSEC),
+			t->code,
+			(unsigned long)startime->tv_sec,
+			(startime->tv_nsec / NSEC_PER_MSEC),
+			(tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+			tm.tm_hour, tm.tm_min, tm.tm_sec,
+			(unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+
+static void probe_binder_txn_latency_alloc(void *ignore,
+					struct binder_transaction *t)
+{
+	struct timespec64 now;
+
+	ktime_get_ts64(&t->timestamp);
+	ktime_get_real_ts64(&now);
+	t->tv.tv_sec = now.tv_sec;
+	t->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
+	t->tv.tv_usec = now.tv_nsec/1000;
+}
+
+static void probe_binder_txn_latency_info(void *ignore, struct seq_file *m,
+					struct binder_transaction *t)
+{
+	struct rtc_time tm;
+
+	rtc_time_to_tm(t->tv.tv_sec, &tm);
+	seq_printf(m,
+		   " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
+		   (unsigned long)t->timestamp.tv_sec,
+		   (t->timestamp.tv_nsec / NSEC_PER_USEC),
+		   (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+		   tm.tm_hour, tm.tm_min, tm.tm_sec,
+		   (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+
+static int __init init_binder_latency_tracer(void)
+{
+	register_trace_binder_txn_latency_free(
+			probe_binder_txn_latency_free, NULL);
+	register_trace_binder_txn_latency_alloc(
+			probe_binder_txn_latency_alloc, NULL);
+	register_trace_binder_txn_latency_info(
+			probe_binder_txn_latency_info, NULL);
+
+	return 0;
+}
+
+static void exit_binder_latency_tracer(void)
+{
+	unregister_trace_binder_txn_latency_free(
+			probe_binder_txn_latency_free, NULL);
+	unregister_trace_binder_txn_latency_alloc(
+			probe_binder_txn_latency_alloc, NULL);
+	unregister_trace_binder_txn_latency_info(
+			probe_binder_txn_latency_info, NULL);
+}
+
+module_init(init_binder_latency_tracer);
+module_exit(exit_binder_latency_tracer);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index eb2c53c..be4fe4c 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,17 @@
 		  __entry->thread_todo)
 );
 
+DECLARE_TRACE(binder_txn_latency_alloc,
+	TP_PROTO(struct binder_transaction *t),
+	TP_ARGS(t, e)
+);
+
+DECLARE_TRACE(binder_txn_latency_info,
+	TP_PROTO(struct seq_file *m,
+		 struct binder_transaction *t),
+	TP_ARGS(m, t)
+);
+
 TRACE_EVENT(binder_txn_latency_free,
 	TP_PROTO(struct binder_transaction *t
 		 int from_proc, int from_thread
@@ -108,6 +119,8 @@
 		__field(int, to_thread)
 		__field(unsigned int, code)
 		__field(unsigned int, flags)
+		__field(unsigned long, start_sec)
+		__field(unsigned long, start_nsec)
 	),
 	TP_fast_assign(
 		__entry->debug_id = t->debug_id;
@@ -117,11 +130,18 @@
 		__entry->to_thread = to_thread;
 		__entry->code = t->code;
 		__entry->flags = t->flags;
-	),
-	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
+		__entry->start_sec = t->timestamp.tv_sec;
+		__entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
+#else
+		__entry->start_sec = 0;
+		__entry->start_nsec = 0;
+#endif
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
 		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
 		  __entry->to_proc, __entry->to_thread, __entry->code,
-		  __entry->flags)
+		  __entry->flags, __entry->start_sec, __entry->start_nsec)
 );
 
 TRACE_EVENT(binder_transaction,
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v7 1/3] binder: move structs from core file to header file
  2020-08-04 13:59                                                   ` [PATCH v7 1/3] binder: move structs from core file to header file Frankie Chang
@ 2020-08-04 15:24                                                     ` Todd Kjos
  0 siblings, 0 replies; 72+ messages in thread
From: Todd Kjos @ 2020-08-04 15:24 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Tue, Aug 4, 2020 at 6:59 AM Frankie Chang <Frankie.Chang@mediatek.com> wrote:
>
> From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
>
> Moving all structs to header file makes module more
> extendable, and makes all these structs to be defined
> in the same file.
>
> Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>

Acked-by: Todd Kjos <tkjos@google.com>

> ---
>  drivers/android/binder.c          |  405 -------------------------------------
>  drivers/android/binder_internal.h |  404 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 404 insertions(+), 405 deletions(-)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index a6b2082..2df146f 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -72,7 +72,6 @@
>
>  #include <asm/cacheflush.h>
>
> -#include "binder_alloc.h"
>  #include "binder_internal.h"
>  #include "binder_trace.h"
>
> @@ -160,24 +159,6 @@ static int binder_set_stop_on_user_error(const char *val,
>  #define to_binder_fd_array_object(hdr) \
>         container_of(hdr, struct binder_fd_array_object, hdr)
>
> -enum binder_stat_types {
> -       BINDER_STAT_PROC,
> -       BINDER_STAT_THREAD,
> -       BINDER_STAT_NODE,
> -       BINDER_STAT_REF,
> -       BINDER_STAT_DEATH,
> -       BINDER_STAT_TRANSACTION,
> -       BINDER_STAT_TRANSACTION_COMPLETE,
> -       BINDER_STAT_COUNT
> -};
> -
> -struct binder_stats {
> -       atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
> -       atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
> -       atomic_t obj_created[BINDER_STAT_COUNT];
> -       atomic_t obj_deleted[BINDER_STAT_COUNT];
> -};
> -
>  static struct binder_stats binder_stats;
>
>  static inline void binder_stats_deleted(enum binder_stat_types type)
> @@ -213,278 +194,11 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
>         return e;
>  }
>
> -/**
> - * struct binder_work - work enqueued on a worklist
> - * @entry:             node enqueued on list
> - * @type:              type of work to be performed
> - *
> - * There are separate work lists for proc, thread, and node (async).
> - */
> -struct binder_work {
> -       struct list_head entry;
> -
> -       enum {
> -               BINDER_WORK_TRANSACTION = 1,
> -               BINDER_WORK_TRANSACTION_COMPLETE,
> -               BINDER_WORK_RETURN_ERROR,
> -               BINDER_WORK_NODE,
> -               BINDER_WORK_DEAD_BINDER,
> -               BINDER_WORK_DEAD_BINDER_AND_CLEAR,
> -               BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
> -       } type;
> -};
> -
> -struct binder_error {
> -       struct binder_work work;
> -       uint32_t cmd;
> -};
> -
> -/**
> - * struct binder_node - binder node bookkeeping
> - * @debug_id:             unique ID for debugging
> - *                        (invariant after initialized)
> - * @lock:                 lock for node fields
> - * @work:                 worklist element for node work
> - *                        (protected by @proc->inner_lock)
> - * @rb_node:              element for proc->nodes tree
> - *                        (protected by @proc->inner_lock)
> - * @dead_node:            element for binder_dead_nodes list
> - *                        (protected by binder_dead_nodes_lock)
> - * @proc:                 binder_proc that owns this node
> - *                        (invariant after initialized)
> - * @refs:                 list of references on this node
> - *                        (protected by @lock)
> - * @internal_strong_refs: used to take strong references when
> - *                        initiating a transaction
> - *                        (protected by @proc->inner_lock if @proc
> - *                        and by @lock)
> - * @local_weak_refs:      weak user refs from local process
> - *                        (protected by @proc->inner_lock if @proc
> - *                        and by @lock)
> - * @local_strong_refs:    strong user refs from local process
> - *                        (protected by @proc->inner_lock if @proc
> - *                        and by @lock)
> - * @tmp_refs:             temporary kernel refs
> - *                        (protected by @proc->inner_lock while @proc
> - *                        is valid, and by binder_dead_nodes_lock
> - *                        if @proc is NULL. During inc/dec and node release
> - *                        it is also protected by @lock to provide safety
> - *                        as the node dies and @proc becomes NULL)
> - * @ptr:                  userspace pointer for node
> - *                        (invariant, no lock needed)
> - * @cookie:               userspace cookie for node
> - *                        (invariant, no lock needed)
> - * @has_strong_ref:       userspace notified of strong ref
> - *                        (protected by @proc->inner_lock if @proc
> - *                        and by @lock)
> - * @pending_strong_ref:   userspace has acked notification of strong ref
> - *                        (protected by @proc->inner_lock if @proc
> - *                        and by @lock)
> - * @has_weak_ref:         userspace notified of weak ref
> - *                        (protected by @proc->inner_lock if @proc
> - *                        and by @lock)
> - * @pending_weak_ref:     userspace has acked notification of weak ref
> - *                        (protected by @proc->inner_lock if @proc
> - *                        and by @lock)
> - * @has_async_transaction: async transaction to node in progress
> - *                        (protected by @lock)
> - * @accept_fds:           file descriptor operations supported for node
> - *                        (invariant after initialized)
> - * @min_priority:         minimum scheduling priority
> - *                        (invariant after initialized)
> - * @txn_security_ctx:     require sender's security context
> - *                        (invariant after initialized)
> - * @async_todo:           list of async work items
> - *                        (protected by @proc->inner_lock)
> - *
> - * Bookkeeping structure for binder nodes.
> - */
> -struct binder_node {
> -       int debug_id;
> -       spinlock_t lock;
> -       struct binder_work work;
> -       union {
> -               struct rb_node rb_node;
> -               struct hlist_node dead_node;
> -       };
> -       struct binder_proc *proc;
> -       struct hlist_head refs;
> -       int internal_strong_refs;
> -       int local_weak_refs;
> -       int local_strong_refs;
> -       int tmp_refs;
> -       binder_uintptr_t ptr;
> -       binder_uintptr_t cookie;
> -       struct {
> -               /*
> -                * bitfield elements protected by
> -                * proc inner_lock
> -                */
> -               u8 has_strong_ref:1;
> -               u8 pending_strong_ref:1;
> -               u8 has_weak_ref:1;
> -               u8 pending_weak_ref:1;
> -       };
> -       struct {
> -               /*
> -                * invariant after initialization
> -                */
> -               u8 accept_fds:1;
> -               u8 txn_security_ctx:1;
> -               u8 min_priority;
> -       };
> -       bool has_async_transaction;
> -       struct list_head async_todo;
> -};
> -
> -struct binder_ref_death {
> -       /**
> -        * @work: worklist element for death notifications
> -        *        (protected by inner_lock of the proc that
> -        *        this ref belongs to)
> -        */
> -       struct binder_work work;
> -       binder_uintptr_t cookie;
> -};
> -
> -/**
> - * struct binder_ref_data - binder_ref counts and id
> - * @debug_id:        unique ID for the ref
> - * @desc:            unique userspace handle for ref
> - * @strong:          strong ref count (debugging only if not locked)
> - * @weak:            weak ref count (debugging only if not locked)
> - *
> - * Structure to hold ref count and ref id information. Since
> - * the actual ref can only be accessed with a lock, this structure
> - * is used to return information about the ref to callers of
> - * ref inc/dec functions.
> - */
> -struct binder_ref_data {
> -       int debug_id;
> -       uint32_t desc;
> -       int strong;
> -       int weak;
> -};
> -
> -/**
> - * struct binder_ref - struct to track references on nodes
> - * @data:        binder_ref_data containing id, handle, and current refcounts
> - * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
> - * @rb_node_node: node for lookup by @node in proc's rb_tree
> - * @node_entry:  list entry for node->refs list in target node
> - *               (protected by @node->lock)
> - * @proc:        binder_proc containing ref
> - * @node:        binder_node of target node. When cleaning up a
> - *               ref for deletion in binder_cleanup_ref, a non-NULL
> - *               @node indicates the node must be freed
> - * @death:       pointer to death notification (ref_death) if requested
> - *               (protected by @node->lock)
> - *
> - * Structure to track references from procA to target node (on procB). This
> - * structure is unsafe to access without holding @proc->outer_lock.
> - */
> -struct binder_ref {
> -       /* Lookups needed: */
> -       /*   node + proc => ref (transaction) */
> -       /*   desc + proc => ref (transaction, inc/dec ref) */
> -       /*   node => refs + procs (proc exit) */
> -       struct binder_ref_data data;
> -       struct rb_node rb_node_desc;
> -       struct rb_node rb_node_node;
> -       struct hlist_node node_entry;
> -       struct binder_proc *proc;
> -       struct binder_node *node;
> -       struct binder_ref_death *death;
> -};
> -
>  enum binder_deferred_state {
>         BINDER_DEFERRED_FLUSH        = 0x01,
>         BINDER_DEFERRED_RELEASE      = 0x02,
>  };
>
> -/**
> - * struct binder_proc - binder process bookkeeping
> - * @proc_node:            element for binder_procs list
> - * @threads:              rbtree of binder_threads in this proc
> - *                        (protected by @inner_lock)
> - * @nodes:                rbtree of binder nodes associated with
> - *                        this proc ordered by node->ptr
> - *                        (protected by @inner_lock)
> - * @refs_by_desc:         rbtree of refs ordered by ref->desc
> - *                        (protected by @outer_lock)
> - * @refs_by_node:         rbtree of refs ordered by ref->node
> - *                        (protected by @outer_lock)
> - * @waiting_threads:      threads currently waiting for proc work
> - *                        (protected by @inner_lock)
> - * @pid                   PID of group_leader of process
> - *                        (invariant after initialized)
> - * @tsk                   task_struct for group_leader of process
> - *                        (invariant after initialized)
> - * @deferred_work_node:   element for binder_deferred_list
> - *                        (protected by binder_deferred_lock)
> - * @deferred_work:        bitmap of deferred work to perform
> - *                        (protected by binder_deferred_lock)
> - * @is_dead:              process is dead and awaiting free
> - *                        when outstanding transactions are cleaned up
> - *                        (protected by @inner_lock)
> - * @todo:                 list of work for this process
> - *                        (protected by @inner_lock)
> - * @stats:                per-process binder statistics
> - *                        (atomics, no lock needed)
> - * @delivered_death:      list of delivered death notification
> - *                        (protected by @inner_lock)
> - * @max_threads:          cap on number of binder threads
> - *                        (protected by @inner_lock)
> - * @requested_threads:    number of binder threads requested but not
> - *                        yet started. In current implementation, can
> - *                        only be 0 or 1.
> - *                        (protected by @inner_lock)
> - * @requested_threads_started: number binder threads started
> - *                        (protected by @inner_lock)
> - * @tmp_ref:              temporary reference to indicate proc is in use
> - *                        (protected by @inner_lock)
> - * @default_priority:     default scheduler priority
> - *                        (invariant after initialized)
> - * @debugfs_entry:        debugfs node
> - * @alloc:                binder allocator bookkeeping
> - * @context:              binder_context for this proc
> - *                        (invariant after initialized)
> - * @inner_lock:           can nest under outer_lock and/or node lock
> - * @outer_lock:           no nesting under innor or node lock
> - *                        Lock order: 1) outer, 2) node, 3) inner
> - * @binderfs_entry:       process-specific binderfs log file
> - *
> - * Bookkeeping structure for binder processes
> - */
> -struct binder_proc {
> -       struct hlist_node proc_node;
> -       struct rb_root threads;
> -       struct rb_root nodes;
> -       struct rb_root refs_by_desc;
> -       struct rb_root refs_by_node;
> -       struct list_head waiting_threads;
> -       int pid;
> -       struct task_struct *tsk;
> -       struct hlist_node deferred_work_node;
> -       int deferred_work;
> -       bool is_dead;
> -
> -       struct list_head todo;
> -       struct binder_stats stats;
> -       struct list_head delivered_death;
> -       int max_threads;
> -       int requested_threads;
> -       int requested_threads_started;
> -       int tmp_ref;
> -       long default_priority;
> -       struct dentry *debugfs_entry;
> -       struct binder_alloc alloc;
> -       struct binder_context *context;
> -       spinlock_t inner_lock;
> -       spinlock_t outer_lock;
> -       struct dentry *binderfs_entry;
> -};
> -
>  enum {
>         BINDER_LOOPER_STATE_REGISTERED  = 0x01,
>         BINDER_LOOPER_STATE_ENTERED     = 0x02,
> @@ -495,125 +209,6 @@ enum {
>  };
>
>  /**
> - * struct binder_thread - binder thread bookkeeping
> - * @proc:                 binder process for this thread
> - *                        (invariant after initialization)
> - * @rb_node:              element for proc->threads rbtree
> - *                        (protected by @proc->inner_lock)
> - * @waiting_thread_node:  element for @proc->waiting_threads list
> - *                        (protected by @proc->inner_lock)
> - * @pid:                  PID for this thread
> - *                        (invariant after initialization)
> - * @looper:               bitmap of looping state
> - *                        (only accessed by this thread)
> - * @looper_needs_return:  looping thread needs to exit driver
> - *                        (no lock needed)
> - * @transaction_stack:    stack of in-progress transactions for this thread
> - *                        (protected by @proc->inner_lock)
> - * @todo:                 list of work to do for this thread
> - *                        (protected by @proc->inner_lock)
> - * @process_todo:         whether work in @todo should be processed
> - *                        (protected by @proc->inner_lock)
> - * @return_error:         transaction errors reported by this thread
> - *                        (only accessed by this thread)
> - * @reply_error:          transaction errors reported by target thread
> - *                        (protected by @proc->inner_lock)
> - * @wait:                 wait queue for thread work
> - * @stats:                per-thread statistics
> - *                        (atomics, no lock needed)
> - * @tmp_ref:              temporary reference to indicate thread is in use
> - *                        (atomic since @proc->inner_lock cannot
> - *                        always be acquired)
> - * @is_dead:              thread is dead and awaiting free
> - *                        when outstanding transactions are cleaned up
> - *                        (protected by @proc->inner_lock)
> - *
> - * Bookkeeping structure for binder threads.
> - */
> -struct binder_thread {
> -       struct binder_proc *proc;
> -       struct rb_node rb_node;
> -       struct list_head waiting_thread_node;
> -       int pid;
> -       int looper;              /* only modified by this thread */
> -       bool looper_need_return; /* can be written by other thread */
> -       struct binder_transaction *transaction_stack;
> -       struct list_head todo;
> -       bool process_todo;
> -       struct binder_error return_error;
> -       struct binder_error reply_error;
> -       wait_queue_head_t wait;
> -       struct binder_stats stats;
> -       atomic_t tmp_ref;
> -       bool is_dead;
> -};
> -
> -/**
> - * struct binder_txn_fd_fixup - transaction fd fixup list element
> - * @fixup_entry:          list entry
> - * @file:                 struct file to be associated with new fd
> - * @offset:               offset in buffer data to this fixup
> - *
> - * List element for fd fixups in a transaction. Since file
> - * descriptors need to be allocated in the context of the
> - * target process, we pass each fd to be processed in this
> - * struct.
> - */
> -struct binder_txn_fd_fixup {
> -       struct list_head fixup_entry;
> -       struct file *file;
> -       size_t offset;
> -};
> -
> -struct binder_transaction {
> -       int debug_id;
> -       struct binder_work work;
> -       struct binder_thread *from;
> -       struct binder_transaction *from_parent;
> -       struct binder_proc *to_proc;
> -       struct binder_thread *to_thread;
> -       struct binder_transaction *to_parent;
> -       unsigned need_reply:1;
> -       /* unsigned is_dead:1; */       /* not used at the moment */
> -
> -       struct binder_buffer *buffer;
> -       unsigned int    code;
> -       unsigned int    flags;
> -       long    priority;
> -       long    saved_priority;
> -       kuid_t  sender_euid;
> -       struct list_head fd_fixups;
> -       binder_uintptr_t security_ctx;
> -       /**
> -        * @lock:  protects @from, @to_proc, and @to_thread
> -        *
> -        * @from, @to_proc, and @to_thread can be set to NULL
> -        * during thread teardown
> -        */
> -       spinlock_t lock;
> -};
> -
> -/**
> - * struct binder_object - union of flat binder object types
> - * @hdr:   generic object header
> - * @fbo:   binder object (nodes and refs)
> - * @fdo:   file descriptor object
> - * @bbo:   binder buffer pointer
> - * @fdao:  file descriptor array
> - *
> - * Used for type-independent object copies
> - */
> -struct binder_object {
> -       union {
> -               struct binder_object_header hdr;
> -               struct flat_binder_object fbo;
> -               struct binder_fd_object fdo;
> -               struct binder_buffer_object bbo;
> -               struct binder_fd_array_object fdao;
> -       };
> -};
> -
> -/**
>   * binder_proc_lock() - Acquire outer lock for given binder_proc
>   * @proc:         struct binder_proc to acquire
>   *
> diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> index ae99109..5b65413 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -11,6 +11,7 @@
>  #include <linux/stddef.h>
>  #include <linux/types.h>
>  #include <linux/uidgid.h>
> +#include "binder_alloc.h"
>
>  struct binder_context {
>         struct binder_node *binder_context_mgr_node;
> @@ -139,6 +140,409 @@ struct binder_transaction_log {
>         struct binder_transaction_log_entry entry[32];
>  };
>
> +enum binder_stat_types {
> +       BINDER_STAT_PROC,
> +       BINDER_STAT_THREAD,
> +       BINDER_STAT_NODE,
> +       BINDER_STAT_REF,
> +       BINDER_STAT_DEATH,
> +       BINDER_STAT_TRANSACTION,
> +       BINDER_STAT_TRANSACTION_COMPLETE,
> +       BINDER_STAT_COUNT
> +};
> +
> +struct binder_stats {
> +       atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
> +       atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
> +       atomic_t obj_created[BINDER_STAT_COUNT];
> +       atomic_t obj_deleted[BINDER_STAT_COUNT];
> +};
> +
> +/**
> + * struct binder_work - work enqueued on a worklist
> + * @entry:             node enqueued on list
> + * @type:              type of work to be performed
> + *
> + * There are separate work lists for proc, thread, and node (async).
> + */
> +struct binder_work {
> +       struct list_head entry;
> +
> +       enum {
> +               BINDER_WORK_TRANSACTION = 1,
> +               BINDER_WORK_TRANSACTION_COMPLETE,
> +               BINDER_WORK_RETURN_ERROR,
> +               BINDER_WORK_NODE,
> +               BINDER_WORK_DEAD_BINDER,
> +               BINDER_WORK_DEAD_BINDER_AND_CLEAR,
> +               BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
> +       } type;
> +};
> +
> +struct binder_error {
> +       struct binder_work work;
> +       uint32_t cmd;
> +};
> +
> +/* struct binder_node - binder node bookkeeping
> + * @debug_id:             unique ID for debugging
> + *                        (invariant after initialized)
> + * @lock:                 lock for node fields
> + * @work:                 worklist element for node work
> + *                        (protected by @proc->inner_lock)
> + * @rb_node:              element for proc->nodes tree
> + *                        (protected by @proc->inner_lock)
> + * @dead_node:            element for binder_dead_nodes list
> + *                        (protected by binder_dead_nodes_lock)
> + * @proc:                 binder_proc that owns this node
> + *                        (invariant after initialized)
> + * @refs:                 list of references on this node
> + *                        (protected by @lock)
> + * @internal_strong_refs: used to take strong references when
> + *                        initiating a transaction
> + *                        (protected by @proc->inner_lock if @proc
> + *                        and by @lock)
> + * @local_weak_refs:      weak user refs from local process
> + *                        (protected by @proc->inner_lock if @proc
> + *                        and by @lock)
> + * @local_strong_refs:    strong user refs from local process
> + *                        (protected by @proc->inner_lock if @proc
> + *                        and by @lock)
> + * @tmp_refs:             temporary kernel refs
> + *                        (protected by @proc->inner_lock while @proc
> + *                        is valid, and by binder_dead_nodes_lock
> + *                        if @proc is NULL. During inc/dec and node release
> + *                        it is also protected by @lock to provide safety
> + *                        as the node dies and @proc becomes NULL)
> + * @ptr:                  userspace pointer for node
> + *                        (invariant, no lock needed)
> + * @cookie:               userspace cookie for node
> + *                        (invariant, no lock needed)
> + * @has_strong_ref:       userspace notified of strong ref
> + *                        (protected by @proc->inner_lock if @proc
> + *                        and by @lock)
> + * @pending_strong_ref:   userspace has acked notification of strong ref
> + *                        (protected by @proc->inner_lock if @proc
> + *                        and by @lock)
> + * @has_weak_ref:         userspace notified of weak ref
> + *                        (protected by @proc->inner_lock if @proc
> + *                        and by @lock)
> + * @pending_weak_ref:     userspace has acked notification of weak ref
> + *                        (protected by @proc->inner_lock if @proc
> + *                        and by @lock)
> + * @has_async_transaction: async transaction to node in progress
> + *                        (protected by @lock)
> + * @accept_fds:           file descriptor operations supported for node
> + *                        (invariant after initialized)
> + * @min_priority:         minimum scheduling priority
> + *                        (invariant after initialized)
> + * @txn_security_ctx:     require sender's security context
> + *                        (invariant after initialized)
> + * @async_todo:           list of async work items
> + *                        (protected by @proc->inner_lock)
> + *
> + * Bookkeeping structure for binder nodes.
> + */
> +struct binder_node {
> +       int debug_id;
> +       spinlock_t lock;
> +       struct binder_work work;
> +       union {
> +               struct rb_node rb_node;
> +               struct hlist_node dead_node;
> +       };
> +       struct binder_proc *proc;
> +       struct hlist_head refs;
> +       int internal_strong_refs;
> +       int local_weak_refs;
> +       int local_strong_refs;
> +       int tmp_refs;
> +       binder_uintptr_t ptr;
> +       binder_uintptr_t cookie;
> +       struct {
> +               /*
> +                * bitfield elements protected by
> +                * proc inner_lock
> +                */
> +               u8 has_strong_ref:1;
> +               u8 pending_strong_ref:1;
> +               u8 has_weak_ref:1;
> +               u8 pending_weak_ref:1;
> +       };
> +       struct {
> +               /*
> +                * invariant after initialization
> +                */
> +               u8 accept_fds:1;
> +               u8 txn_security_ctx:1;
> +               u8 min_priority;
> +       };
> +       bool has_async_transaction;
> +       struct list_head async_todo;
> +};
> +
> +struct binder_ref_death {
> +       /**
> +        * @work: worklist element for death notifications
> +        *        (protected by inner_lock of the proc that
> +        *        this ref belongs to)
> +        */
> +       struct binder_work work;
> +       binder_uintptr_t cookie;
> +};
> +
> +/**
> + * struct binder_ref_data - binder_ref counts and id
> + * @debug_id:        unique ID for the ref
> + * @desc:            unique userspace handle for ref
> + * @strong:          strong ref count (debugging only if not locked)
> + * @weak:            weak ref count (debugging only if not locked)
> + *
> + * Structure to hold ref count and ref id information. Since
> + * the actual ref can only be accessed with a lock, this structure
> + * is used to return information about the ref to callers of
> + * ref inc/dec functions.
> + */
> +struct binder_ref_data {
> +       int debug_id;
> +       uint32_t desc;
> +       int strong;
> +       int weak;
> +};
> +
> +/**
> + * struct binder_ref - struct to track references on nodes
> + * @data:        binder_ref_data containing id, handle, and current refcounts
> + * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
> + * @rb_node_node: node for lookup by @node in proc's rb_tree
> + * @node_entry:  list entry for node->refs list in target node
> + *               (protected by @node->lock)
> + * @proc:        binder_proc containing ref
> + * @node:        binder_node of target node. When cleaning up a
> + *               ref for deletion in binder_cleanup_ref, a non-NULL
> + *               @node indicates the node must be freed
> + * @death:       pointer to death notification (ref_death) if requested
> + *               (protected by @node->lock)
> + *
> + * Structure to track references from procA to target node (on procB). This
> + * structure is unsafe to access without holding @proc->outer_lock.
> + */
> +struct binder_ref {
> +       /* Lookups needed: */
> +       /*   node + proc => ref (transaction) */
> +       /*   desc + proc => ref (transaction, inc/dec ref) */
> +       /*   node => refs + procs (proc exit) */
> +       struct binder_ref_data data;
> +       struct rb_node rb_node_desc;
> +       struct rb_node rb_node_node;
> +       struct hlist_node node_entry;
> +       struct binder_proc *proc;
> +       struct binder_node *node;
> +       struct binder_ref_death *death;
> +};
> +
> +/**
> + * struct binder_proc - binder process bookkeeping
> + * @proc_node:            element for binder_procs list
> + * @threads:              rbtree of binder_threads in this proc
> + *                        (protected by @inner_lock)
> + * @nodes:                rbtree of binder nodes associated with
> + *                        this proc ordered by node->ptr
> + *                        (protected by @inner_lock)
> + * @refs_by_desc:         rbtree of refs ordered by ref->desc
> + *                        (protected by @outer_lock)
> + * @refs_by_node:         rbtree of refs ordered by ref->node
> + *                        (protected by @outer_lock)
> + * @waiting_threads:      threads currently waiting for proc work
> + *                        (protected by @inner_lock)
> + * @pid                   PID of group_leader of process
> + *                        (invariant after initialized)
> + * @tsk                   task_struct for group_leader of process
> + *                        (invariant after initialized)
> + * @deferred_work_node:   element for binder_deferred_list
> + *                        (protected by binder_deferred_lock)
> + * @deferred_work:        bitmap of deferred work to perform
> + *                        (protected by binder_deferred_lock)
> + * @is_dead:              process is dead and awaiting free
> + *                        when outstanding transactions are cleaned up
> + *                        (protected by @inner_lock)
> + * @todo:                 list of work for this process
> + *                        (protected by @inner_lock)
> + * @stats:                per-process binder statistics
> + *                        (atomics, no lock needed)
> + * @delivered_death:      list of delivered death notification
> + *                        (protected by @inner_lock)
> + * @max_threads:          cap on number of binder threads
> + *                        (protected by @inner_lock)
> + * @requested_threads:    number of binder threads requested but not
> + *                        yet started. In current implementation, can
> + *                        only be 0 or 1.
> + *                        (protected by @inner_lock)
> + * @requested_threads_started: number binder threads started
> + *                        (protected by @inner_lock)
> + * @tmp_ref:              temporary reference to indicate proc is in use
> + *                        (protected by @inner_lock)
> + * @default_priority:     default scheduler priority
> + *                        (invariant after initialized)
> + * @debugfs_entry:        debugfs node
> + * @alloc:                binder allocator bookkeeping
> + * @context:              binder_context for this proc
> + *                        (invariant after initialized)
> + * @inner_lock:           can nest under outer_lock and/or node lock
> + * @outer_lock:           no nesting under innor or node lock
> + *                        Lock order: 1) outer, 2) node, 3) inner
> + * @binderfs_entry:       process-specific binderfs log file
> + *
> + * Bookkeeping structure for binder processes
> + */
> +struct binder_proc {
> +       struct hlist_node proc_node;
> +       struct rb_root threads;
> +       struct rb_root nodes;
> +       struct rb_root refs_by_desc;
> +       struct rb_root refs_by_node;
> +       struct list_head waiting_threads;
> +       int pid;
> +       struct task_struct *tsk;
> +       struct hlist_node deferred_work_node;
> +       int deferred_work;
> +       bool is_dead;
> +
> +       struct list_head todo;
> +       struct binder_stats stats;
> +       struct list_head delivered_death;
> +       int max_threads;
> +       int requested_threads;
> +       int requested_threads_started;
> +       int tmp_ref;
> +       long default_priority;
> +       struct dentry *debugfs_entry;
> +       struct binder_alloc alloc;
> +       struct binder_context *context;
> +       spinlock_t inner_lock;
> +       spinlock_t outer_lock;
> +       struct dentry *binderfs_entry;
> +};
> +
> +/**
> + * struct binder_thread - binder thread bookkeeping
> + * @proc:                 binder process for this thread
> + *                        (invariant after initialization)
> + * @rb_node:              element for proc->threads rbtree
> + *                        (protected by @proc->inner_lock)
> + * @waiting_thread_node:  element for @proc->waiting_threads list
> + *                        (protected by @proc->inner_lock)
> + * @pid:                  PID for this thread
> + *                        (invariant after initialization)
> + * @looper:               bitmap of looping state
> + *                        (only accessed by this thread)
> + * @looper_needs_return:  looping thread needs to exit driver
> + *                        (no lock needed)
> + * @transaction_stack:    stack of in-progress transactions for this thread
> + *                        (protected by @proc->inner_lock)
> + * @todo:                 list of work to do for this thread
> + *                        (protected by @proc->inner_lock)
> + * @process_todo:         whether work in @todo should be processed
> + *                        (protected by @proc->inner_lock)
> + * @return_error:         transaction errors reported by this thread
> + *                        (only accessed by this thread)
> + * @reply_error:          transaction errors reported by target thread
> + *                        (protected by @proc->inner_lock)
> + * @wait:                 wait queue for thread work
> + * @stats:                per-thread statistics
> + *                        (atomics, no lock needed)
> + * @tmp_ref:              temporary reference to indicate thread is in use
> + *                        (atomic since @proc->inner_lock cannot
> + *                        always be acquired)
> + * @is_dead:              thread is dead and awaiting free
> + *                        when outstanding transactions are cleaned up
> + *                        (protected by @proc->inner_lock)
> + *
> + * Bookkeeping structure for binder threads.
> + */
> +struct binder_thread {
> +       struct binder_proc *proc;
> +       struct rb_node rb_node;
> +       struct list_head waiting_thread_node;
> +       int pid;
> +       int looper;              /* only modified by this thread */
> +       bool looper_need_return; /* can be written by other thread */
> +       struct binder_transaction *transaction_stack;
> +       struct list_head todo;
> +       bool process_todo;
> +       struct binder_error return_error;
> +       struct binder_error reply_error;
> +       wait_queue_head_t wait;
> +       struct binder_stats stats;
> +       atomic_t tmp_ref;
> +       bool is_dead;
> +};
> +
> +/**
> + * struct binder_txn_fd_fixup - transaction fd fixup list element
> + * @fixup_entry:          list entry
> + * @file:                 struct file to be associated with new fd
> + * @offset:               offset in buffer data to this fixup
> + *
> + * List element for fd fixups in a transaction. Since file
> + * descriptors need to be allocated in the context of the
> + * target process, we pass each fd to be processed in this
> + * struct.
> + */
> +struct binder_txn_fd_fixup {
> +       struct list_head fixup_entry;
> +       struct file *file;
> +       size_t offset;
> +};
> +
> +struct binder_transaction {
> +       int debug_id;
> +       struct binder_work work;
> +       struct binder_thread *from;
> +       struct binder_transaction *from_parent;
> +       struct binder_proc *to_proc;
> +       struct binder_thread *to_thread;
> +       struct binder_transaction *to_parent;
> +       unsigned need_reply:1;
> +       /* unsigned is_dead:1; */       /* not used at the moment */
> +
> +       struct binder_buffer *buffer;
> +       unsigned int    code;
> +       unsigned int    flags;
> +       long    priority;
> +       long    saved_priority;
> +       kuid_t  sender_euid;
> +       struct list_head fd_fixups;
> +       binder_uintptr_t security_ctx;
> +       /**
> +        * @lock:  protects @from, @to_proc, and @to_thread
> +        *
> +        * @from, @to_proc, and @to_thread can be set to NULL
> +        * during thread teardown
> +        */
> +       spinlock_t lock;
> +};
> +
> +/**
> + * struct binder_object - union of flat binder object types
> + * @hdr:   generic object header
> + * @fbo:   binder object (nodes and refs)
> + * @fdo:   file descriptor object
> + * @bbo:   binder buffer pointer
> + * @fdao:  file descriptor array
> + *
> + * Used for type-independent object copies
> + */
> +struct binder_object {
> +       union {
> +               struct binder_object_header hdr;
> +               struct flat_binder_object fbo;
> +               struct binder_fd_object fdo;
> +               struct binder_buffer_object bbo;
> +               struct binder_fd_array_object fdao;
> +       };
> +};
> +
>  extern struct binder_transaction_log binder_transaction_log;
>  extern struct binder_transaction_log binder_transaction_log_failed;
>  #endif /* _LINUX_BINDER_INTERNAL_H */
> --
> 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v7 2/3] binder: add trace at free transaction.
  2020-08-04 13:59                                                   ` [PATCH v7 2/3] binder: add trace at free transaction Frankie Chang
@ 2020-08-04 15:26                                                     ` Todd Kjos
  0 siblings, 0 replies; 72+ messages in thread
From: Todd Kjos @ 2020-08-04 15:26 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Tue, Aug 4, 2020 at 7:09 AM Frankie Chang <Frankie.Chang@mediatek.com> wrote:
>
> From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
>
> Since the original trace_binder_transaction_received cannot
> precisely present the real finished time of transaction, adding a
> trace_binder_txn_latency_free at the point of free transaction
> may be more close to it.
>
> Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>

Acked-by: Todd Kjos <tkjos@google.com>

> ---
>  drivers/android/binder.c       |   18 ++++++++++++++++++
>  drivers/android/binder_trace.h |   29 +++++++++++++++++++++++++++++
>  2 files changed, 47 insertions(+)
>
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 2df146f..1bfadc2 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -1508,6 +1508,20 @@ static void binder_free_txn_fixups(struct binder_transaction *t)
>         }
>  }
>
> +static void binder_txn_latency_free(struct binder_transaction *t)
> +{
> +       int from_proc, from_thread, to_proc, to_thread;
> +
> +       spin_lock(&t->lock);
> +       from_proc = t->from ? t->from->proc->pid : 0;
> +       from_thread = t->from ? t->from->pid : 0;
> +       to_proc = t->to_proc ? t->to_proc->pid : 0;
> +       to_thread = t->to_thread ? t->to_thread->pid : 0;
> +       spin_unlock(&t->lock);
> +
> +       trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc, to_thread);
> +}
> +
>  static void binder_free_transaction(struct binder_transaction *t)
>  {
>         struct binder_proc *target_proc = t->to_proc;
> @@ -1518,6 +1532,8 @@ static void binder_free_transaction(struct binder_transaction *t)
>                         t->buffer->transaction = NULL;
>                 binder_inner_proc_unlock(target_proc);
>         }
> +       if (trace_binder_txn_latency_free_enabled())
> +               binder_txn_latency_free(t);
>         /*
>          * If the transaction has no target_proc, then
>          * t->buffer->transaction has already been cleared.
> @@ -3093,6 +3109,8 @@ static void binder_transaction(struct binder_proc *proc,
>         kfree(tcomplete);
>         binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
>  err_alloc_tcomplete_failed:
> +       if (trace_binder_txn_latency_free_enabled())
> +               binder_txn_latency_free(t);
>         kfree(t);
>         binder_stats_deleted(BINDER_STAT_TRANSACTION);
>  err_alloc_t_failed:
> diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> index 6731c3c..eb2c53c 100644
> --- a/drivers/android/binder_trace.h
> +++ b/drivers/android/binder_trace.h
> @@ -95,6 +95,35 @@
>                   __entry->thread_todo)
>  );
>
> +TRACE_EVENT(binder_txn_latency_free,
> +       TP_PROTO(struct binder_transaction *t
> +                int from_proc, int from_thread
> +                int to_proc, int to_thread),
> +       TP_ARGS(t, from_proc, from_thread, to_proc, to_thread),
> +       TP_STRUCT__entry(
> +               __field(int, debug_id)
> +               __field(int, from_proc)
> +               __field(int, from_thread)
> +               __field(int, to_proc)
> +               __field(int, to_thread)
> +               __field(unsigned int, code)
> +               __field(unsigned int, flags)
> +       ),
> +       TP_fast_assign(
> +               __entry->debug_id = t->debug_id;
> +               __entry->from_proc = from_proc;
> +               __entry->from_thread = from_thread;
> +               __entry->to_proc = to_proc;
> +               __entry->to_thread = to_thread;
> +               __entry->code = t->code;
> +               __entry->flags = t->flags;
> +       ),
> +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> +                 __entry->debug_id, __entry->from_proc, __entry->from_thread,
> +                 __entry->to_proc, __entry->to_thread, __entry->code,
> +                 __entry->flags)
> +);
> +
>  TRACE_EVENT(binder_transaction,
>         TP_PROTO(bool reply, struct binder_transaction *t,
>                  struct binder_node *target_node),
> --
> 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v7 3/3] binder: add transaction latency tracer
  2020-08-04 13:59                                                   ` [PATCH v7 3/3] binder: add transaction latency tracer Frankie Chang
@ 2020-08-04 15:28                                                     ` Todd Kjos
  2020-09-07 14:41                                                     ` peter enderborg
  1 sibling, 0 replies; 72+ messages in thread
From: Todd Kjos @ 2020-08-04 15:28 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, Greg Kroah-Hartman, LKML, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner

On Tue, Aug 4, 2020 at 6:59 AM Frankie Chang <Frankie.Chang@mediatek.com> wrote:
>
> From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
>
> Record start/end timestamp for binder transaction.
> When transaction is completed or transaction is free,
> it would be checked if transaction latency over threshold
> (default 2 sec), if yes, printing related information for tracing.
>
> /* Implement details */
> - Add latency tracer module to monitor transaction
>   by attaching to new tracepoints introduced
>   when transactions are allocated and freed.
>   The trace_binder_txn_latency_free would not be enabled
>   by default. Monitoring which transaction is too slow to
>   cause some of exceptions is important. So we hook the
>   tracepoint to call the monitor function.
>
> - Since some of modules would trigger timeout NE
>   if their binder transaction don't finish in time,
>   such as audio timeout (5 sec), even BT command
>   timeout (2 sec), etc.
>   Therefore, setting the timeout threshold as default
>   2 seconds could be helpful to debug.
>   But this timeout threshold is configurable, to let
>   all users determine the more suitable threshold.
>
> - The reason why printing the related information to
>   kernel information log but not trace buffer is that
>   some abnormal transactions may be pending for a long
>   time ago, they could not be recorded due to buffer
>   limited.
>
> Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>

Acked-by: Todd Kjos <tkjos@google.com>

> ---
>  drivers/android/Kconfig                 |    8 +++
>  drivers/android/Makefile                |    1 +
>  drivers/android/binder.c                |    2 +
>  drivers/android/binder_internal.h       |   13 ++++
>  drivers/android/binder_latency_tracer.c |  112 +++++++++++++++++++++++++++++++
>  drivers/android/binder_trace.h          |   26 ++++++-
>  6 files changed, 159 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/android/binder_latency_tracer.c
>
> diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> index 6fdf2ab..91fff1e 100644
> --- a/drivers/android/Kconfig
> +++ b/drivers/android/Kconfig
> @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
>           exhaustively with combinations of various buffer sizes and
>           alignments.
>
> +config BINDER_TRANSACTION_LATENCY_TRACKING
> +       tristate "Android Binder transaction tracking"
> +       help
> +         Used for track abnormal binder transaction which is over threshold,
> +         when the transaction is done or be free, this transaction would be
> +         checked whether it executed overtime.
> +         If yes, printing out the detailed info.
> +
>  endif # if ANDROID
>
>  endmenu
> diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> index c9d3d0c9..c2ffdb6 100644
> --- a/drivers/android/Makefile
> +++ b/drivers/android/Makefile
> @@ -4,3 +4,4 @@ ccflags-y += -I$(src)                   # needed for trace events
>  obj-$(CONFIG_ANDROID_BINDERFS)         += binderfs.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC)       += binder.o binder_alloc.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> +obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)      += binder_latency_tracer.o
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 1bfadc2..22f7cc6 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2671,6 +2671,7 @@ static void binder_transaction(struct binder_proc *proc,
>                 return_error_line = __LINE__;
>                 goto err_alloc_t_failed;
>         }
> +       trace_binder_txn_latency_alloc(t);
>         INIT_LIST_HEAD(&t->fd_fixups);
>         binder_stats_created(BINDER_STAT_TRANSACTION);
>         spin_lock_init(&t->lock);
> @@ -5159,6 +5160,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
>                    to_proc ? to_proc->pid : 0,
>                    t->to_thread ? t->to_thread->pid : 0,
>                    t->code, t->flags, t->priority, t->need_reply);
> +       trace_binder_txn_latency_info(m, t);
>         spin_unlock(&t->lock);
>
>         if (proc != to_proc) {
> diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> index 5b65413..596db00 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -13,6 +13,11 @@
>  #include <linux/uidgid.h>
>  #include "binder_alloc.h"
>
> +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> +#include <linux/rtc.h>
> +#include <linux/time.h>
> +#endif
> +
>  struct binder_context {
>         struct binder_node *binder_context_mgr_node;
>         struct mutex context_mgr_node_lock;
> @@ -521,6 +526,14 @@ struct binder_transaction {
>          * during thread teardown
>          */
>         spinlock_t lock;
> +       /**
> +        * @timestamp and @tv are used to record the time
> +        * that the binder transaction startup
> +        */
> +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> +       struct timespec64 timestamp;
> +       struct timeval tv;
> +#endif
>  };
>
>  /**
> diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
> new file mode 100644
> index 0000000..61ae75f
> --- /dev/null
> +++ b/drivers/android/binder_latency_tracer.c
> @@ -0,0 +1,112 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2019 MediaTek Inc.
> + */
> +
> +#include <linux/module.h>
> +#include <uapi/linux/android/binder.h>
> +#include "binder_internal.h"
> +#include "binder_trace.h"
> +
> +/**
> + * The reason setting the binder_txn_latency_threshold to 2 sec
> + * is that most of timeout abort is greater or equal to 2 sec.
> + * Making it configurable to let all users determine which
> + * threshold is more suitable.
> + */
> +static uint32_t binder_txn_latency_threshold = 2;
> +module_param_named(threshold, binder_txn_latency_threshold,
> +                       uint, 0644);
> +
> +/*
> + * probe_binder_txn_latency_free - Output info of a delay transaction
> + * @t:          pointer to the over-time transaction
> + */
> +void probe_binder_txn_latency_free(void *ignore, struct binder_transaction *t,
> +                                       int from_proc, int from_thread,
> +                                       int to_proc, int to_thread)
> +{
> +       struct rtc_time tm;
> +       struct timespec64 *startime;
> +       struct timespec64 cur, sub_t;
> +
> +       ktime_get_ts64(&cur);
> +       startime = &t->timestamp;
> +       sub_t = timespec64_sub(cur, *startime);
> +
> +       /* if transaction time is over than binder_txn_latency_threshold (sec),
> +        * show timeout warning log.
> +        */
> +       if (sub_t.tv_sec < binder_txn_latency_threshold)
> +               return;
> +
> +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> +
> +       pr_info_ratelimited("%d: from %d:%d to %d:%d",
> +                       t->debug_id, from_proc, from_thread,
> +                       to_proc, to_thread);
> +
> +       pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
> +                       (unsigned int)sub_t.tv_sec,
> +                       (sub_t.tv_nsec / NSEC_PER_MSEC),
> +                       t->code,
> +                       (unsigned long)startime->tv_sec,
> +                       (startime->tv_nsec / NSEC_PER_MSEC),
> +                       (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> +                       tm.tm_hour, tm.tm_min, tm.tm_sec,
> +                       (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> +}
> +
> +static void probe_binder_txn_latency_alloc(void *ignore,
> +                                       struct binder_transaction *t)
> +{
> +       struct timespec64 now;
> +
> +       ktime_get_ts64(&t->timestamp);
> +       ktime_get_real_ts64(&now);
> +       t->tv.tv_sec = now.tv_sec;
> +       t->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
> +       t->tv.tv_usec = now.tv_nsec/1000;
> +}
> +
> +static void probe_binder_txn_latency_info(void *ignore, struct seq_file *m,
> +                                       struct binder_transaction *t)
> +{
> +       struct rtc_time tm;
> +
> +       rtc_time_to_tm(t->tv.tv_sec, &tm);
> +       seq_printf(m,
> +                  " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
> +                  (unsigned long)t->timestamp.tv_sec,
> +                  (t->timestamp.tv_nsec / NSEC_PER_USEC),
> +                  (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
> +                  tm.tm_hour, tm.tm_min, tm.tm_sec,
> +                  (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
> +}
> +
> +static int __init init_binder_latency_tracer(void)
> +{
> +       register_trace_binder_txn_latency_free(
> +                       probe_binder_txn_latency_free, NULL);
> +       register_trace_binder_txn_latency_alloc(
> +                       probe_binder_txn_latency_alloc, NULL);
> +       register_trace_binder_txn_latency_info(
> +                       probe_binder_txn_latency_info, NULL);
> +
> +       return 0;
> +}
> +
> +static void exit_binder_latency_tracer(void)
> +{
> +       unregister_trace_binder_txn_latency_free(
> +                       probe_binder_txn_latency_free, NULL);
> +       unregister_trace_binder_txn_latency_alloc(
> +                       probe_binder_txn_latency_alloc, NULL);
> +       unregister_trace_binder_txn_latency_info(
> +                       probe_binder_txn_latency_info, NULL);
> +}
> +
> +module_init(init_binder_latency_tracer);
> +module_exit(exit_binder_latency_tracer);
> +
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
> index eb2c53c..be4fe4c 100644
> --- a/drivers/android/binder_trace.h
> +++ b/drivers/android/binder_trace.h
> @@ -95,6 +95,17 @@
>                   __entry->thread_todo)
>  );
>
> +DECLARE_TRACE(binder_txn_latency_alloc,
> +       TP_PROTO(struct binder_transaction *t),
> +       TP_ARGS(t, e)
> +);
> +
> +DECLARE_TRACE(binder_txn_latency_info,
> +       TP_PROTO(struct seq_file *m,
> +                struct binder_transaction *t),
> +       TP_ARGS(m, t)
> +);
> +
>  TRACE_EVENT(binder_txn_latency_free,
>         TP_PROTO(struct binder_transaction *t
>                  int from_proc, int from_thread
> @@ -108,6 +119,8 @@
>                 __field(int, to_thread)
>                 __field(unsigned int, code)
>                 __field(unsigned int, flags)
> +               __field(unsigned long, start_sec)
> +               __field(unsigned long, start_nsec)
>         ),
>         TP_fast_assign(
>                 __entry->debug_id = t->debug_id;
> @@ -117,11 +130,18 @@
>                 __entry->to_thread = to_thread;
>                 __entry->code = t->code;
>                 __entry->flags = t->flags;
> -       ),
> -       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
> +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> +               __entry->start_sec = t->timestamp.tv_sec;
> +               __entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
> +#else
> +               __entry->start_sec = 0;
> +               __entry->start_nsec = 0;
> +#endif
> +       ),
> +       TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
>                   __entry->debug_id, __entry->from_proc, __entry->from_thread,
>                   __entry->to_proc, __entry->to_thread, __entry->code,
> -                 __entry->flags)
> +                 __entry->flags, __entry->start_sec, __entry->start_nsec)
>  );
>
>  TRACE_EVENT(binder_transaction,
> --
> 1.7.9.5

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v7] binder: transaction latency tracking for user build
  2020-08-04 13:59                                                 ` [PATCH v7] binder: transaction latency tracking for user build Frankie Chang
                                                                     ` (2 preceding siblings ...)
  2020-08-04 13:59                                                   ` [PATCH v7 3/3] binder: add transaction latency tracer Frankie Chang
@ 2020-09-03 16:21                                                   ` Greg Kroah-Hartman
  2020-09-07  6:49                                                     ` Frankie Chang
  3 siblings, 1 reply; 72+ messages in thread
From: Greg Kroah-Hartman @ 2020-09-03 16:21 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Tue, Aug 04, 2020 at 09:59:09PM +0800, Frankie Chang wrote:
> 
> Frankie.Chang (3):
>   binder: move structs from core file to header file
>   binder: add trace at free transaction.
>   binder: add transaction latency tracer
> 
>  drivers/android/Kconfig                 |    8 +
>  drivers/android/Makefile                |    1 +
>  drivers/android/binder.c                |  425 ++-----------------------------
>  drivers/android/binder_internal.h       |  417 ++++++++++++++++++++++++++++++
>  drivers/android/binder_latency_tracer.c |  112 ++++++++
>  drivers/android/binder_trace.h          |   49 ++++
>  6 files changed, 607 insertions(+), 405 deletions(-)  create mode 100644 drivers/android/binder_latency_tracer.c

This series blows up the build into lots of tiny pieces, how was it
tested?

Here's my error logs:

In file included from drivers/android/binderfs.c:37:
drivers/android/binder_internal.h:537:17: error: field ‘tv’ has incomplete type
  537 |  struct timeval tv;
      |                 ^~
In file included from drivers/android/binder_trace.h:12,
                 from drivers/android/binder_alloc.c:27:
drivers/android/binder_trace.h: In function ‘trace_binder_txn_latency_alloc’:
drivers/android/binder_trace.h:100:13: error: ‘e’ undeclared (first use in this function)
  100 |  TP_ARGS(t, e)
      |             ^
./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
  191 |     ((void(*)(proto))(it_func))(args); \
      |                                 ^~~~
./include/linux/tracepoint.h:236:5: note: in expansion of macro ‘TP_ARGS’
  236 |     TP_ARGS(data_args),   \
      |     ^~~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
  378 |    PARAMS(__data, args))
      |    ^~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
  100 |  TP_ARGS(t, e)
      |  ^~~~~~~
drivers/android/binder_trace.h:100:13: note: each undeclared identifier is reported only once for each function it appears in
  100 |  TP_ARGS(t, e)
      |             ^
./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
  191 |     ((void(*)(proto))(it_func))(args); \
      |                                 ^~~~
./include/linux/tracepoint.h:236:5: note: in expansion of macro ‘TP_ARGS’
  236 |     TP_ARGS(data_args),   \
      |     ^~~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
  378 |    PARAMS(__data, args))
      |    ^~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
  100 |  TP_ARGS(t, e)
      |  ^~~~~~~
./include/linux/tracepoint.h:191:6: error: too many arguments to function ‘(void (*)(void *, struct binder_transaction *))it_func’
  191 |     ((void(*)(proto))(it_func))(args); \
      |     ~^~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/tracepoint.h:234:4: note: in expansion of macro ‘__DO_TRACE’
  234 |    __DO_TRACE(&__tracepoint_##name,  \
      |    ^~~~~~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h: In function ‘trace_binder_txn_latency_alloc_rcuidle’:
drivers/android/binder_trace.h:100:13: error: ‘e’ undeclared (first use in this function)
  100 |  TP_ARGS(t, e)
      |             ^
./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
  191 |     ((void(*)(proto))(it_func))(args); \
      |                                 ^~~~
./include/linux/tracepoint.h:210:5: note: in expansion of macro ‘TP_ARGS’
  210 |     TP_ARGS(data_args),   \
      |     ^~~~~~~
./include/linux/tracepoint.h:244:2: note: in expansion of macro ‘__DECLARE_TRACE_RCU’
  244 |  __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~~~~~
./include/linux/tracepoint.h:245:37: note: in expansion of macro ‘PARAMS’
  245 |   PARAMS(cond), PARAMS(data_proto), PARAMS(data_args)) \
      |                                     ^~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
  378 |    PARAMS(__data, args))
      |    ^~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
  100 |  TP_ARGS(t, e)
      |  ^~~~~~~
./include/linux/tracepoint.h:191:6: error: too many arguments to function ‘(void (*)(void *, struct binder_transaction *))it_func’
  191 |     ((void(*)(proto))(it_func))(args); \
      |     ~^~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/tracepoint.h:208:4: note: in expansion of macro ‘__DO_TRACE’
  208 |    __DO_TRACE(&__tracepoint_##name,  \
      |    ^~~~~~~~~~
./include/linux/tracepoint.h:244:2: note: in expansion of macro ‘__DECLARE_TRACE_RCU’
  244 |  __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h: At top level:
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:231:34: note: in definition of macro ‘__DECLARE_TRACE’
  231 |  static inline void trace_##name(proto)    \
      |                                  ^~~~~
./include/linux/tracepoint.h:375:24: note: in expansion of macro ‘PARAMS’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |                        ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:205:44: note: in definition of macro ‘__DECLARE_TRACE_RCU’
  205 |  static inline void trace_##name##_rcuidle(proto)  \
      |                                            ^~~~~
./include/linux/tracepoint.h:244:28: note: in expansion of macro ‘PARAMS’
  244 |  __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),  \
      |                            ^~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:375:24: note: in expansion of macro ‘PARAMS’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |                        ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:247:38: note: in definition of macro ‘__DECLARE_TRACE’
  247 |  register_trace_##name(void (*probe)(data_proto), void *data) \
      |                                      ^~~~~~~~~~
./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
  377 |    PARAMS(void *__data, proto),   \
      |    ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
./include/linux/tracepoint.h:247:51: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
  247 |  register_trace_##name(void (*probe)(data_proto), void *data) \
      |                                                   ^~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:253:43: note: in definition of macro ‘__DECLARE_TRACE’
  253 |  register_trace_prio_##name(void (*probe)(data_proto), void *data,\
      |                                           ^~~~~~~~~~
./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
  377 |    PARAMS(void *__data, proto),   \
      |    ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
./include/linux/tracepoint.h:253:56: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
  253 |  register_trace_prio_##name(void (*probe)(data_proto), void *data,\
      |                                                        ^~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:260:40: note: in definition of macro ‘__DECLARE_TRACE’
  260 |  unregister_trace_##name(void (*probe)(data_proto), void *data) \
      |                                        ^~~~~~~~~~
./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
  377 |    PARAMS(void *__data, proto),   \
      |    ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
./include/linux/tracepoint.h:260:53: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
  260 |  unregister_trace_##name(void (*probe)(data_proto), void *data) \
      |                                                     ^~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:266:46: note: in definition of macro ‘__DECLARE_TRACE’
  266 |  check_trace_callback_type_##name(void (*cb)(data_proto)) \
      |                                              ^~~~~~~~~~
./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
  377 |    PARAMS(void *__data, proto),   \
      |    ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
make[2]: *** [scripts/Makefile.build:283: drivers/android/binderfs.o] Error 1
make[2]: *** Waiting for unfinished jobs....
In file included from drivers/android/binder_latency_tracer.c:8:
drivers/android/binder_internal.h:141:20: error: ‘BINDERFS_MAX_NAME’ undeclared here (not in a function)
  141 |  char context_name[BINDERFS_MAX_NAME + 1];
      |                    ^~~~~~~~~~~~~~~~~
drivers/android/binder_internal.h:537:17: error: field ‘tv’ has incomplete type
  537 |  struct timeval tv;
      |                 ^~
In file included from drivers/android/binder_trace.h:12,
                 from drivers/android/binder_latency_tracer.c:9:
drivers/android/binder_trace.h: In function ‘trace_binder_txn_latency_alloc’:
drivers/android/binder_trace.h:100:13: error: ‘e’ undeclared (first use in this function)
  100 |  TP_ARGS(t, e)
      |             ^
./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
  191 |     ((void(*)(proto))(it_func))(args); \
      |                                 ^~~~
./include/linux/tracepoint.h:236:5: note: in expansion of macro ‘TP_ARGS’
  236 |     TP_ARGS(data_args),   \
      |     ^~~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
  378 |    PARAMS(__data, args))
      |    ^~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
  100 |  TP_ARGS(t, e)
      |  ^~~~~~~
drivers/android/binder_trace.h:100:13: note: each undeclared identifier is reported only once for each function it appears in
  100 |  TP_ARGS(t, e)
      |             ^
./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
  191 |     ((void(*)(proto))(it_func))(args); \
      |                                 ^~~~
./include/linux/tracepoint.h:236:5: note: in expansion of macro ‘TP_ARGS’
  236 |     TP_ARGS(data_args),   \
      |     ^~~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
  378 |    PARAMS(__data, args))
      |    ^~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
  100 |  TP_ARGS(t, e)
      |  ^~~~~~~
./include/linux/tracepoint.h:191:6: error: too many arguments to function ‘(void (*)(void *, struct binder_transaction *))it_func’
  191 |     ((void(*)(proto))(it_func))(args); \
      |     ~^~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/tracepoint.h:234:4: note: in expansion of macro ‘__DO_TRACE’
  234 |    __DO_TRACE(&__tracepoint_##name,  \
      |    ^~~~~~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h: At top level:
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:231:34: note: in definition of macro ‘__DECLARE_TRACE’
  231 |  static inline void trace_##name(proto)    \
      |                                  ^~~~~
./include/linux/tracepoint.h:375:24: note: in expansion of macro ‘PARAMS’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |                        ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:247:38: note: in definition of macro ‘__DECLARE_TRACE’
  247 |  register_trace_##name(void (*probe)(data_proto), void *data) \
      |                                      ^~~~~~~~~~
./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
  377 |    PARAMS(void *__data, proto),   \
      |    ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
./include/linux/tracepoint.h:247:51: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
  247 |  register_trace_##name(void (*probe)(data_proto), void *data) \
      |                                                   ^~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:253:43: note: in definition of macro ‘__DECLARE_TRACE’
  253 |  register_trace_prio_##name(void (*probe)(data_proto), void *data,\
      |                                           ^~~~~~~~~~
./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
  377 |    PARAMS(void *__data, proto),   \
      |    ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
./include/linux/tracepoint.h:253:56: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
  253 |  register_trace_prio_##name(void (*probe)(data_proto), void *data,\
      |                                                        ^~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:260:40: note: in definition of macro ‘__DECLARE_TRACE’
  260 |  unregister_trace_##name(void (*probe)(data_proto), void *data) \
      |                                        ^~~~~~~~~~
./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
  377 |    PARAMS(void *__data, proto),   \
      |    ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
./include/linux/tracepoint.h:260:53: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
  260 |  unregister_trace_##name(void (*probe)(data_proto), void *data) \
      |                                                     ^~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:266:46: note: in definition of macro ‘__DECLARE_TRACE’
  266 |  check_trace_callback_type_##name(void (*cb)(data_proto)) \
      |                                              ^~~~~~~~~~
./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
  377 |    PARAMS(void *__data, proto),   \
      |    ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
In file included from drivers/android/binder.c:75:
drivers/android/binder_internal.h:537:17: error: field ‘tv’ has incomplete type
  537 |  struct timeval tv;
      |                 ^~
In file included from ./include/trace/syscall.h:5,
                 from ./include/linux/syscalls.h:84,
                 from drivers/android/binder.c:66:
drivers/android/binder_trace.h: In function ‘trace_binder_txn_latency_alloc’:
drivers/android/binder_trace.h:100:13: error: ‘e’ undeclared (first use in this function)
  100 |  TP_ARGS(t, e)
      |             ^
./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
  191 |     ((void(*)(proto))(it_func))(args); \
      |                                 ^~~~
./include/linux/tracepoint.h:236:5: note: in expansion of macro ‘TP_ARGS’
  236 |     TP_ARGS(data_args),   \
      |     ^~~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
  378 |    PARAMS(__data, args))
      |    ^~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
  100 |  TP_ARGS(t, e)
      |  ^~~~~~~
drivers/android/binder_trace.h:100:13: note: each undeclared identifier is reported only once for each function it appears in
  100 |  TP_ARGS(t, e)
      |             ^
./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
  191 |     ((void(*)(proto))(it_func))(args); \
      |                                 ^~~~
./include/linux/tracepoint.h:236:5: note: in expansion of macro ‘TP_ARGS’
  236 |     TP_ARGS(data_args),   \
      |     ^~~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
  378 |    PARAMS(__data, args))
      |    ^~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
  100 |  TP_ARGS(t, e)
      |  ^~~~~~~
./include/linux/tracepoint.h:191:6: error: too many arguments to function ‘(void (*)(void *, struct binder_transaction *))it_func’
  191 |     ((void(*)(proto))(it_func))(args); \
      |     ~^~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/tracepoint.h:234:4: note: in expansion of macro ‘__DO_TRACE’
  234 |    __DO_TRACE(&__tracepoint_##name,  \
      |    ^~~~~~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h: In function ‘trace_binder_txn_latency_alloc_rcuidle’:
drivers/android/binder_trace.h:100:13: error: ‘e’ undeclared (first use in this function)
  100 |  TP_ARGS(t, e)
      |             ^
./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
  191 |     ((void(*)(proto))(it_func))(args); \
      |                                 ^~~~
./include/linux/tracepoint.h:210:5: note: in expansion of macro ‘TP_ARGS’
  210 |     TP_ARGS(data_args),   \
      |     ^~~~~~~
./include/linux/tracepoint.h:244:2: note: in expansion of macro ‘__DECLARE_TRACE_RCU’
  244 |  __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~~~~~
./include/linux/tracepoint.h:245:37: note: in expansion of macro ‘PARAMS’
  245 |   PARAMS(cond), PARAMS(data_proto), PARAMS(data_args)) \
      |                                     ^~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
  378 |    PARAMS(__data, args))
      |    ^~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
  100 |  TP_ARGS(t, e)
      |  ^~~~~~~
./include/linux/tracepoint.h:191:6: error: too many arguments to function ‘(void (*)(void *, struct binder_transaction *))it_func’
  191 |     ((void(*)(proto))(it_func))(args); \
      |     ~^~~~~~~~~~~~~~~~~~~~~~~~~~
./include/linux/tracepoint.h:208:4: note: in expansion of macro ‘__DO_TRACE’
  208 |    __DO_TRACE(&__tracepoint_##name,  \
      |    ^~~~~~~~~~
./include/linux/tracepoint.h:244:2: note: in expansion of macro ‘__DECLARE_TRACE_RCU’
  244 |  __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
   98 | DECLARE_TRACE(binder_txn_latency_alloc,
      | ^~~~~~~~~~~~~
drivers/android/binder_trace.h: At top level:
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:231:34: note: in definition of macro ‘__DECLARE_TRACE’
  231 |  static inline void trace_##name(proto)    \
      |                                  ^~~~~
./include/linux/tracepoint.h:375:24: note: in expansion of macro ‘PARAMS’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |                        ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:205:44: note: in definition of macro ‘__DECLARE_TRACE_RCU’
  205 |  static inline void trace_##name##_rcuidle(proto)  \
      |                                            ^~~~~
./include/linux/tracepoint.h:244:28: note: in expansion of macro ‘PARAMS’
  244 |  __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),  \
      |                            ^~~~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:375:24: note: in expansion of macro ‘PARAMS’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |                        ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:247:38: note: in definition of macro ‘__DECLARE_TRACE’
  247 |  register_trace_##name(void (*probe)(data_proto), void *data) \
      |                                      ^~~~~~~~~~
./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
  377 |    PARAMS(void *__data, proto),   \
      |    ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
./include/linux/tracepoint.h:247:51: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
  247 |  register_trace_##name(void (*probe)(data_proto), void *data) \
      |                                                   ^~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:253:43: note: in definition of macro ‘__DECLARE_TRACE’
  253 |  register_trace_prio_##name(void (*probe)(data_proto), void *data,\
      |                                           ^~~~~~~~~~
./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
  377 |    PARAMS(void *__data, proto),   \
      |    ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
./include/linux/tracepoint.h:253:56: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
  253 |  register_trace_prio_##name(void (*probe)(data_proto), void *data,\
      |                                                        ^~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:260:40: note: in definition of macro ‘__DECLARE_TRACE’
  260 |  unregister_trace_##name(void (*probe)(data_proto), void *data) \
      |                                        ^~~~~~~~~~
./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
  377 |    PARAMS(void *__data, proto),   \
      |    ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
./include/linux/tracepoint.h:260:53: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
  260 |  unregister_trace_##name(void (*probe)(data_proto), void *data) \
      |                                                     ^~~~
./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
  375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
      |  ^~~~~~~~~~~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/linux/tracepoint.h:266:46: note: in definition of macro ‘__DECLARE_TRACE’
  266 |  check_trace_callback_type_##name(void (*cb)(data_proto)) \
      |                                              ^~~~~~~~~~
./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
  377 |    PARAMS(void *__data, proto),   \
      |    ^~~~~~
./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |  ^~~~~~~~~~~~~
./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
  511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
      |                      ^~~~~~
drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
drivers/android/binder_latency_tracer.c: In function ‘probe_binder_txn_latency_free’:
drivers/android/binder_latency_tracer.c:43:2: error: implicit declaration of function ‘rtc_time_to_tm’; did you mean ‘rtc_ktime_to_tm’? [-Werror=implicit-function-declaration]
   43 |  rtc_time_to_tm(t->tv.tv_sec, &tm);
      |  ^~~~~~~~~~~~~~
      |  rtc_ktime_to_tm
make[2]: *** [scripts/Makefile.build:283: drivers/android/binder_alloc.o] Error 1
drivers/android/binder_latency_tracer.c: In function ‘init_binder_latency_tracer’:
drivers/android/binder_latency_tracer.c:89:2: error: implicit declaration of function ‘register_trace_binder_txn_latency_free’; did you mean ‘register_trace_binder_txn_latency_info’? [-Werror=implicit-function-declaration]
   89 |  register_trace_binder_txn_latency_free(
      |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |  register_trace_binder_txn_latency_info
drivers/android/binder_latency_tracer.c: In function ‘exit_binder_latency_tracer’:
drivers/android/binder_latency_tracer.c:101:2: error: implicit declaration of function ‘unregister_trace_binder_txn_latency_free’; did you mean ‘unregister_trace_binder_txn_latency_info’? [-Werror=implicit-function-declaration]
  101 |  unregister_trace_binder_txn_latency_free(
      |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |  unregister_trace_binder_txn_latency_info
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:283: drivers/android/binder_latency_tracer.o] Error 1
drivers/android/binder.c: In function ‘binder_txn_latency_free’:
drivers/android/binder.c:1522:2: error: implicit declaration of function ‘trace_binder_txn_latency_free’; did you mean ‘trace_binder_txn_latency_info’? [-Werror=implicit-function-declaration]
 1522 |  trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc, to_thread);
      |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |  trace_binder_txn_latency_info
In file included from ./include/trace/define_trace.h:102,
                 from drivers/android/binder_trace.h:448,
                 from drivers/android/binder.c:5822:
drivers/android/./binder_trace.h: At top level:
drivers/android/./binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/trace/trace_events.h:510:58: note: in definition of macro ‘DECLARE_EVENT_CLASS’
  510 |  struct trace_event_data_offsets_##call *__data_offsets, proto) \
      |                                                          ^~~~~
./include/trace/trace_events.h:76:9: note: in expansion of macro ‘PARAMS’
   76 |         PARAMS(proto),         \
      |         ^~~~~~
drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/./binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
In file included from ./include/trace/define_trace.h:102,
                 from drivers/android/binder_trace.h:448,
                 from drivers/android/binder.c:5822:
drivers/android/./binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/trace/trace_events.h:674:44: note: in definition of macro ‘DECLARE_EVENT_CLASS’
  674 | trace_event_raw_event_##call(void *__data, proto)   \
      |                                            ^~~~~
./include/trace/trace_events.h:76:9: note: in expansion of macro ‘PARAMS’
   76 |         PARAMS(proto),         \
      |         ^~~~~~
drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/./binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
drivers/android/./binder_trace.h: In function ‘ftrace_test_probe_binder_txn_latency_free’:
./include/trace/trace_events.h:709:2: error: implicit declaration of function ‘check_trace_callback_type_binder_txn_latency_free’; did you mean ‘check_trace_callback_type_binder_txn_latency_info’? [-Werror=implicit-function-declaration]
  709 |  check_trace_callback_type_##call(trace_event_raw_event_##template); \
      |  ^~~~~~~~~~~~~~~~~~~~~~~~~~
./include/trace/trace_events.h:81:2: note: in expansion of macro ‘DEFINE_EVENT’
   81 |  DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args));
      |  ^~~~~~~~~~~~
drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
./include/trace/trace_events.h:709:35: error: ‘trace_event_raw_event_binder_txn_latency_free’ undeclared (first use in this function); did you mean ‘trace_event_raw_binder_txn_latency_free’?
  709 |  check_trace_callback_type_##call(trace_event_raw_event_##template); \
      |                                   ^~~~~~~~~~~~~~~~~~~~~~
./include/trace/trace_events.h:81:2: note: in expansion of macro ‘DEFINE_EVENT’
   81 |  DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args));
      |  ^~~~~~~~~~~~
drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/./binder_trace.h: At top level:
drivers/android/./binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/trace/trace_events.h:618:34: note: in definition of macro ‘_TRACE_PERF_PROTO’
  618 |  perf_trace_##call(void *__data, proto);
      |                                  ^~~~~
./include/trace/trace_events.h:733:25: note: in expansion of macro ‘PARAMS’
  733 | _TRACE_PERF_PROTO(call, PARAMS(proto));     \
      |                         ^~~~~~
./include/trace/trace_events.h:75:2: note: in expansion of macro ‘DECLARE_EVENT_CLASS’
   75 |  DECLARE_EVENT_CLASS(name,          \
      |  ^~~~~~~~~~~~~~~~~~~
./include/trace/trace_events.h:76:9: note: in expansion of macro ‘PARAMS’
   76 |         PARAMS(proto),         \
      |         ^~~~~~
drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/./binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
In file included from ./include/trace/define_trace.h:102,
                 from drivers/android/binder_trace.h:448,
                 from drivers/android/binder.c:5822:
./include/trace/trace_events.h:740:13: error: ‘trace_event_raw_event_binder_txn_latency_free’ undeclared here (not in a function); did you mean ‘trace_event_raw_binder_txn_latency_free’?
  740 |  .probe   = trace_event_raw_event_##call,  \
      |             ^~~~~~~~~~~~~~~~~~~~~~
./include/trace/trace_events.h:75:2: note: in expansion of macro ‘DECLARE_EVENT_CLASS’
   75 |  DECLARE_EVENT_CLASS(name,          \
      |  ^~~~~~~~~~~~~~~~~~~
drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
In file included from ./include/trace/define_trace.h:102,
                 from drivers/android/binder_trace.h:448,
                 from drivers/android/binder.c:5822:
./include/trace/trace_events.h:621:17: error: ‘perf_trace_binder_txn_latency_free’ undeclared here (not in a function); did you mean ‘print_fmt_binder_txn_latency_free’?
  621 |  .perf_probe  = perf_trace_##call,
      |                 ^~~~~~~~~~~
./include/trace/trace_events.h:742:2: note: in expansion of macro ‘_TRACE_PERF_INIT’
  742 |  _TRACE_PERF_INIT(call)      \
      |  ^~~~~~~~~~~~~~~~
./include/trace/trace_events.h:75:2: note: in expansion of macro ‘DECLARE_EVENT_CLASS’
   75 |  DECLARE_EVENT_CLASS(name,          \
      |  ^~~~~~~~~~~~~~~~~~~
drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
In file included from ./include/trace/define_trace.h:103,
                 from drivers/android/binder_trace.h:448,
                 from drivers/android/binder.c:5822:
drivers/android/./binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
  111 |    int from_proc, int from_thread
      |    ^~~
./include/trace/perf.h:33:33: note: in definition of macro ‘DECLARE_EVENT_CLASS’
   33 | perf_trace_##call(void *__data, proto)     \
      |                                 ^~~~~
./include/trace/trace_events.h:76:9: note: in expansion of macro ‘PARAMS’
   76 |         PARAMS(proto),         \
      |         ^~~~~~
drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
  109 | TRACE_EVENT(binder_txn_latency_free,
      | ^~~~~~~~~~~
drivers/android/./binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
  110 |  TP_PROTO(struct binder_transaction *t
      |  ^~~~~~~~
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:283: drivers/android/binder.o] Error 1
make[1]: *** [scripts/Makefile.build:500: drivers/android] Error 2
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1788: drivers] Error 2


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v7] binder: transaction latency tracking for user build
  2020-09-03 16:21                                                   ` [PATCH v7] binder: transaction latency tracking for user build Greg Kroah-Hartman
@ 2020-09-07  6:49                                                     ` Frankie Chang
  2020-09-07  7:00                                                       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-09-07  6:49 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Thu, 2020-09-03 at 18:21 +0200, Greg Kroah-Hartman wrote:
> On Tue, Aug 04, 2020 at 09:59:09PM +0800, Frankie Chang wrote:
> > 
> > Frankie.Chang (3):
> >   binder: move structs from core file to header file
> >   binder: add trace at free transaction.
> >   binder: add transaction latency tracer
> > 
> >  drivers/android/Kconfig                 |    8 +
> >  drivers/android/Makefile                |    1 +
> >  drivers/android/binder.c                |  425 ++-----------------------------
> >  drivers/android/binder_internal.h       |  417 ++++++++++++++++++++++++++++++
> >  drivers/android/binder_latency_tracer.c |  112 ++++++++
> >  drivers/android/binder_trace.h          |   49 ++++
> >  6 files changed, 607 insertions(+), 405 deletions(-)  create mode 100644 drivers/android/binder_latency_tracer.c
> 
> This series blows up the build into lots of tiny pieces, how was it
> tested?
> 

I am sorry that I had built pass.on the too older kernel, and some of
api had been deprecated.
I have fixed these errors in local, and I add the
EXPORT_TRACEPOINT_SYMBOL for binder_latency_tracer to be ko needed.

Do I need to push a patch V8 or I provide the fixed code here ?

~/mtk_soc_new$ cat b.log | grep binder
  CC      drivers/android/binderfs.o
  CC      drivers/android/binder.o
  CC [M]  drivers/android/binder_latency_tracer.o
  LD [M]  drivers/android/binder_latency_tracer.ko

~/mtk_soc_new$ tail -n 10 b.log
make[1]: Leaving directory `/proj/mtk16184/mtk_soc_new/kernel/mediatek'
make ARCH=arm64
CROSS_COMPILE=/proj/mtk16184/mtk_soc_new/prebuilt/toolchain/aarch64/usr/bin/aarch64-poky-linux/aarch64-poky-linux- O=/proj/mtk16184/mtk_soc_new/out -C kernel/mediatek dtbs
make[1]: Entering directory `/proj/mtk16184/mtk_soc_new/kernel/mediatek'
make[2]: Entering directory `/proj/mtk16184/mtk_soc_new/out'
arch/arm64/Makefile:26: ld does not support --fix-cortex-a53-843419;
kernel may be susceptible to erratum
arch/arm64/Makefile:34: LSE atomics not supported by binutils
make[2]: Leaving directory `/proj/mtk16184/mtk_soc_new/out'
make[1]: Leaving directory `/proj/mtk16184/mtk_soc_new/kernel/mediatek'
cat /proj/mtk16184/mtk_soc_new/out/arch/arm64/boot/Image.gz /proj/mtk16184/mtk_soc_new/out/arch/arm64/boot/dts/mediatek/mt6779-evb.dtb > /proj/mtk16184/mtk_soc_new/out/arch/arm64/boot/Image.gz-dtb
/proj/mtk16184/mtk_soc_new/prebuilt/bootable/mkbootimg
--kernel /proj/mtk16184/mtk_soc_new/out/arch/arm64/boot/Image.gz-dtb
--ramdisk /proj/mtk16184/mtk_soc_new/prebuilt/bootable/6779_loader/ramdisk.img --base 0x40000000 --ramdisk_offset 0x04000000 --kernel_offset 0x00080000 --cmdline bootopt=64S3,32N2,64N2 --output /proj/mtk16184/mtk_soc_new/prebuilt/bootable/6779_loader/boot.img


> Here's my error logs:
> 
> In file included from drivers/android/binderfs.c:37:
> drivers/android/binder_internal.h:537:17: error: field ‘tv’ has incomplete type
>   537 |  struct timeval tv;
>       |                 ^~
> In file included from drivers/android/binder_trace.h:12,
>                  from drivers/android/binder_alloc.c:27:
> drivers/android/binder_trace.h: In function ‘trace_binder_txn_latency_alloc’:
> drivers/android/binder_trace.h:100:13: error: ‘e’ undeclared (first use in this function)
>   100 |  TP_ARGS(t, e)
>       |             ^
> ./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |                                 ^~~~
> ./include/linux/tracepoint.h:236:5: note: in expansion of macro ‘TP_ARGS’
>   236 |     TP_ARGS(data_args),   \
>       |     ^~~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
>   378 |    PARAMS(__data, args))
>       |    ^~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
>   100 |  TP_ARGS(t, e)
>       |  ^~~~~~~
> drivers/android/binder_trace.h:100:13: note: each undeclared identifier is reported only once for each function it appears in
>   100 |  TP_ARGS(t, e)
>       |             ^
> ./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |                                 ^~~~
> ./include/linux/tracepoint.h:236:5: note: in expansion of macro ‘TP_ARGS’
>   236 |     TP_ARGS(data_args),   \
>       |     ^~~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
>   378 |    PARAMS(__data, args))
>       |    ^~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
>   100 |  TP_ARGS(t, e)
>       |  ^~~~~~~
> ./include/linux/tracepoint.h:191:6: error: too many arguments to function ‘(void (*)(void *, struct binder_transaction *))it_func’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |     ~^~~~~~~~~~~~~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:234:4: note: in expansion of macro ‘__DO_TRACE’
>   234 |    __DO_TRACE(&__tracepoint_##name,  \
>       |    ^~~~~~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h: In function ‘trace_binder_txn_latency_alloc_rcuidle’:
> drivers/android/binder_trace.h:100:13: error: ‘e’ undeclared (first use in this function)
>   100 |  TP_ARGS(t, e)
>       |             ^
> ./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |                                 ^~~~
> ./include/linux/tracepoint.h:210:5: note: in expansion of macro ‘TP_ARGS’
>   210 |     TP_ARGS(data_args),   \
>       |     ^~~~~~~
> ./include/linux/tracepoint.h:244:2: note: in expansion of macro ‘__DECLARE_TRACE_RCU’
>   244 |  __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:245:37: note: in expansion of macro ‘PARAMS’
>   245 |   PARAMS(cond), PARAMS(data_proto), PARAMS(data_args)) \
>       |                                     ^~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
>   378 |    PARAMS(__data, args))
>       |    ^~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
>   100 |  TP_ARGS(t, e)
>       |  ^~~~~~~
> ./include/linux/tracepoint.h:191:6: error: too many arguments to function ‘(void (*)(void *, struct binder_transaction *))it_func’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |     ~^~~~~~~~~~~~~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:208:4: note: in expansion of macro ‘__DO_TRACE’
>   208 |    __DO_TRACE(&__tracepoint_##name,  \
>       |    ^~~~~~~~~~
> ./include/linux/tracepoint.h:244:2: note: in expansion of macro ‘__DECLARE_TRACE_RCU’
>   244 |  __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h: At top level:
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:231:34: note: in definition of macro ‘__DECLARE_TRACE’
>   231 |  static inline void trace_##name(proto)    \
>       |                                  ^~~~~
> ./include/linux/tracepoint.h:375:24: note: in expansion of macro ‘PARAMS’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |                        ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:205:44: note: in definition of macro ‘__DECLARE_TRACE_RCU’
>   205 |  static inline void trace_##name##_rcuidle(proto)  \
>       |                                            ^~~~~
> ./include/linux/tracepoint.h:244:28: note: in expansion of macro ‘PARAMS’
>   244 |  __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),  \
>       |                            ^~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:375:24: note: in expansion of macro ‘PARAMS’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |                        ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:247:38: note: in definition of macro ‘__DECLARE_TRACE’
>   247 |  register_trace_##name(void (*probe)(data_proto), void *data) \
>       |                                      ^~~~~~~~~~
> ./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
>   377 |    PARAMS(void *__data, proto),   \
>       |    ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> ./include/linux/tracepoint.h:247:51: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
>   247 |  register_trace_##name(void (*probe)(data_proto), void *data) \
>       |                                                   ^~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:253:43: note: in definition of macro ‘__DECLARE_TRACE’
>   253 |  register_trace_prio_##name(void (*probe)(data_proto), void *data,\
>       |                                           ^~~~~~~~~~
> ./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
>   377 |    PARAMS(void *__data, proto),   \
>       |    ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> ./include/linux/tracepoint.h:253:56: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
>   253 |  register_trace_prio_##name(void (*probe)(data_proto), void *data,\
>       |                                                        ^~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:260:40: note: in definition of macro ‘__DECLARE_TRACE’
>   260 |  unregister_trace_##name(void (*probe)(data_proto), void *data) \
>       |                                        ^~~~~~~~~~
> ./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
>   377 |    PARAMS(void *__data, proto),   \
>       |    ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> ./include/linux/tracepoint.h:260:53: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
>   260 |  unregister_trace_##name(void (*probe)(data_proto), void *data) \
>       |                                                     ^~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:266:46: note: in definition of macro ‘__DECLARE_TRACE’
>   266 |  check_trace_callback_type_##name(void (*cb)(data_proto)) \
>       |                                              ^~~~~~~~~~
> ./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
>   377 |    PARAMS(void *__data, proto),   \
>       |    ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> make[2]: *** [scripts/Makefile.build:283: drivers/android/binderfs.o] Error 1
> make[2]: *** Waiting for unfinished jobs....
> In file included from drivers/android/binder_latency_tracer.c:8:
> drivers/android/binder_internal.h:141:20: error: ‘BINDERFS_MAX_NAME’ undeclared here (not in a function)
>   141 |  char context_name[BINDERFS_MAX_NAME + 1];
>       |                    ^~~~~~~~~~~~~~~~~
> drivers/android/binder_internal.h:537:17: error: field ‘tv’ has incomplete type
>   537 |  struct timeval tv;
>       |                 ^~
> In file included from drivers/android/binder_trace.h:12,
>                  from drivers/android/binder_latency_tracer.c:9:
> drivers/android/binder_trace.h: In function ‘trace_binder_txn_latency_alloc’:
> drivers/android/binder_trace.h:100:13: error: ‘e’ undeclared (first use in this function)
>   100 |  TP_ARGS(t, e)
>       |             ^
> ./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |                                 ^~~~
> ./include/linux/tracepoint.h:236:5: note: in expansion of macro ‘TP_ARGS’
>   236 |     TP_ARGS(data_args),   \
>       |     ^~~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
>   378 |    PARAMS(__data, args))
>       |    ^~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
>   100 |  TP_ARGS(t, e)
>       |  ^~~~~~~
> drivers/android/binder_trace.h:100:13: note: each undeclared identifier is reported only once for each function it appears in
>   100 |  TP_ARGS(t, e)
>       |             ^
> ./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |                                 ^~~~
> ./include/linux/tracepoint.h:236:5: note: in expansion of macro ‘TP_ARGS’
>   236 |     TP_ARGS(data_args),   \
>       |     ^~~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
>   378 |    PARAMS(__data, args))
>       |    ^~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
>   100 |  TP_ARGS(t, e)
>       |  ^~~~~~~
> ./include/linux/tracepoint.h:191:6: error: too many arguments to function ‘(void (*)(void *, struct binder_transaction *))it_func’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |     ~^~~~~~~~~~~~~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:234:4: note: in expansion of macro ‘__DO_TRACE’
>   234 |    __DO_TRACE(&__tracepoint_##name,  \
>       |    ^~~~~~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h: At top level:
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:231:34: note: in definition of macro ‘__DECLARE_TRACE’
>   231 |  static inline void trace_##name(proto)    \
>       |                                  ^~~~~
> ./include/linux/tracepoint.h:375:24: note: in expansion of macro ‘PARAMS’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |                        ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:247:38: note: in definition of macro ‘__DECLARE_TRACE’
>   247 |  register_trace_##name(void (*probe)(data_proto), void *data) \
>       |                                      ^~~~~~~~~~
> ./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
>   377 |    PARAMS(void *__data, proto),   \
>       |    ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> ./include/linux/tracepoint.h:247:51: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
>   247 |  register_trace_##name(void (*probe)(data_proto), void *data) \
>       |                                                   ^~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:253:43: note: in definition of macro ‘__DECLARE_TRACE’
>   253 |  register_trace_prio_##name(void (*probe)(data_proto), void *data,\
>       |                                           ^~~~~~~~~~
> ./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
>   377 |    PARAMS(void *__data, proto),   \
>       |    ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> ./include/linux/tracepoint.h:253:56: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
>   253 |  register_trace_prio_##name(void (*probe)(data_proto), void *data,\
>       |                                                        ^~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:260:40: note: in definition of macro ‘__DECLARE_TRACE’
>   260 |  unregister_trace_##name(void (*probe)(data_proto), void *data) \
>       |                                        ^~~~~~~~~~
> ./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
>   377 |    PARAMS(void *__data, proto),   \
>       |    ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> ./include/linux/tracepoint.h:260:53: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
>   260 |  unregister_trace_##name(void (*probe)(data_proto), void *data) \
>       |                                                     ^~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:266:46: note: in definition of macro ‘__DECLARE_TRACE’
>   266 |  check_trace_callback_type_##name(void (*cb)(data_proto)) \
>       |                                              ^~~~~~~~~~
> ./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
>   377 |    PARAMS(void *__data, proto),   \
>       |    ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> In file included from drivers/android/binder.c:75:
> drivers/android/binder_internal.h:537:17: error: field ‘tv’ has incomplete type
>   537 |  struct timeval tv;
>       |                 ^~
> In file included from ./include/trace/syscall.h:5,
>                  from ./include/linux/syscalls.h:84,
>                  from drivers/android/binder.c:66:
> drivers/android/binder_trace.h: In function ‘trace_binder_txn_latency_alloc’:
> drivers/android/binder_trace.h:100:13: error: ‘e’ undeclared (first use in this function)
>   100 |  TP_ARGS(t, e)
>       |             ^
> ./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |                                 ^~~~
> ./include/linux/tracepoint.h:236:5: note: in expansion of macro ‘TP_ARGS’
>   236 |     TP_ARGS(data_args),   \
>       |     ^~~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
>   378 |    PARAMS(__data, args))
>       |    ^~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
>   100 |  TP_ARGS(t, e)
>       |  ^~~~~~~
> drivers/android/binder_trace.h:100:13: note: each undeclared identifier is reported only once for each function it appears in
>   100 |  TP_ARGS(t, e)
>       |             ^
> ./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |                                 ^~~~
> ./include/linux/tracepoint.h:236:5: note: in expansion of macro ‘TP_ARGS’
>   236 |     TP_ARGS(data_args),   \
>       |     ^~~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
>   378 |    PARAMS(__data, args))
>       |    ^~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
>   100 |  TP_ARGS(t, e)
>       |  ^~~~~~~
> ./include/linux/tracepoint.h:191:6: error: too many arguments to function ‘(void (*)(void *, struct binder_transaction *))it_func’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |     ~^~~~~~~~~~~~~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:234:4: note: in expansion of macro ‘__DO_TRACE’
>   234 |    __DO_TRACE(&__tracepoint_##name,  \
>       |    ^~~~~~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h: In function ‘trace_binder_txn_latency_alloc_rcuidle’:
> drivers/android/binder_trace.h:100:13: error: ‘e’ undeclared (first use in this function)
>   100 |  TP_ARGS(t, e)
>       |             ^
> ./include/linux/tracepoint.h:191:33: note: in definition of macro ‘__DO_TRACE’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |                                 ^~~~
> ./include/linux/tracepoint.h:210:5: note: in expansion of macro ‘TP_ARGS’
>   210 |     TP_ARGS(data_args),   \
>       |     ^~~~~~~
> ./include/linux/tracepoint.h:244:2: note: in expansion of macro ‘__DECLARE_TRACE_RCU’
>   244 |  __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:245:37: note: in expansion of macro ‘PARAMS’
>   245 |   PARAMS(cond), PARAMS(data_proto), PARAMS(data_args)) \
>       |                                     ^~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:378:4: note: in expansion of macro ‘PARAMS’
>   378 |    PARAMS(__data, args))
>       |    ^~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:100:2: note: in expansion of macro ‘TP_ARGS’
>   100 |  TP_ARGS(t, e)
>       |  ^~~~~~~
> ./include/linux/tracepoint.h:191:6: error: too many arguments to function ‘(void (*)(void *, struct binder_transaction *))it_func’
>   191 |     ((void(*)(proto))(it_func))(args); \
>       |     ~^~~~~~~~~~~~~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:208:4: note: in expansion of macro ‘__DO_TRACE’
>   208 |    __DO_TRACE(&__tracepoint_##name,  \
>       |    ^~~~~~~~~~
> ./include/linux/tracepoint.h:244:2: note: in expansion of macro ‘__DECLARE_TRACE_RCU’
>   244 |  __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> drivers/android/binder_trace.h:98:1: note: in expansion of macro ‘DECLARE_TRACE’
>    98 | DECLARE_TRACE(binder_txn_latency_alloc,
>       | ^~~~~~~~~~~~~
> drivers/android/binder_trace.h: At top level:
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:231:34: note: in definition of macro ‘__DECLARE_TRACE’
>   231 |  static inline void trace_##name(proto)    \
>       |                                  ^~~~~
> ./include/linux/tracepoint.h:375:24: note: in expansion of macro ‘PARAMS’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |                        ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:205:44: note: in definition of macro ‘__DECLARE_TRACE_RCU’
>   205 |  static inline void trace_##name##_rcuidle(proto)  \
>       |                                            ^~~~~
> ./include/linux/tracepoint.h:244:28: note: in expansion of macro ‘PARAMS’
>   244 |  __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),  \
>       |                            ^~~~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:375:24: note: in expansion of macro ‘PARAMS’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |                        ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:247:38: note: in definition of macro ‘__DECLARE_TRACE’
>   247 |  register_trace_##name(void (*probe)(data_proto), void *data) \
>       |                                      ^~~~~~~~~~
> ./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
>   377 |    PARAMS(void *__data, proto),   \
>       |    ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> ./include/linux/tracepoint.h:247:51: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
>   247 |  register_trace_##name(void (*probe)(data_proto), void *data) \
>       |                                                   ^~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:253:43: note: in definition of macro ‘__DECLARE_TRACE’
>   253 |  register_trace_prio_##name(void (*probe)(data_proto), void *data,\
>       |                                           ^~~~~~~~~~
> ./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
>   377 |    PARAMS(void *__data, proto),   \
>       |    ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> ./include/linux/tracepoint.h:253:56: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
>   253 |  register_trace_prio_##name(void (*probe)(data_proto), void *data,\
>       |                                                        ^~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:260:40: note: in definition of macro ‘__DECLARE_TRACE’
>   260 |  unregister_trace_##name(void (*probe)(data_proto), void *data) \
>       |                                        ^~~~~~~~~~
> ./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
>   377 |    PARAMS(void *__data, proto),   \
>       |    ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> ./include/linux/tracepoint.h:260:53: error: expected ‘;’, ‘,’ or ‘)’ before ‘void’
>   260 |  unregister_trace_##name(void (*probe)(data_proto), void *data) \
>       |                                                     ^~~~
> ./include/linux/tracepoint.h:375:2: note: in expansion of macro ‘__DECLARE_TRACE’
>   375 |  __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),  \
>       |  ^~~~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/linux/tracepoint.h:266:46: note: in definition of macro ‘__DECLARE_TRACE’
>   266 |  check_trace_callback_type_##name(void (*cb)(data_proto)) \
>       |                                              ^~~~~~~~~~
> ./include/linux/tracepoint.h:377:4: note: in expansion of macro ‘PARAMS’
>   377 |    PARAMS(void *__data, proto),   \
>       |    ^~~~~~
> ./include/linux/tracepoint.h:511:2: note: in expansion of macro ‘DECLARE_TRACE’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |  ^~~~~~~~~~~~~
> ./include/linux/tracepoint.h:511:22: note: in expansion of macro ‘PARAMS’
>   511 |  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
>       |                      ^~~~~~
> drivers/android/binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> drivers/android/binder_latency_tracer.c: In function ‘probe_binder_txn_latency_free’:
> drivers/android/binder_latency_tracer.c:43:2: error: implicit declaration of function ‘rtc_time_to_tm’; did you mean ‘rtc_ktime_to_tm’? [-Werror=implicit-function-declaration]
>    43 |  rtc_time_to_tm(t->tv.tv_sec, &tm);
>       |  ^~~~~~~~~~~~~~
>       |  rtc_ktime_to_tm
> make[2]: *** [scripts/Makefile.build:283: drivers/android/binder_alloc.o] Error 1
> drivers/android/binder_latency_tracer.c: In function ‘init_binder_latency_tracer’:
> drivers/android/binder_latency_tracer.c:89:2: error: implicit declaration of function ‘register_trace_binder_txn_latency_free’; did you mean ‘register_trace_binder_txn_latency_info’? [-Werror=implicit-function-declaration]
>    89 |  register_trace_binder_txn_latency_free(
>       |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>       |  register_trace_binder_txn_latency_info
> drivers/android/binder_latency_tracer.c: In function ‘exit_binder_latency_tracer’:
> drivers/android/binder_latency_tracer.c:101:2: error: implicit declaration of function ‘unregister_trace_binder_txn_latency_free’; did you mean ‘unregister_trace_binder_txn_latency_info’? [-Werror=implicit-function-declaration]
>   101 |  unregister_trace_binder_txn_latency_free(
>       |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>       |  unregister_trace_binder_txn_latency_info
> cc1: some warnings being treated as errors
> make[2]: *** [scripts/Makefile.build:283: drivers/android/binder_latency_tracer.o] Error 1
> drivers/android/binder.c: In function ‘binder_txn_latency_free’:
> drivers/android/binder.c:1522:2: error: implicit declaration of function ‘trace_binder_txn_latency_free’; did you mean ‘trace_binder_txn_latency_info’? [-Werror=implicit-function-declaration]
>  1522 |  trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc, to_thread);
>       |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>       |  trace_binder_txn_latency_info
> In file included from ./include/trace/define_trace.h:102,
>                  from drivers/android/binder_trace.h:448,
>                  from drivers/android/binder.c:5822:
> drivers/android/./binder_trace.h: At top level:
> drivers/android/./binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/trace/trace_events.h:510:58: note: in definition of macro ‘DECLARE_EVENT_CLASS’
>   510 |  struct trace_event_data_offsets_##call *__data_offsets, proto) \
>       |                                                          ^~~~~
> ./include/trace/trace_events.h:76:9: note: in expansion of macro ‘PARAMS’
>    76 |         PARAMS(proto),         \
>       |         ^~~~~~
> drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/./binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> In file included from ./include/trace/define_trace.h:102,
>                  from drivers/android/binder_trace.h:448,
>                  from drivers/android/binder.c:5822:
> drivers/android/./binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/trace/trace_events.h:674:44: note: in definition of macro ‘DECLARE_EVENT_CLASS’
>   674 | trace_event_raw_event_##call(void *__data, proto)   \
>       |                                            ^~~~~
> ./include/trace/trace_events.h:76:9: note: in expansion of macro ‘PARAMS’
>    76 |         PARAMS(proto),         \
>       |         ^~~~~~
> drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/./binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> drivers/android/./binder_trace.h: In function ‘ftrace_test_probe_binder_txn_latency_free’:
> ./include/trace/trace_events.h:709:2: error: implicit declaration of function ‘check_trace_callback_type_binder_txn_latency_free’; did you mean ‘check_trace_callback_type_binder_txn_latency_info’? [-Werror=implicit-function-declaration]
>   709 |  check_trace_callback_type_##call(trace_event_raw_event_##template); \
>       |  ^~~~~~~~~~~~~~~~~~~~~~~~~~
> ./include/trace/trace_events.h:81:2: note: in expansion of macro ‘DEFINE_EVENT’
>    81 |  DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args));
>       |  ^~~~~~~~~~~~
> drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> ./include/trace/trace_events.h:709:35: error: ‘trace_event_raw_event_binder_txn_latency_free’ undeclared (first use in this function); did you mean ‘trace_event_raw_binder_txn_latency_free’?
>   709 |  check_trace_callback_type_##call(trace_event_raw_event_##template); \
>       |                                   ^~~~~~~~~~~~~~~~~~~~~~
> ./include/trace/trace_events.h:81:2: note: in expansion of macro ‘DEFINE_EVENT’
>    81 |  DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args));
>       |  ^~~~~~~~~~~~
> drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/./binder_trace.h: At top level:
> drivers/android/./binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/trace/trace_events.h:618:34: note: in definition of macro ‘_TRACE_PERF_PROTO’
>   618 |  perf_trace_##call(void *__data, proto);
>       |                                  ^~~~~
> ./include/trace/trace_events.h:733:25: note: in expansion of macro ‘PARAMS’
>   733 | _TRACE_PERF_PROTO(call, PARAMS(proto));     \
>       |                         ^~~~~~
> ./include/trace/trace_events.h:75:2: note: in expansion of macro ‘DECLARE_EVENT_CLASS’
>    75 |  DECLARE_EVENT_CLASS(name,          \
>       |  ^~~~~~~~~~~~~~~~~~~
> ./include/trace/trace_events.h:76:9: note: in expansion of macro ‘PARAMS’
>    76 |         PARAMS(proto),         \
>       |         ^~~~~~
> drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/./binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> In file included from ./include/trace/define_trace.h:102,
>                  from drivers/android/binder_trace.h:448,
>                  from drivers/android/binder.c:5822:
> ./include/trace/trace_events.h:740:13: error: ‘trace_event_raw_event_binder_txn_latency_free’ undeclared here (not in a function); did you mean ‘trace_event_raw_binder_txn_latency_free’?
>   740 |  .probe   = trace_event_raw_event_##call,  \
>       |             ^~~~~~~~~~~~~~~~~~~~~~
> ./include/trace/trace_events.h:75:2: note: in expansion of macro ‘DECLARE_EVENT_CLASS’
>    75 |  DECLARE_EVENT_CLASS(name,          \
>       |  ^~~~~~~~~~~~~~~~~~~
> drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> In file included from ./include/trace/define_trace.h:102,
>                  from drivers/android/binder_trace.h:448,
>                  from drivers/android/binder.c:5822:
> ./include/trace/trace_events.h:621:17: error: ‘perf_trace_binder_txn_latency_free’ undeclared here (not in a function); did you mean ‘print_fmt_binder_txn_latency_free’?
>   621 |  .perf_probe  = perf_trace_##call,
>       |                 ^~~~~~~~~~~
> ./include/trace/trace_events.h:742:2: note: in expansion of macro ‘_TRACE_PERF_INIT’
>   742 |  _TRACE_PERF_INIT(call)      \
>       |  ^~~~~~~~~~~~~~~~
> ./include/trace/trace_events.h:75:2: note: in expansion of macro ‘DECLARE_EVENT_CLASS’
>    75 |  DECLARE_EVENT_CLASS(name,          \
>       |  ^~~~~~~~~~~~~~~~~~~
> drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> In file included from ./include/trace/define_trace.h:103,
>                  from drivers/android/binder_trace.h:448,
>                  from drivers/android/binder.c:5822:
> drivers/android/./binder_trace.h:111:4: error: expected ‘;’, ‘,’ or ‘)’ before ‘int’
>   111 |    int from_proc, int from_thread
>       |    ^~~
> ./include/trace/perf.h:33:33: note: in definition of macro ‘DECLARE_EVENT_CLASS’
>    33 | perf_trace_##call(void *__data, proto)     \
>       |                                 ^~~~~
> ./include/trace/trace_events.h:76:9: note: in expansion of macro ‘PARAMS’
>    76 |         PARAMS(proto),         \
>       |         ^~~~~~
> drivers/android/./binder_trace.h:109:1: note: in expansion of macro ‘TRACE_EVENT’
>   109 | TRACE_EVENT(binder_txn_latency_free,
>       | ^~~~~~~~~~~
> drivers/android/./binder_trace.h:110:2: note: in expansion of macro ‘TP_PROTO’
>   110 |  TP_PROTO(struct binder_transaction *t
>       |  ^~~~~~~~
> cc1: some warnings being treated as errors
> make[2]: *** [scripts/Makefile.build:283: drivers/android/binder.o] Error 1
> make[1]: *** [scripts/Makefile.build:500: drivers/android] Error 2
> make[1]: *** Waiting for unfinished jobs....
> make: *** [Makefile:1788: drivers] Error 2
> 

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v7] binder: transaction latency tracking for user build
  2020-09-07  6:49                                                     ` Frankie Chang
@ 2020-09-07  7:00                                                       ` Greg Kroah-Hartman
  2020-09-07 12:00                                                         ` [PATCH v8] " Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Greg Kroah-Hartman @ 2020-09-07  7:00 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Mon, Sep 07, 2020 at 02:49:29PM +0800, Frankie Chang wrote:
> On Thu, 2020-09-03 at 18:21 +0200, Greg Kroah-Hartman wrote:
> > On Tue, Aug 04, 2020 at 09:59:09PM +0800, Frankie Chang wrote:
> > > 
> > > Frankie.Chang (3):
> > >   binder: move structs from core file to header file
> > >   binder: add trace at free transaction.
> > >   binder: add transaction latency tracer
> > > 
> > >  drivers/android/Kconfig                 |    8 +
> > >  drivers/android/Makefile                |    1 +
> > >  drivers/android/binder.c                |  425 ++-----------------------------
> > >  drivers/android/binder_internal.h       |  417 ++++++++++++++++++++++++++++++
> > >  drivers/android/binder_latency_tracer.c |  112 ++++++++
> > >  drivers/android/binder_trace.h          |   49 ++++
> > >  6 files changed, 607 insertions(+), 405 deletions(-)  create mode 100644 drivers/android/binder_latency_tracer.c
> > 
> > This series blows up the build into lots of tiny pieces, how was it
> > tested?
> > 
> 
> I am sorry that I had built pass.on the too older kernel, and some of
> api had been deprecated.
> I have fixed these errors in local, and I add the
> EXPORT_TRACEPOINT_SYMBOL for binder_latency_tracer to be ko needed.
> 
> Do I need to push a patch V8 or I provide the fixed code here ?

I need a whole new patch series, I dropped yours when it would not
compile properly.

thanks,

greg k-h

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v8] binder: transaction latency tracking for user build
  2020-09-07  7:00                                                       ` Greg Kroah-Hartman
@ 2020-09-07 12:00                                                         ` Frankie Chang
  2020-09-07 12:00                                                           ` [PATCH v8 1/3] binder: move structs from core file to header file Frankie Chang
                                                                             ` (3 more replies)
  0 siblings, 4 replies; 72+ messages in thread
From: Frankie Chang @ 2020-09-07 12:00 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

Change from v8:
  - change rtc_time_to_tm to rtc_time64_to_tm.
  - change timeval to __kernel_old_timeval due to 
    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c766d1472c70d25ad475cf56042af1652e792b23
  - export tracepoint symbol for binder_txn_latency_* which binder_transaction_latency_tracer to be ko needed.

Change from v7:
  - Use the passed-in values instead of accessing via t->from/to_proc/to_thread
    for trace_binder_txn_latency_free, when trace_binder_txn_latency_free_enable() return true.
  - make a helper function to do the above.

Change from v6:
  - change CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING type from bool to tristate
  - add comments to @timestamp and @tv under struct binder_transaction
  - make binder_txn_latency threshold configurable
  - enhance lock protection

Change from v5:
  - change config name to the proper one, CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING.
  - change tracepoint name to more descriptive one, trace_binder_txn_latency_(alloc|info|free)
  - enhance some lock protection.

Change from v4:
  - split up into patch series.

Change from v3:
  - use tracepoints for binder_update_info and print_binder_transaction_ext,
    instead of custom registration functions.

Change from v2:
  - create transaction latency module to monitor slow transaction.

Change from v1:
  - first patchset.


Frankie.Chang (3):
  binder: move structs from core file to header file
  binder: add trace at free transaction.
  binder: add transaction latency tracer

 drivers/android/Kconfig                 |   8 +
 drivers/android/Makefile                |   1 +
 drivers/android/binder.c                | 430 ++----------------------
 drivers/android/binder_internal.h       | 418 +++++++++++++++++++++++
 drivers/android/binder_latency_tracer.c | 112 ++++++
 drivers/android/binder_trace.h          |  49 +++
 6 files changed, 612 insertions(+), 406 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v8 1/3] binder: move structs from core file to header file
  2020-09-07 12:00                                                         ` [PATCH v8] " Frankie Chang
@ 2020-09-07 12:00                                                           ` Frankie Chang
  2020-09-07 12:00                                                           ` [PATCH v8 2/3] binder: add trace at free transaction Frankie Chang
                                                                             ` (2 subsequent siblings)
  3 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-09-07 12:00 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Frankie.Chang,
	Martijn Coenen, Christian Brauner, Todd Kjos

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Moving all structs to header file makes module more
extendable, and makes all these structs to be defined
in the same file.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
Acked-by: Todd Kjos <tkjos@google.com>
---
 drivers/android/binder.c          |  406 -------------------------------------
 drivers/android/binder_internal.h |  405 ++++++++++++++++++++++++++++++++++++
 2 files changed, 405 insertions(+), 406 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index f936530..943c49c 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -68,11 +68,9 @@
 #include <linux/sizes.h>
 
 #include <uapi/linux/android/binder.h>
-#include <uapi/linux/android/binderfs.h>
 
 #include <asm/cacheflush.h>
 
-#include "binder_alloc.h"
 #include "binder_internal.h"
 #include "binder_trace.h"
 
@@ -160,24 +158,6 @@ static int binder_set_stop_on_user_error(const char *val,
 #define to_binder_fd_array_object(hdr) \
 	container_of(hdr, struct binder_fd_array_object, hdr)
 
-enum binder_stat_types {
-	BINDER_STAT_PROC,
-	BINDER_STAT_THREAD,
-	BINDER_STAT_NODE,
-	BINDER_STAT_REF,
-	BINDER_STAT_DEATH,
-	BINDER_STAT_TRANSACTION,
-	BINDER_STAT_TRANSACTION_COMPLETE,
-	BINDER_STAT_COUNT
-};
-
-struct binder_stats {
-	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
-	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
-	atomic_t obj_created[BINDER_STAT_COUNT];
-	atomic_t obj_deleted[BINDER_STAT_COUNT];
-};
-
 static struct binder_stats binder_stats;
 
 static inline void binder_stats_deleted(enum binder_stat_types type)
@@ -213,278 +193,11 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
 	return e;
 }
 
-/**
- * struct binder_work - work enqueued on a worklist
- * @entry:             node enqueued on list
- * @type:              type of work to be performed
- *
- * There are separate work lists for proc, thread, and node (async).
- */
-struct binder_work {
-	struct list_head entry;
-
-	enum {
-		BINDER_WORK_TRANSACTION = 1,
-		BINDER_WORK_TRANSACTION_COMPLETE,
-		BINDER_WORK_RETURN_ERROR,
-		BINDER_WORK_NODE,
-		BINDER_WORK_DEAD_BINDER,
-		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
-		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
-	} type;
-};
-
-struct binder_error {
-	struct binder_work work;
-	uint32_t cmd;
-};
-
-/**
- * struct binder_node - binder node bookkeeping
- * @debug_id:             unique ID for debugging
- *                        (invariant after initialized)
- * @lock:                 lock for node fields
- * @work:                 worklist element for node work
- *                        (protected by @proc->inner_lock)
- * @rb_node:              element for proc->nodes tree
- *                        (protected by @proc->inner_lock)
- * @dead_node:            element for binder_dead_nodes list
- *                        (protected by binder_dead_nodes_lock)
- * @proc:                 binder_proc that owns this node
- *                        (invariant after initialized)
- * @refs:                 list of references on this node
- *                        (protected by @lock)
- * @internal_strong_refs: used to take strong references when
- *                        initiating a transaction
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_weak_refs:      weak user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_strong_refs:    strong user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @tmp_refs:             temporary kernel refs
- *                        (protected by @proc->inner_lock while @proc
- *                        is valid, and by binder_dead_nodes_lock
- *                        if @proc is NULL. During inc/dec and node release
- *                        it is also protected by @lock to provide safety
- *                        as the node dies and @proc becomes NULL)
- * @ptr:                  userspace pointer for node
- *                        (invariant, no lock needed)
- * @cookie:               userspace cookie for node
- *                        (invariant, no lock needed)
- * @has_strong_ref:       userspace notified of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_strong_ref:   userspace has acked notification of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_weak_ref:         userspace notified of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_weak_ref:     userspace has acked notification of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_async_transaction: async transaction to node in progress
- *                        (protected by @lock)
- * @accept_fds:           file descriptor operations supported for node
- *                        (invariant after initialized)
- * @min_priority:         minimum scheduling priority
- *                        (invariant after initialized)
- * @txn_security_ctx:     require sender's security context
- *                        (invariant after initialized)
- * @async_todo:           list of async work items
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder nodes.
- */
-struct binder_node {
-	int debug_id;
-	spinlock_t lock;
-	struct binder_work work;
-	union {
-		struct rb_node rb_node;
-		struct hlist_node dead_node;
-	};
-	struct binder_proc *proc;
-	struct hlist_head refs;
-	int internal_strong_refs;
-	int local_weak_refs;
-	int local_strong_refs;
-	int tmp_refs;
-	binder_uintptr_t ptr;
-	binder_uintptr_t cookie;
-	struct {
-		/*
-		 * bitfield elements protected by
-		 * proc inner_lock
-		 */
-		u8 has_strong_ref:1;
-		u8 pending_strong_ref:1;
-		u8 has_weak_ref:1;
-		u8 pending_weak_ref:1;
-	};
-	struct {
-		/*
-		 * invariant after initialization
-		 */
-		u8 accept_fds:1;
-		u8 txn_security_ctx:1;
-		u8 min_priority;
-	};
-	bool has_async_transaction;
-	struct list_head async_todo;
-};
-
-struct binder_ref_death {
-	/**
-	 * @work: worklist element for death notifications
-	 *        (protected by inner_lock of the proc that
-	 *        this ref belongs to)
-	 */
-	struct binder_work work;
-	binder_uintptr_t cookie;
-};
-
-/**
- * struct binder_ref_data - binder_ref counts and id
- * @debug_id:        unique ID for the ref
- * @desc:            unique userspace handle for ref
- * @strong:          strong ref count (debugging only if not locked)
- * @weak:            weak ref count (debugging only if not locked)
- *
- * Structure to hold ref count and ref id information. Since
- * the actual ref can only be accessed with a lock, this structure
- * is used to return information about the ref to callers of
- * ref inc/dec functions.
- */
-struct binder_ref_data {
-	int debug_id;
-	uint32_t desc;
-	int strong;
-	int weak;
-};
-
-/**
- * struct binder_ref - struct to track references on nodes
- * @data:        binder_ref_data containing id, handle, and current refcounts
- * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
- * @rb_node_node: node for lookup by @node in proc's rb_tree
- * @node_entry:  list entry for node->refs list in target node
- *               (protected by @node->lock)
- * @proc:        binder_proc containing ref
- * @node:        binder_node of target node. When cleaning up a
- *               ref for deletion in binder_cleanup_ref, a non-NULL
- *               @node indicates the node must be freed
- * @death:       pointer to death notification (ref_death) if requested
- *               (protected by @node->lock)
- *
- * Structure to track references from procA to target node (on procB). This
- * structure is unsafe to access without holding @proc->outer_lock.
- */
-struct binder_ref {
-	/* Lookups needed: */
-	/*   node + proc => ref (transaction) */
-	/*   desc + proc => ref (transaction, inc/dec ref) */
-	/*   node => refs + procs (proc exit) */
-	struct binder_ref_data data;
-	struct rb_node rb_node_desc;
-	struct rb_node rb_node_node;
-	struct hlist_node node_entry;
-	struct binder_proc *proc;
-	struct binder_node *node;
-	struct binder_ref_death *death;
-};
-
 enum binder_deferred_state {
 	BINDER_DEFERRED_FLUSH        = 0x01,
 	BINDER_DEFERRED_RELEASE      = 0x02,
 };
 
-/**
- * struct binder_proc - binder process bookkeeping
- * @proc_node:            element for binder_procs list
- * @threads:              rbtree of binder_threads in this proc
- *                        (protected by @inner_lock)
- * @nodes:                rbtree of binder nodes associated with
- *                        this proc ordered by node->ptr
- *                        (protected by @inner_lock)
- * @refs_by_desc:         rbtree of refs ordered by ref->desc
- *                        (protected by @outer_lock)
- * @refs_by_node:         rbtree of refs ordered by ref->node
- *                        (protected by @outer_lock)
- * @waiting_threads:      threads currently waiting for proc work
- *                        (protected by @inner_lock)
- * @pid                   PID of group_leader of process
- *                        (invariant after initialized)
- * @tsk                   task_struct for group_leader of process
- *                        (invariant after initialized)
- * @deferred_work_node:   element for binder_deferred_list
- *                        (protected by binder_deferred_lock)
- * @deferred_work:        bitmap of deferred work to perform
- *                        (protected by binder_deferred_lock)
- * @is_dead:              process is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @inner_lock)
- * @todo:                 list of work for this process
- *                        (protected by @inner_lock)
- * @stats:                per-process binder statistics
- *                        (atomics, no lock needed)
- * @delivered_death:      list of delivered death notification
- *                        (protected by @inner_lock)
- * @max_threads:          cap on number of binder threads
- *                        (protected by @inner_lock)
- * @requested_threads:    number of binder threads requested but not
- *                        yet started. In current implementation, can
- *                        only be 0 or 1.
- *                        (protected by @inner_lock)
- * @requested_threads_started: number binder threads started
- *                        (protected by @inner_lock)
- * @tmp_ref:              temporary reference to indicate proc is in use
- *                        (protected by @inner_lock)
- * @default_priority:     default scheduler priority
- *                        (invariant after initialized)
- * @debugfs_entry:        debugfs node
- * @alloc:                binder allocator bookkeeping
- * @context:              binder_context for this proc
- *                        (invariant after initialized)
- * @inner_lock:           can nest under outer_lock and/or node lock
- * @outer_lock:           no nesting under innor or node lock
- *                        Lock order: 1) outer, 2) node, 3) inner
- * @binderfs_entry:       process-specific binderfs log file
- *
- * Bookkeeping structure for binder processes
- */
-struct binder_proc {
-	struct hlist_node proc_node;
-	struct rb_root threads;
-	struct rb_root nodes;
-	struct rb_root refs_by_desc;
-	struct rb_root refs_by_node;
-	struct list_head waiting_threads;
-	int pid;
-	struct task_struct *tsk;
-	struct hlist_node deferred_work_node;
-	int deferred_work;
-	bool is_dead;
-
-	struct list_head todo;
-	struct binder_stats stats;
-	struct list_head delivered_death;
-	int max_threads;
-	int requested_threads;
-	int requested_threads_started;
-	int tmp_ref;
-	long default_priority;
-	struct dentry *debugfs_entry;
-	struct binder_alloc alloc;
-	struct binder_context *context;
-	spinlock_t inner_lock;
-	spinlock_t outer_lock;
-	struct dentry *binderfs_entry;
-};
-
 enum {
 	BINDER_LOOPER_STATE_REGISTERED  = 0x01,
 	BINDER_LOOPER_STATE_ENTERED     = 0x02,
@@ -495,125 +208,6 @@ enum {
 };
 
 /**
- * struct binder_thread - binder thread bookkeeping
- * @proc:                 binder process for this thread
- *                        (invariant after initialization)
- * @rb_node:              element for proc->threads rbtree
- *                        (protected by @proc->inner_lock)
- * @waiting_thread_node:  element for @proc->waiting_threads list
- *                        (protected by @proc->inner_lock)
- * @pid:                  PID for this thread
- *                        (invariant after initialization)
- * @looper:               bitmap of looping state
- *                        (only accessed by this thread)
- * @looper_needs_return:  looping thread needs to exit driver
- *                        (no lock needed)
- * @transaction_stack:    stack of in-progress transactions for this thread
- *                        (protected by @proc->inner_lock)
- * @todo:                 list of work to do for this thread
- *                        (protected by @proc->inner_lock)
- * @process_todo:         whether work in @todo should be processed
- *                        (protected by @proc->inner_lock)
- * @return_error:         transaction errors reported by this thread
- *                        (only accessed by this thread)
- * @reply_error:          transaction errors reported by target thread
- *                        (protected by @proc->inner_lock)
- * @wait:                 wait queue for thread work
- * @stats:                per-thread statistics
- *                        (atomics, no lock needed)
- * @tmp_ref:              temporary reference to indicate thread is in use
- *                        (atomic since @proc->inner_lock cannot
- *                        always be acquired)
- * @is_dead:              thread is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder threads.
- */
-struct binder_thread {
-	struct binder_proc *proc;
-	struct rb_node rb_node;
-	struct list_head waiting_thread_node;
-	int pid;
-	int looper;              /* only modified by this thread */
-	bool looper_need_return; /* can be written by other thread */
-	struct binder_transaction *transaction_stack;
-	struct list_head todo;
-	bool process_todo;
-	struct binder_error return_error;
-	struct binder_error reply_error;
-	wait_queue_head_t wait;
-	struct binder_stats stats;
-	atomic_t tmp_ref;
-	bool is_dead;
-};
-
-/**
- * struct binder_txn_fd_fixup - transaction fd fixup list element
- * @fixup_entry:          list entry
- * @file:                 struct file to be associated with new fd
- * @offset:               offset in buffer data to this fixup
- *
- * List element for fd fixups in a transaction. Since file
- * descriptors need to be allocated in the context of the
- * target process, we pass each fd to be processed in this
- * struct.
- */
-struct binder_txn_fd_fixup {
-	struct list_head fixup_entry;
-	struct file *file;
-	size_t offset;
-};
-
-struct binder_transaction {
-	int debug_id;
-	struct binder_work work;
-	struct binder_thread *from;
-	struct binder_transaction *from_parent;
-	struct binder_proc *to_proc;
-	struct binder_thread *to_thread;
-	struct binder_transaction *to_parent;
-	unsigned need_reply:1;
-	/* unsigned is_dead:1; */	/* not used at the moment */
-
-	struct binder_buffer *buffer;
-	unsigned int	code;
-	unsigned int	flags;
-	long	priority;
-	long	saved_priority;
-	kuid_t	sender_euid;
-	struct list_head fd_fixups;
-	binder_uintptr_t security_ctx;
-	/**
-	 * @lock:  protects @from, @to_proc, and @to_thread
-	 *
-	 * @from, @to_proc, and @to_thread can be set to NULL
-	 * during thread teardown
-	 */
-	spinlock_t lock;
-};
-
-/**
- * struct binder_object - union of flat binder object types
- * @hdr:   generic object header
- * @fbo:   binder object (nodes and refs)
- * @fdo:   file descriptor object
- * @bbo:   binder buffer pointer
- * @fdao:  file descriptor array
- *
- * Used for type-independent object copies
- */
-struct binder_object {
-	union {
-		struct binder_object_header hdr;
-		struct flat_binder_object fbo;
-		struct binder_fd_object fdo;
-		struct binder_buffer_object bbo;
-		struct binder_fd_array_object fdao;
-	};
-};
-
-/**
  * binder_proc_lock() - Acquire outer lock for given binder_proc
  * @proc:         struct binder_proc to acquire
  *
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index 283d3cb..872232f 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -12,6 +12,8 @@
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/uidgid.h>
+#include <uapi/linux/android/binderfs.h>
+#include "binder_alloc.h"
 
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
@@ -141,6 +143,409 @@ struct binder_transaction_log {
 	struct binder_transaction_log_entry entry[32];
 };
 
+enum binder_stat_types {
+	BINDER_STAT_PROC,
+	BINDER_STAT_THREAD,
+	BINDER_STAT_NODE,
+	BINDER_STAT_REF,
+	BINDER_STAT_DEATH,
+	BINDER_STAT_TRANSACTION,
+	BINDER_STAT_TRANSACTION_COMPLETE,
+	BINDER_STAT_COUNT
+};
+
+struct binder_stats {
+	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
+	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
+	atomic_t obj_created[BINDER_STAT_COUNT];
+	atomic_t obj_deleted[BINDER_STAT_COUNT];
+};
+
+/**
+ * struct binder_work - work enqueued on a worklist
+ * @entry:             node enqueued on list
+ * @type:              type of work to be performed
+ *
+ * There are separate work lists for proc, thread, and node (async).
+ */
+struct binder_work {
+	struct list_head entry;
+
+	enum {
+		BINDER_WORK_TRANSACTION = 1,
+		BINDER_WORK_TRANSACTION_COMPLETE,
+		BINDER_WORK_RETURN_ERROR,
+		BINDER_WORK_NODE,
+		BINDER_WORK_DEAD_BINDER,
+		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
+		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
+	} type;
+};
+
+struct binder_error {
+	struct binder_work work;
+	uint32_t cmd;
+};
+
+/* struct binder_node - binder node bookkeeping
+ * @debug_id:             unique ID for debugging
+ *                        (invariant after initialized)
+ * @lock:                 lock for node fields
+ * @work:                 worklist element for node work
+ *                        (protected by @proc->inner_lock)
+ * @rb_node:              element for proc->nodes tree
+ *                        (protected by @proc->inner_lock)
+ * @dead_node:            element for binder_dead_nodes list
+ *                        (protected by binder_dead_nodes_lock)
+ * @proc:                 binder_proc that owns this node
+ *                        (invariant after initialized)
+ * @refs:                 list of references on this node
+ *                        (protected by @lock)
+ * @internal_strong_refs: used to take strong references when
+ *                        initiating a transaction
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_weak_refs:      weak user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_strong_refs:    strong user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @tmp_refs:             temporary kernel refs
+ *                        (protected by @proc->inner_lock while @proc
+ *                        is valid, and by binder_dead_nodes_lock
+ *                        if @proc is NULL. During inc/dec and node release
+ *                        it is also protected by @lock to provide safety
+ *                        as the node dies and @proc becomes NULL)
+ * @ptr:                  userspace pointer for node
+ *                        (invariant, no lock needed)
+ * @cookie:               userspace cookie for node
+ *                        (invariant, no lock needed)
+ * @has_strong_ref:       userspace notified of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_strong_ref:   userspace has acked notification of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_weak_ref:         userspace notified of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_weak_ref:     userspace has acked notification of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_async_transaction: async transaction to node in progress
+ *                        (protected by @lock)
+ * @accept_fds:           file descriptor operations supported for node
+ *                        (invariant after initialized)
+ * @min_priority:         minimum scheduling priority
+ *                        (invariant after initialized)
+ * @txn_security_ctx:     require sender's security context
+ *                        (invariant after initialized)
+ * @async_todo:           list of async work items
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder nodes.
+ */
+struct binder_node {
+	int debug_id;
+	spinlock_t lock;
+	struct binder_work work;
+	union {
+		struct rb_node rb_node;
+		struct hlist_node dead_node;
+	};
+	struct binder_proc *proc;
+	struct hlist_head refs;
+	int internal_strong_refs;
+	int local_weak_refs;
+	int local_strong_refs;
+	int tmp_refs;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
+	struct {
+		/*
+		 * bitfield elements protected by
+		 * proc inner_lock
+		 */
+		u8 has_strong_ref:1;
+		u8 pending_strong_ref:1;
+		u8 has_weak_ref:1;
+		u8 pending_weak_ref:1;
+	};
+	struct {
+		/*
+		 * invariant after initialization
+		 */
+		u8 accept_fds:1;
+		u8 txn_security_ctx:1;
+		u8 min_priority;
+	};
+	bool has_async_transaction;
+	struct list_head async_todo;
+};
+
+struct binder_ref_death {
+	/**
+	 * @work: worklist element for death notifications
+	 *        (protected by inner_lock of the proc that
+	 *        this ref belongs to)
+	 */
+	struct binder_work work;
+	binder_uintptr_t cookie;
+};
+
+/**
+ * struct binder_ref_data - binder_ref counts and id
+ * @debug_id:        unique ID for the ref
+ * @desc:            unique userspace handle for ref
+ * @strong:          strong ref count (debugging only if not locked)
+ * @weak:            weak ref count (debugging only if not locked)
+ *
+ * Structure to hold ref count and ref id information. Since
+ * the actual ref can only be accessed with a lock, this structure
+ * is used to return information about the ref to callers of
+ * ref inc/dec functions.
+ */
+struct binder_ref_data {
+	int debug_id;
+	uint32_t desc;
+	int strong;
+	int weak;
+};
+
+/**
+ * struct binder_ref - struct to track references on nodes
+ * @data:        binder_ref_data containing id, handle, and current refcounts
+ * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
+ * @rb_node_node: node for lookup by @node in proc's rb_tree
+ * @node_entry:  list entry for node->refs list in target node
+ *               (protected by @node->lock)
+ * @proc:        binder_proc containing ref
+ * @node:        binder_node of target node. When cleaning up a
+ *               ref for deletion in binder_cleanup_ref, a non-NULL
+ *               @node indicates the node must be freed
+ * @death:       pointer to death notification (ref_death) if requested
+ *               (protected by @node->lock)
+ *
+ * Structure to track references from procA to target node (on procB). This
+ * structure is unsafe to access without holding @proc->outer_lock.
+ */
+struct binder_ref {
+	/* Lookups needed: */
+	/*   node + proc => ref (transaction) */
+	/*   desc + proc => ref (transaction, inc/dec ref) */
+	/*   node => refs + procs (proc exit) */
+	struct binder_ref_data data;
+	struct rb_node rb_node_desc;
+	struct rb_node rb_node_node;
+	struct hlist_node node_entry;
+	struct binder_proc *proc;
+	struct binder_node *node;
+	struct binder_ref_death *death;
+};
+
+/**
+ * struct binder_proc - binder process bookkeeping
+ * @proc_node:            element for binder_procs list
+ * @threads:              rbtree of binder_threads in this proc
+ *                        (protected by @inner_lock)
+ * @nodes:                rbtree of binder nodes associated with
+ *                        this proc ordered by node->ptr
+ *                        (protected by @inner_lock)
+ * @refs_by_desc:         rbtree of refs ordered by ref->desc
+ *                        (protected by @outer_lock)
+ * @refs_by_node:         rbtree of refs ordered by ref->node
+ *                        (protected by @outer_lock)
+ * @waiting_threads:      threads currently waiting for proc work
+ *                        (protected by @inner_lock)
+ * @pid                   PID of group_leader of process
+ *                        (invariant after initialized)
+ * @tsk                   task_struct for group_leader of process
+ *                        (invariant after initialized)
+ * @deferred_work_node:   element for binder_deferred_list
+ *                        (protected by binder_deferred_lock)
+ * @deferred_work:        bitmap of deferred work to perform
+ *                        (protected by binder_deferred_lock)
+ * @is_dead:              process is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @inner_lock)
+ * @todo:                 list of work for this process
+ *                        (protected by @inner_lock)
+ * @stats:                per-process binder statistics
+ *                        (atomics, no lock needed)
+ * @delivered_death:      list of delivered death notification
+ *                        (protected by @inner_lock)
+ * @max_threads:          cap on number of binder threads
+ *                        (protected by @inner_lock)
+ * @requested_threads:    number of binder threads requested but not
+ *                        yet started. In current implementation, can
+ *                        only be 0 or 1.
+ *                        (protected by @inner_lock)
+ * @requested_threads_started: number binder threads started
+ *                        (protected by @inner_lock)
+ * @tmp_ref:              temporary reference to indicate proc is in use
+ *                        (protected by @inner_lock)
+ * @default_priority:     default scheduler priority
+ *                        (invariant after initialized)
+ * @debugfs_entry:        debugfs node
+ * @alloc:                binder allocator bookkeeping
+ * @context:              binder_context for this proc
+ *                        (invariant after initialized)
+ * @inner_lock:           can nest under outer_lock and/or node lock
+ * @outer_lock:           no nesting under innor or node lock
+ *                        Lock order: 1) outer, 2) node, 3) inner
+ * @binderfs_entry:       process-specific binderfs log file
+ *
+ * Bookkeeping structure for binder processes
+ */
+struct binder_proc {
+	struct hlist_node proc_node;
+	struct rb_root threads;
+	struct rb_root nodes;
+	struct rb_root refs_by_desc;
+	struct rb_root refs_by_node;
+	struct list_head waiting_threads;
+	int pid;
+	struct task_struct *tsk;
+	struct hlist_node deferred_work_node;
+	int deferred_work;
+	bool is_dead;
+
+	struct list_head todo;
+	struct binder_stats stats;
+	struct list_head delivered_death;
+	int max_threads;
+	int requested_threads;
+	int requested_threads_started;
+	int tmp_ref;
+	long default_priority;
+	struct dentry *debugfs_entry;
+	struct binder_alloc alloc;
+	struct binder_context *context;
+	spinlock_t inner_lock;
+	spinlock_t outer_lock;
+	struct dentry *binderfs_entry;
+};
+
+/**
+ * struct binder_thread - binder thread bookkeeping
+ * @proc:                 binder process for this thread
+ *                        (invariant after initialization)
+ * @rb_node:              element for proc->threads rbtree
+ *                        (protected by @proc->inner_lock)
+ * @waiting_thread_node:  element for @proc->waiting_threads list
+ *                        (protected by @proc->inner_lock)
+ * @pid:                  PID for this thread
+ *                        (invariant after initialization)
+ * @looper:               bitmap of looping state
+ *                        (only accessed by this thread)
+ * @looper_needs_return:  looping thread needs to exit driver
+ *                        (no lock needed)
+ * @transaction_stack:    stack of in-progress transactions for this thread
+ *                        (protected by @proc->inner_lock)
+ * @todo:                 list of work to do for this thread
+ *                        (protected by @proc->inner_lock)
+ * @process_todo:         whether work in @todo should be processed
+ *                        (protected by @proc->inner_lock)
+ * @return_error:         transaction errors reported by this thread
+ *                        (only accessed by this thread)
+ * @reply_error:          transaction errors reported by target thread
+ *                        (protected by @proc->inner_lock)
+ * @wait:                 wait queue for thread work
+ * @stats:                per-thread statistics
+ *                        (atomics, no lock needed)
+ * @tmp_ref:              temporary reference to indicate thread is in use
+ *                        (atomic since @proc->inner_lock cannot
+ *                        always be acquired)
+ * @is_dead:              thread is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder threads.
+ */
+struct binder_thread {
+	struct binder_proc *proc;
+	struct rb_node rb_node;
+	struct list_head waiting_thread_node;
+	int pid;
+	int looper;              /* only modified by this thread */
+	bool looper_need_return; /* can be written by other thread */
+	struct binder_transaction *transaction_stack;
+	struct list_head todo;
+	bool process_todo;
+	struct binder_error return_error;
+	struct binder_error reply_error;
+	wait_queue_head_t wait;
+	struct binder_stats stats;
+	atomic_t tmp_ref;
+	bool is_dead;
+};
+
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry:          list entry
+ * @file:                 struct file to be associated with new fd
+ * @offset:               offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+	struct list_head fixup_entry;
+	struct file *file;
+	size_t offset;
+};
+
+struct binder_transaction {
+	int debug_id;
+	struct binder_work work;
+	struct binder_thread *from;
+	struct binder_transaction *from_parent;
+	struct binder_proc *to_proc;
+	struct binder_thread *to_thread;
+	struct binder_transaction *to_parent;
+	unsigned need_reply:1;
+	/* unsigned is_dead:1; */       /* not used at the moment */
+
+	struct binder_buffer *buffer;
+	unsigned int    code;
+	unsigned int    flags;
+	long    priority;
+	long    saved_priority;
+	kuid_t  sender_euid;
+	struct list_head fd_fixups;
+	binder_uintptr_t security_ctx;
+	/**
+	 * @lock:  protects @from, @to_proc, and @to_thread
+	 *
+	 * @from, @to_proc, and @to_thread can be set to NULL
+	 * during thread teardown
+	 */
+	spinlock_t lock;
+};
+
+/**
+ * struct binder_object - union of flat binder object types
+ * @hdr:   generic object header
+ * @fbo:   binder object (nodes and refs)
+ * @fdo:   file descriptor object
+ * @bbo:   binder buffer pointer
+ * @fdao:  file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+	union {
+		struct binder_object_header hdr;
+		struct flat_binder_object fbo;
+		struct binder_fd_object fdo;
+		struct binder_buffer_object bbo;
+		struct binder_fd_array_object fdao;
+	};
+};
+
 extern struct binder_transaction_log binder_transaction_log;
 extern struct binder_transaction_log binder_transaction_log_failed;
 #endif /* _LINUX_BINDER_INTERNAL_H */
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v8 2/3] binder: add trace at free transaction.
  2020-09-07 12:00                                                         ` [PATCH v8] " Frankie Chang
  2020-09-07 12:00                                                           ` [PATCH v8 1/3] binder: move structs from core file to header file Frankie Chang
@ 2020-09-07 12:00                                                           ` Frankie Chang
  2020-09-07 12:00                                                           ` [PATCH v8 3/3] binder: add transaction latency tracer Frankie Chang
  2020-09-07 12:24                                                           ` [PATCH v8] " Greg Kroah-Hartman
  3 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-09-07 12:00 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Frankie.Chang,
	Martijn Coenen, Christian Brauner, Todd Kjos

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Since the original trace_binder_transaction_received cannot
precisely present the real finished time of transaction, adding a
trace_binder_txn_latency_free at the point of free transaction
may be more close to it.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
Acked-by: Todd Kjos <tkjos@google.com>
---
 drivers/android/binder.c       |   18 ++++++++++++++++++
 drivers/android/binder_trace.h |   29 +++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 943c49c..0cab900 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1507,6 +1507,20 @@ static void binder_free_txn_fixups(struct binder_transaction *t)
 	}
 }
 
+static void binder_txn_latency_free(struct binder_transaction *t)
+{
+	int from_proc, from_thread, to_proc, to_thread;
+
+	spin_lock(&t->lock);
+	from_proc = t->from ? t->from->proc->pid : 0;
+	from_thread = t->from ? t->from->pid : 0;
+	to_proc = t->to_proc ? t->to_proc->pid : 0;
+	to_thread = t->to_thread ? t->to_thread->pid : 0;
+	spin_unlock(&t->lock);
+
+	trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc, to_thread);
+}
+
 static void binder_free_transaction(struct binder_transaction *t)
 {
 	struct binder_proc *target_proc = t->to_proc;
@@ -1517,6 +1531,8 @@ static void binder_free_transaction(struct binder_transaction *t)
 			t->buffer->transaction = NULL;
 		binder_inner_proc_unlock(target_proc);
 	}
+	if (trace_binder_txn_latency_free_enabled())
+		binder_txn_latency_free(t);
 	/*
 	 * If the transaction has no target_proc, then
 	 * t->buffer->transaction has already been cleared.
@@ -3096,6 +3112,8 @@ static void binder_transaction(struct binder_proc *proc,
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 err_alloc_tcomplete_failed:
+	if (trace_binder_txn_latency_free_enabled())
+		binder_txn_latency_free(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
 err_alloc_t_failed:
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 6731c3c..8eeccdc 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,35 @@
 		  __entry->thread_todo)
 );
 
+TRACE_EVENT(binder_txn_latency_free,
+	TP_PROTO(struct binder_transaction *t,
+		 int from_proc, int from_thread,
+		 int to_proc, int to_thread),
+	TP_ARGS(t, from_proc, from_thread, to_proc, to_thread),
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, from_proc)
+		__field(int, from_thread)
+		__field(int, to_proc)
+		__field(int, to_thread)
+		__field(unsigned int, code)
+		__field(unsigned int, flags)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->from_proc = from_proc;
+		__entry->from_thread = from_thread;
+		__entry->to_proc = to_proc;
+		__entry->to_thread = to_thread;
+		__entry->code = t->code;
+		__entry->flags = t->flags;
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
+		  __entry->to_proc, __entry->to_thread, __entry->code,
+		  __entry->flags)
+);
+
 TRACE_EVENT(binder_transaction,
 	TP_PROTO(bool reply, struct binder_transaction *t,
 		 struct binder_node *target_node),
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v8 3/3] binder: add transaction latency tracer
  2020-09-07 12:00                                                         ` [PATCH v8] " Frankie Chang
  2020-09-07 12:00                                                           ` [PATCH v8 1/3] binder: move structs from core file to header file Frankie Chang
  2020-09-07 12:00                                                           ` [PATCH v8 2/3] binder: add trace at free transaction Frankie Chang
@ 2020-09-07 12:00                                                           ` Frankie Chang
  2020-09-07 12:25                                                             ` Greg Kroah-Hartman
  2020-09-07 12:24                                                           ` [PATCH v8] " Greg Kroah-Hartman
  3 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-09-07 12:00 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Frankie.Chang,
	Martijn Coenen, Christian Brauner, Todd Kjos

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Record start/end timestamp for binder transaction.
When transaction is completed or transaction is free,
it would be checked if transaction latency over threshold
(default 2 sec), if yes, printing related information for tracing.

/* Implement details */
- Add latency tracer module to monitor transaction
  by attaching to new tracepoints introduced
  when transactions are allocated and freed.
  The trace_binder_txn_latency_free would not be enabled
  by default. Monitoring which transaction is too slow to
  cause some of exceptions is important. So we hook the
  tracepoint to call the monitor function.

- Since some of modules would trigger timeout NE
  if their binder transaction don't finish in time,
  such as audio timeout (5 sec), even BT command
  timeout (2 sec), etc.
  Therefore, setting the timeout threshold as default
  2 seconds could be helpful to debug.
  But this timeout threshold is configurable, to let
  all users determine the more suitable threshold.

- The reason why printing the related information to
  kernel information log but not trace buffer is that
  some abnormal transactions may be pending for a long
  time ago, they could not be recorded due to buffer
  limited.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
Acked-by: Todd Kjos <tkjos@google.com>
---
 drivers/android/Kconfig                 |    8 +++
 drivers/android/Makefile                |    1 +
 drivers/android/binder.c                |    6 ++
 drivers/android/binder_internal.h       |   13 ++++
 drivers/android/binder_latency_tracer.c |  112 +++++++++++++++++++++++++++++++
 drivers/android/binder_trace.h          |   26 ++++++-
 6 files changed, 163 insertions(+), 3 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 53b22e2..8aadaf4 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
 	  exhaustively with combinations of various buffer sizes and
 	  alignments.
 
+config BINDER_TRANSACTION_LATENCY_TRACKING
+	tristate "Android Binder transaction tracking"
+	help
+	  Used for track abnormal binder transaction which is over threshold,
+	  when the transaction is done or be free, this transaction would be
+	  checked whether it executed overtime.
+	  If yes, printing out the detailed info.
+
 endif # if ANDROID
 
 endmenu
diff --git a/drivers/android/Makefile b/drivers/android/Makefile
index c9d3d0c9..c2ffdb6 100644
--- a/drivers/android/Makefile
+++ b/drivers/android/Makefile
@@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
 obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
 obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
 obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
+obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)	+= binder_latency_tracer.o
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 0cab900..65ad38c 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2674,6 +2674,7 @@ static void binder_transaction(struct binder_proc *proc,
 		return_error_line = __LINE__;
 		goto err_alloc_t_failed;
 	}
+	trace_binder_txn_latency_alloc(t);
 	INIT_LIST_HEAD(&t->fd_fixups);
 	binder_stats_created(BINDER_STAT_TRANSACTION);
 	spin_lock_init(&t->lock);
@@ -5177,6 +5178,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
 		   to_proc ? to_proc->pid : 0,
 		   t->to_thread ? t->to_thread->pid : 0,
 		   t->code, t->flags, t->priority, t->need_reply);
+	trace_binder_txn_latency_info(m, t);
 	spin_unlock(&t->lock);
 
 	if (proc != to_proc) {
@@ -5818,4 +5820,8 @@ static int __init binder_init(void)
 #define CREATE_TRACE_POINTS
 #include "binder_trace.h"
 
+EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_alloc);
+EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_info);
+EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_free);
+
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index 872232f..309d1b10 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -15,6 +15,11 @@
 #include <uapi/linux/android/binderfs.h>
 #include "binder_alloc.h"
 
+#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
+#include <uapi/linux/time_types.h>
+#include <linux/rtc.h>
+#endif
+
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
 	struct mutex context_mgr_node_lock;
@@ -524,6 +529,14 @@ struct binder_transaction {
 	 * during thread teardown
 	 */
 	spinlock_t lock;
+	/**
+	 * @timestamp and @tv are used to record the time
+	 * that the binder transaction startup
+	 */
+#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
+	struct timespec64 timestamp;
+	struct __kernel_old_timeval tv;
+#endif
 };
 
 /**
diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
new file mode 100644
index 0000000..b29b26f
--- /dev/null
+++ b/drivers/android/binder_latency_tracer.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ */
+
+#include <linux/module.h>
+#include <uapi/linux/android/binder.h>
+#include "binder_internal.h"
+#include "binder_trace.h"
+
+/**
+ * The reason setting the binder_txn_latency_threshold to 2 sec
+ * is that most of timeout abort is greater or equal to 2 sec.
+ * Making it configurable to let all users determine which
+ * threshold is more suitable.
+ */
+static uint32_t binder_txn_latency_threshold = 2;
+module_param_named(threshold, binder_txn_latency_threshold,
+			uint, 0644);
+
+/*
+ * probe_binder_txn_latency_free - Output info of a delay transaction
+ * @t:          pointer to the over-time transaction
+ */
+void probe_binder_txn_latency_free(void *ignore, struct binder_transaction *t,
+					int from_proc, int from_thread,
+					int to_proc, int to_thread)
+{
+	struct rtc_time tm;
+	struct timespec64 *startime;
+	struct timespec64 cur, sub_t;
+
+	ktime_get_ts64(&cur);
+	startime = &t->timestamp;
+	sub_t = timespec64_sub(cur, *startime);
+
+	/* if transaction time is over than binder_txn_latency_threshold (sec),
+	 * show timeout warning log.
+	 */
+	if (sub_t.tv_sec < binder_txn_latency_threshold)
+		return;
+
+	rtc_time64_to_tm(t->tv.tv_sec, &tm);
+
+	pr_info_ratelimited("%d: from %d:%d to %d:%d",
+			t->debug_id, from_proc, from_thread,
+			to_proc, to_thread);
+
+	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
+			(unsigned int)sub_t.tv_sec,
+			(sub_t.tv_nsec / NSEC_PER_MSEC),
+			t->code,
+			(unsigned long)startime->tv_sec,
+			(startime->tv_nsec / NSEC_PER_MSEC),
+			(tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+			tm.tm_hour, tm.tm_min, tm.tm_sec,
+			(unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+
+static void probe_binder_txn_latency_alloc(void *ignore,
+					struct binder_transaction *t)
+{
+	struct timespec64 now;
+
+	ktime_get_ts64(&t->timestamp);
+	ktime_get_real_ts64(&now);
+	t->tv.tv_sec = now.tv_sec;
+	t->tv.tv_sec -= (sys_tz.tz_minuteswest * 60);
+	t->tv.tv_usec = now.tv_nsec/1000;
+}
+
+static void probe_binder_txn_latency_info(void *ignore, struct seq_file *m,
+					struct binder_transaction *t)
+{
+	struct rtc_time tm;
+
+	rtc_time64_to_tm(t->tv.tv_sec, &tm);
+	seq_printf(m,
+		   " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
+		   (unsigned long)t->timestamp.tv_sec,
+		   (t->timestamp.tv_nsec / NSEC_PER_USEC),
+		   (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+		   tm.tm_hour, tm.tm_min, tm.tm_sec,
+		   (unsigned long)(t->tv.tv_usec / USEC_PER_MSEC));
+}
+
+static int __init init_binder_latency_tracer(void)
+{
+	register_trace_binder_txn_latency_free(
+			probe_binder_txn_latency_free, NULL);
+	register_trace_binder_txn_latency_alloc(
+			probe_binder_txn_latency_alloc, NULL);
+	register_trace_binder_txn_latency_info(
+			probe_binder_txn_latency_info, NULL);
+
+	return 0;
+}
+
+static void exit_binder_latency_tracer(void)
+{
+	unregister_trace_binder_txn_latency_free(
+			probe_binder_txn_latency_free, NULL);
+	unregister_trace_binder_txn_latency_alloc(
+			probe_binder_txn_latency_alloc, NULL);
+	unregister_trace_binder_txn_latency_info(
+			probe_binder_txn_latency_info, NULL);
+}
+
+module_init(init_binder_latency_tracer);
+module_exit(exit_binder_latency_tracer);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 8eeccdc..f1bbff4 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,17 @@
 		  __entry->thread_todo)
 );
 
+DECLARE_TRACE(binder_txn_latency_alloc,
+	TP_PROTO(struct binder_transaction *t),
+	TP_ARGS(t)
+);
+
+DECLARE_TRACE(binder_txn_latency_info,
+	TP_PROTO(struct seq_file *m,
+		 struct binder_transaction *t),
+	TP_ARGS(m, t)
+);
+
 TRACE_EVENT(binder_txn_latency_free,
 	TP_PROTO(struct binder_transaction *t,
 		 int from_proc, int from_thread,
@@ -108,6 +119,8 @@
 		__field(int, to_thread)
 		__field(unsigned int, code)
 		__field(unsigned int, flags)
+		__field(unsigned long, start_sec)
+		__field(unsigned long, start_nsec)
 	),
 	TP_fast_assign(
 		__entry->debug_id = t->debug_id;
@@ -117,11 +130,18 @@
 		__entry->to_thread = to_thread;
 		__entry->code = t->code;
 		__entry->flags = t->flags;
-	),
-	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
+		__entry->start_sec = t->timestamp.tv_sec;
+		__entry->start_nsec = t->timestamp.tv_nsec / NSEC_PER_MSEC;
+#else
+		__entry->start_sec = 0;
+		__entry->start_nsec = 0;
+#endif
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
 		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
 		  __entry->to_proc, __entry->to_thread, __entry->code,
-		  __entry->flags)
+		  __entry->flags, __entry->start_sec, __entry->start_nsec)
 );
 
 TRACE_EVENT(binder_transaction,
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v8] binder: transaction latency tracking for user build
  2020-09-07 12:00                                                         ` [PATCH v8] " Frankie Chang
                                                                             ` (2 preceding siblings ...)
  2020-09-07 12:00                                                           ` [PATCH v8 3/3] binder: add transaction latency tracer Frankie Chang
@ 2020-09-07 12:24                                                           ` Greg Kroah-Hartman
  3 siblings, 0 replies; 72+ messages in thread
From: Greg Kroah-Hartman @ 2020-09-07 12:24 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Mon, Sep 07, 2020 at 08:00:52PM +0800, Frankie Chang wrote:
> Change from v8:
>   - change rtc_time_to_tm to rtc_time64_to_tm.
>   - change timeval to __kernel_old_timeval due to 
>     https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c766d1472c70d25ad475cf56042af1652e792b23

That feels wrong, why can't you use the "new" structure instead?

thanks,

greg k-h

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v8 3/3] binder: add transaction latency tracer
  2020-09-07 12:00                                                           ` [PATCH v8 3/3] binder: add transaction latency tracer Frankie Chang
@ 2020-09-07 12:25                                                             ` Greg Kroah-Hartman
  2020-09-07 13:51                                                               ` Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Greg Kroah-Hartman @ 2020-09-07 12:25 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Mon, Sep 07, 2020 at 08:00:55PM +0800, Frankie Chang wrote:
> From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
> 
> Record start/end timestamp for binder transaction.
> When transaction is completed or transaction is free,
> it would be checked if transaction latency over threshold
> (default 2 sec), if yes, printing related information for tracing.
> 
> /* Implement details */
> - Add latency tracer module to monitor transaction
>   by attaching to new tracepoints introduced
>   when transactions are allocated and freed.
>   The trace_binder_txn_latency_free would not be enabled
>   by default. Monitoring which transaction is too slow to
>   cause some of exceptions is important. So we hook the
>   tracepoint to call the monitor function.
> 
> - Since some of modules would trigger timeout NE
>   if their binder transaction don't finish in time,
>   such as audio timeout (5 sec), even BT command
>   timeout (2 sec), etc.
>   Therefore, setting the timeout threshold as default
>   2 seconds could be helpful to debug.
>   But this timeout threshold is configurable, to let
>   all users determine the more suitable threshold.
> 
> - The reason why printing the related information to
>   kernel information log but not trace buffer is that
>   some abnormal transactions may be pending for a long
>   time ago, they could not be recorded due to buffer
>   limited.
> 
> Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> Acked-by: Todd Kjos <tkjos@google.com>
> ---
>  drivers/android/Kconfig                 |    8 +++
>  drivers/android/Makefile                |    1 +
>  drivers/android/binder.c                |    6 ++
>  drivers/android/binder_internal.h       |   13 ++++
>  drivers/android/binder_latency_tracer.c |  112 +++++++++++++++++++++++++++++++
>  drivers/android/binder_trace.h          |   26 ++++++-
>  6 files changed, 163 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/android/binder_latency_tracer.c
> 
> diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> index 53b22e2..8aadaf4 100644
> --- a/drivers/android/Kconfig
> +++ b/drivers/android/Kconfig
> @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
>  	  exhaustively with combinations of various buffer sizes and
>  	  alignments.
>  
> +config BINDER_TRANSACTION_LATENCY_TRACKING
> +	tristate "Android Binder transaction tracking"
> +	help
> +	  Used for track abnormal binder transaction which is over threshold,
> +	  when the transaction is done or be free, this transaction would be
> +	  checked whether it executed overtime.
> +	  If yes, printing out the detailed info.
> +
>  endif # if ANDROID
>  
>  endmenu
> diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> index c9d3d0c9..c2ffdb6 100644
> --- a/drivers/android/Makefile
> +++ b/drivers/android/Makefile
> @@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
>  obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
>  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> +obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)	+= binder_latency_tracer.o
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index 0cab900..65ad38c 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -2674,6 +2674,7 @@ static void binder_transaction(struct binder_proc *proc,
>  		return_error_line = __LINE__;
>  		goto err_alloc_t_failed;
>  	}
> +	trace_binder_txn_latency_alloc(t);
>  	INIT_LIST_HEAD(&t->fd_fixups);
>  	binder_stats_created(BINDER_STAT_TRANSACTION);
>  	spin_lock_init(&t->lock);
> @@ -5177,6 +5178,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
>  		   to_proc ? to_proc->pid : 0,
>  		   t->to_thread ? t->to_thread->pid : 0,
>  		   t->code, t->flags, t->priority, t->need_reply);
> +	trace_binder_txn_latency_info(m, t);
>  	spin_unlock(&t->lock);
>  
>  	if (proc != to_proc) {
> @@ -5818,4 +5820,8 @@ static int __init binder_init(void)
>  #define CREATE_TRACE_POINTS
>  #include "binder_trace.h"
>  
> +EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_alloc);
> +EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_info);
> +EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_free);
> +
>  MODULE_LICENSE("GPL v2");
> diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> index 872232f..309d1b10 100644
> --- a/drivers/android/binder_internal.h
> +++ b/drivers/android/binder_internal.h
> @@ -15,6 +15,11 @@
>  #include <uapi/linux/android/binderfs.h>
>  #include "binder_alloc.h"
>  
> +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> +#include <uapi/linux/time_types.h>
> +#include <linux/rtc.h>
> +#endif
> +
>  struct binder_context {
>  	struct binder_node *binder_context_mgr_node;
>  	struct mutex context_mgr_node_lock;
> @@ -524,6 +529,14 @@ struct binder_transaction {
>  	 * during thread teardown
>  	 */
>  	spinlock_t lock;
> +	/**
> +	 * @timestamp and @tv are used to record the time
> +	 * that the binder transaction startup
> +	 */
> +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> +	struct timespec64 timestamp;
> +	struct __kernel_old_timeval tv;

As I stated in the 0/3 email, please use the correct in-kernel structure
for this.  That structure is _ONLY_ for old userspace api compatibility
issues.  Which is not the case here at all.

thanks,

greg k-h

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v8 3/3] binder: add transaction latency tracer
  2020-09-07 12:25                                                             ` Greg Kroah-Hartman
@ 2020-09-07 13:51                                                               ` Frankie Chang
  2020-09-07 14:09                                                                 ` Greg Kroah-Hartman
  0 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-09-07 13:51 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Mon, 2020-09-07 at 14:25 +0200, Greg Kroah-Hartman wrote:
> On Mon, Sep 07, 2020 at 08:00:55PM +0800, Frankie Chang wrote:
> > From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
> > 
> > Record start/end timestamp for binder transaction.
> > When transaction is completed or transaction is free,
> > it would be checked if transaction latency over threshold
> > (default 2 sec), if yes, printing related information for tracing.
> > 
> > /* Implement details */
> > - Add latency tracer module to monitor transaction
> >   by attaching to new tracepoints introduced
> >   when transactions are allocated and freed.
> >   The trace_binder_txn_latency_free would not be enabled
> >   by default. Monitoring which transaction is too slow to
> >   cause some of exceptions is important. So we hook the
> >   tracepoint to call the monitor function.
> > 
> > - Since some of modules would trigger timeout NE
> >   if their binder transaction don't finish in time,
> >   such as audio timeout (5 sec), even BT command
> >   timeout (2 sec), etc.
> >   Therefore, setting the timeout threshold as default
> >   2 seconds could be helpful to debug.
> >   But this timeout threshold is configurable, to let
> >   all users determine the more suitable threshold.
> > 
> > - The reason why printing the related information to
> >   kernel information log but not trace buffer is that
> >   some abnormal transactions may be pending for a long
> >   time ago, they could not be recorded due to buffer
> >   limited.
> > 
> > Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> > Acked-by: Todd Kjos <tkjos@google.com>
> > ---
> >  drivers/android/Kconfig                 |    8 +++
> >  drivers/android/Makefile                |    1 +
> >  drivers/android/binder.c                |    6 ++
> >  drivers/android/binder_internal.h       |   13 ++++
> >  drivers/android/binder_latency_tracer.c |  112 +++++++++++++++++++++++++++++++
> >  drivers/android/binder_trace.h          |   26 ++++++-
> >  6 files changed, 163 insertions(+), 3 deletions(-)
> >  create mode 100644 drivers/android/binder_latency_tracer.c
> > 
> > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > index 53b22e2..8aadaf4 100644
> > --- a/drivers/android/Kconfig
> > +++ b/drivers/android/Kconfig
> > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> >  	  exhaustively with combinations of various buffer sizes and
> >  	  alignments.
> >  
> > +config BINDER_TRANSACTION_LATENCY_TRACKING
> > +	tristate "Android Binder transaction tracking"
> > +	help
> > +	  Used for track abnormal binder transaction which is over threshold,
> > +	  when the transaction is done or be free, this transaction would be
> > +	  checked whether it executed overtime.
> > +	  If yes, printing out the detailed info.
> > +
> >  endif # if ANDROID
> >  
> >  endmenu
> > diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> > index c9d3d0c9..c2ffdb6 100644
> > --- a/drivers/android/Makefile
> > +++ b/drivers/android/Makefile
> > @@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
> >  obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
> >  obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
> >  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> > +obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)	+= binder_latency_tracer.o
> > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > index 0cab900..65ad38c 100644
> > --- a/drivers/android/binder.c
> > +++ b/drivers/android/binder.c
> > @@ -2674,6 +2674,7 @@ static void binder_transaction(struct binder_proc *proc,
> >  		return_error_line = __LINE__;
> >  		goto err_alloc_t_failed;
> >  	}
> > +	trace_binder_txn_latency_alloc(t);
> >  	INIT_LIST_HEAD(&t->fd_fixups);
> >  	binder_stats_created(BINDER_STAT_TRANSACTION);
> >  	spin_lock_init(&t->lock);
> > @@ -5177,6 +5178,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
> >  		   to_proc ? to_proc->pid : 0,
> >  		   t->to_thread ? t->to_thread->pid : 0,
> >  		   t->code, t->flags, t->priority, t->need_reply);
> > +	trace_binder_txn_latency_info(m, t);
> >  	spin_unlock(&t->lock);
> >  
> >  	if (proc != to_proc) {
> > @@ -5818,4 +5820,8 @@ static int __init binder_init(void)
> >  #define CREATE_TRACE_POINTS
> >  #include "binder_trace.h"
> >  
> > +EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_alloc);
> > +EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_info);
> > +EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_free);
> > +
> >  MODULE_LICENSE("GPL v2");
> > diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> > index 872232f..309d1b10 100644
> > --- a/drivers/android/binder_internal.h
> > +++ b/drivers/android/binder_internal.h
> > @@ -15,6 +15,11 @@
> >  #include <uapi/linux/android/binderfs.h>
> >  #include "binder_alloc.h"
> >  
> > +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> > +#include <uapi/linux/time_types.h>
> > +#include <linux/rtc.h>
> > +#endif
> > +
> >  struct binder_context {
> >  	struct binder_node *binder_context_mgr_node;
> >  	struct mutex context_mgr_node_lock;
> > @@ -524,6 +529,14 @@ struct binder_transaction {
> >  	 * during thread teardown
> >  	 */
> >  	spinlock_t lock;
> > +	/**
> > +	 * @timestamp and @tv are used to record the time
> > +	 * that the binder transaction startup
> > +	 */
> > +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> > +	struct timespec64 timestamp;
> > +	struct __kernel_old_timeval tv;
> 
> As I stated in the 0/3 email, please use the correct in-kernel structure
> for this.  That structure is _ONLY_ for old userspace api compatibility
> issues.  Which is not the case here at all.
> 
> thanks,
> greg k-h

Since it's not proper to use timeval & __kernel_old_timeval.
The remaining structure with tv_usec that I found is
__kernel_timex_timeval, but I'm not sure if this is proper one or not.
All I can see is in
https://lwn.net/ml/linux-kernel/20180705213604.18883-6-deepa.kernel@gmail.com/

I'm afraid of using wrong structure again.
Could you give me some advices about this?

Or is there another suitable way to replace timeval

Many thanks,
Frankie



_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v8 3/3] binder: add transaction latency tracer
  2020-09-07 13:51                                                               ` Frankie Chang
@ 2020-09-07 14:09                                                                 ` Greg Kroah-Hartman
  2020-09-08  5:38                                                                   ` Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Greg Kroah-Hartman @ 2020-09-07 14:09 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Mon, Sep 07, 2020 at 09:51:15PM +0800, Frankie Chang wrote:
> On Mon, 2020-09-07 at 14:25 +0200, Greg Kroah-Hartman wrote:
> > On Mon, Sep 07, 2020 at 08:00:55PM +0800, Frankie Chang wrote:
> > > From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
> > > 
> > > Record start/end timestamp for binder transaction.
> > > When transaction is completed or transaction is free,
> > > it would be checked if transaction latency over threshold
> > > (default 2 sec), if yes, printing related information for tracing.
> > > 
> > > /* Implement details */
> > > - Add latency tracer module to monitor transaction
> > >   by attaching to new tracepoints introduced
> > >   when transactions are allocated and freed.
> > >   The trace_binder_txn_latency_free would not be enabled
> > >   by default. Monitoring which transaction is too slow to
> > >   cause some of exceptions is important. So we hook the
> > >   tracepoint to call the monitor function.
> > > 
> > > - Since some of modules would trigger timeout NE
> > >   if their binder transaction don't finish in time,
> > >   such as audio timeout (5 sec), even BT command
> > >   timeout (2 sec), etc.
> > >   Therefore, setting the timeout threshold as default
> > >   2 seconds could be helpful to debug.
> > >   But this timeout threshold is configurable, to let
> > >   all users determine the more suitable threshold.
> > > 
> > > - The reason why printing the related information to
> > >   kernel information log but not trace buffer is that
> > >   some abnormal transactions may be pending for a long
> > >   time ago, they could not be recorded due to buffer
> > >   limited.
> > > 
> > > Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> > > Acked-by: Todd Kjos <tkjos@google.com>
> > > ---
> > >  drivers/android/Kconfig                 |    8 +++
> > >  drivers/android/Makefile                |    1 +
> > >  drivers/android/binder.c                |    6 ++
> > >  drivers/android/binder_internal.h       |   13 ++++
> > >  drivers/android/binder_latency_tracer.c |  112 +++++++++++++++++++++++++++++++
> > >  drivers/android/binder_trace.h          |   26 ++++++-
> > >  6 files changed, 163 insertions(+), 3 deletions(-)
> > >  create mode 100644 drivers/android/binder_latency_tracer.c
> > > 
> > > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > > index 53b22e2..8aadaf4 100644
> > > --- a/drivers/android/Kconfig
> > > +++ b/drivers/android/Kconfig
> > > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> > >  	  exhaustively with combinations of various buffer sizes and
> > >  	  alignments.
> > >  
> > > +config BINDER_TRANSACTION_LATENCY_TRACKING
> > > +	tristate "Android Binder transaction tracking"
> > > +	help
> > > +	  Used for track abnormal binder transaction which is over threshold,
> > > +	  when the transaction is done or be free, this transaction would be
> > > +	  checked whether it executed overtime.
> > > +	  If yes, printing out the detailed info.
> > > +
> > >  endif # if ANDROID
> > >  
> > >  endmenu
> > > diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> > > index c9d3d0c9..c2ffdb6 100644
> > > --- a/drivers/android/Makefile
> > > +++ b/drivers/android/Makefile
> > > @@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
> > >  obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
> > >  obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
> > >  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> > > +obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)	+= binder_latency_tracer.o
> > > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > > index 0cab900..65ad38c 100644
> > > --- a/drivers/android/binder.c
> > > +++ b/drivers/android/binder.c
> > > @@ -2674,6 +2674,7 @@ static void binder_transaction(struct binder_proc *proc,
> > >  		return_error_line = __LINE__;
> > >  		goto err_alloc_t_failed;
> > >  	}
> > > +	trace_binder_txn_latency_alloc(t);
> > >  	INIT_LIST_HEAD(&t->fd_fixups);
> > >  	binder_stats_created(BINDER_STAT_TRANSACTION);
> > >  	spin_lock_init(&t->lock);
> > > @@ -5177,6 +5178,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
> > >  		   to_proc ? to_proc->pid : 0,
> > >  		   t->to_thread ? t->to_thread->pid : 0,
> > >  		   t->code, t->flags, t->priority, t->need_reply);
> > > +	trace_binder_txn_latency_info(m, t);
> > >  	spin_unlock(&t->lock);
> > >  
> > >  	if (proc != to_proc) {
> > > @@ -5818,4 +5820,8 @@ static int __init binder_init(void)
> > >  #define CREATE_TRACE_POINTS
> > >  #include "binder_trace.h"
> > >  
> > > +EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_alloc);
> > > +EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_info);
> > > +EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_free);
> > > +
> > >  MODULE_LICENSE("GPL v2");
> > > diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> > > index 872232f..309d1b10 100644
> > > --- a/drivers/android/binder_internal.h
> > > +++ b/drivers/android/binder_internal.h
> > > @@ -15,6 +15,11 @@
> > >  #include <uapi/linux/android/binderfs.h>
> > >  #include "binder_alloc.h"
> > >  
> > > +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> > > +#include <uapi/linux/time_types.h>
> > > +#include <linux/rtc.h>
> > > +#endif
> > > +
> > >  struct binder_context {
> > >  	struct binder_node *binder_context_mgr_node;
> > >  	struct mutex context_mgr_node_lock;
> > > @@ -524,6 +529,14 @@ struct binder_transaction {
> > >  	 * during thread teardown
> > >  	 */
> > >  	spinlock_t lock;
> > > +	/**
> > > +	 * @timestamp and @tv are used to record the time
> > > +	 * that the binder transaction startup
> > > +	 */
> > > +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> > > +	struct timespec64 timestamp;
> > > +	struct __kernel_old_timeval tv;
> > 
> > As I stated in the 0/3 email, please use the correct in-kernel structure
> > for this.  That structure is _ONLY_ for old userspace api compatibility
> > issues.  Which is not the case here at all.
> > 
> > thanks,
> > greg k-h
> 
> Since it's not proper to use timeval & __kernel_old_timeval.
> The remaining structure with tv_usec that I found is
> __kernel_timex_timeval, but I'm not sure if this is proper one or not.
> All I can see is in
> https://lwn.net/ml/linux-kernel/20180705213604.18883-6-deepa.kernel@gmail.com/
> 
> I'm afraid of using wrong structure again.
> Could you give me some advices about this?
> 
> Or is there another suitable way to replace timeval

What exactly are you trying to measure such that you feel you need a
timeval structure?

thanks,

greg k-h

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v7 3/3] binder: add transaction latency tracer
  2020-08-04 13:59                                                   ` [PATCH v7 3/3] binder: add transaction latency tracer Frankie Chang
  2020-08-04 15:28                                                     ` Todd Kjos
@ 2020-09-07 14:41                                                     ` peter enderborg
  1 sibling, 0 replies; 72+ messages in thread
From: peter enderborg @ 2020-09-07 14:41 UTC (permalink / raw)
  To: Frankie Chang, Todd Kjos
  Cc: wsd_upstream, Greg Kroah-Hartman, linux-kernel,
	Arve Hjønnevåg, Jian-Min Liu, linux-mediatek,
	Joel Fernandes, Martijn Coenen, Christian Brauner

On 8/4/20 3:59 PM, Frankie Chang wrote:
> +void probe_binder_txn_latency_free(void *ignore, struct binder_transaction *t,
> +					int from_proc, int from_thread,
> +					int to_proc, int to_thread)
> +{
> +	struct rtc_time tm;
> +	struct timespec64 *startime;
> +	struct timespec64 cur, sub_t;
> +
> +	ktime_get_ts64(&cur);


I think sched_clock is what you want.


> +	startime = &t->timestamp;
> +	sub_t = timespec64_sub(cur, *startime);
> +
> +	/* if transaction time is over than binder_txn_latency_threshold (sec),
> +	 * show timeout warning log.
> +	 */
> +	if (sub_t.tv_sec < binder_txn_latency_threshold)
> +		return;
> +
> +	rtc_time_to_tm(t->tv.tv_sec, &tm);


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v8 3/3] binder: add transaction latency tracer
  2020-09-07 14:09                                                                 ` Greg Kroah-Hartman
@ 2020-09-08  5:38                                                                   ` Frankie Chang
  2020-09-08 14:06                                                                     ` [PATCH v9] binder: transaction latency tracking for user build Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-09-08  5:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Mon, 2020-09-07 at 16:09 +0200, Greg Kroah-Hartman wrote:
> On Mon, Sep 07, 2020 at 09:51:15PM +0800, Frankie Chang wrote:
> > On Mon, 2020-09-07 at 14:25 +0200, Greg Kroah-Hartman wrote:
> > > On Mon, Sep 07, 2020 at 08:00:55PM +0800, Frankie Chang wrote:
> > > > From: "Frankie.Chang" <Frankie.Chang@mediatek.com>
> > > > 
> > > > Record start/end timestamp for binder transaction.
> > > > When transaction is completed or transaction is free,
> > > > it would be checked if transaction latency over threshold
> > > > (default 2 sec), if yes, printing related information for tracing.
> > > > 
> > > > /* Implement details */
> > > > - Add latency tracer module to monitor transaction
> > > >   by attaching to new tracepoints introduced
> > > >   when transactions are allocated and freed.
> > > >   The trace_binder_txn_latency_free would not be enabled
> > > >   by default. Monitoring which transaction is too slow to
> > > >   cause some of exceptions is important. So we hook the
> > > >   tracepoint to call the monitor function.
> > > > 
> > > > - Since some of modules would trigger timeout NE
> > > >   if their binder transaction don't finish in time,
> > > >   such as audio timeout (5 sec), even BT command
> > > >   timeout (2 sec), etc.
> > > >   Therefore, setting the timeout threshold as default
> > > >   2 seconds could be helpful to debug.
> > > >   But this timeout threshold is configurable, to let
> > > >   all users determine the more suitable threshold.
> > > > 
> > > > - The reason why printing the related information to
> > > >   kernel information log but not trace buffer is that
> > > >   some abnormal transactions may be pending for a long
> > > >   time ago, they could not be recorded due to buffer
> > > >   limited.
> > > > 
> > > > Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
> > > > Acked-by: Todd Kjos <tkjos@google.com>
> > > > ---
> > > >  drivers/android/Kconfig                 |    8 +++
> > > >  drivers/android/Makefile                |    1 +
> > > >  drivers/android/binder.c                |    6 ++
> > > >  drivers/android/binder_internal.h       |   13 ++++
> > > >  drivers/android/binder_latency_tracer.c |  112 +++++++++++++++++++++++++++++++
> > > >  drivers/android/binder_trace.h          |   26 ++++++-
> > > >  6 files changed, 163 insertions(+), 3 deletions(-)
> > > >  create mode 100644 drivers/android/binder_latency_tracer.c
> > > > 
> > > > diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
> > > > index 53b22e2..8aadaf4 100644
> > > > --- a/drivers/android/Kconfig
> > > > +++ b/drivers/android/Kconfig
> > > > @@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
> > > >  	  exhaustively with combinations of various buffer sizes and
> > > >  	  alignments.
> > > >  
> > > > +config BINDER_TRANSACTION_LATENCY_TRACKING
> > > > +	tristate "Android Binder transaction tracking"
> > > > +	help
> > > > +	  Used for track abnormal binder transaction which is over threshold,
> > > > +	  when the transaction is done or be free, this transaction would be
> > > > +	  checked whether it executed overtime.
> > > > +	  If yes, printing out the detailed info.
> > > > +
> > > >  endif # if ANDROID
> > > >  
> > > >  endmenu
> > > > diff --git a/drivers/android/Makefile b/drivers/android/Makefile
> > > > index c9d3d0c9..c2ffdb6 100644
> > > > --- a/drivers/android/Makefile
> > > > +++ b/drivers/android/Makefile
> > > > @@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
> > > >  obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
> > > >  obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
> > > >  obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
> > > > +obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)	+= binder_latency_tracer.o
> > > > diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> > > > index 0cab900..65ad38c 100644
> > > > --- a/drivers/android/binder.c
> > > > +++ b/drivers/android/binder.c
> > > > @@ -2674,6 +2674,7 @@ static void binder_transaction(struct binder_proc *proc,
> > > >  		return_error_line = __LINE__;
> > > >  		goto err_alloc_t_failed;
> > > >  	}
> > > > +	trace_binder_txn_latency_alloc(t);
> > > >  	INIT_LIST_HEAD(&t->fd_fixups);
> > > >  	binder_stats_created(BINDER_STAT_TRANSACTION);
> > > >  	spin_lock_init(&t->lock);
> > > > @@ -5177,6 +5178,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
> > > >  		   to_proc ? to_proc->pid : 0,
> > > >  		   t->to_thread ? t->to_thread->pid : 0,
> > > >  		   t->code, t->flags, t->priority, t->need_reply);
> > > > +	trace_binder_txn_latency_info(m, t);
> > > >  	spin_unlock(&t->lock);
> > > >  
> > > >  	if (proc != to_proc) {
> > > > @@ -5818,4 +5820,8 @@ static int __init binder_init(void)
> > > >  #define CREATE_TRACE_POINTS
> > > >  #include "binder_trace.h"
> > > >  
> > > > +EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_alloc);
> > > > +EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_info);
> > > > +EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_free);
> > > > +
> > > >  MODULE_LICENSE("GPL v2");
> > > > diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
> > > > index 872232f..309d1b10 100644
> > > > --- a/drivers/android/binder_internal.h
> > > > +++ b/drivers/android/binder_internal.h
> > > > @@ -15,6 +15,11 @@
> > > >  #include <uapi/linux/android/binderfs.h>
> > > >  #include "binder_alloc.h"
> > > >  
> > > > +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> > > > +#include <uapi/linux/time_types.h>
> > > > +#include <linux/rtc.h>
> > > > +#endif
> > > > +
> > > >  struct binder_context {
> > > >  	struct binder_node *binder_context_mgr_node;
> > > >  	struct mutex context_mgr_node_lock;
> > > > @@ -524,6 +529,14 @@ struct binder_transaction {
> > > >  	 * during thread teardown
> > > >  	 */
> > > >  	spinlock_t lock;
> > > > +	/**
> > > > +	 * @timestamp and @tv are used to record the time
> > > > +	 * that the binder transaction startup
> > > > +	 */
> > > > +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> > > > +	struct timespec64 timestamp;
> > > > +	struct __kernel_old_timeval tv;
> > > 
> > > As I stated in the 0/3 email, please use the correct in-kernel structure
> > > for this.  That structure is _ONLY_ for old userspace api compatibility
> > > issues.  Which is not the case here at all.
> > > 
> > > thanks,
> > > greg k-h
> > 
> > Since it's not proper to use timeval & __kernel_old_timeval.
> > The remaining structure with tv_usec that I found is
> > __kernel_timex_timeval, but I'm not sure if this is proper one or not.
> > All I can see is in
> > https://lwn.net/ml/linux-kernel/20180705213604.18883-6-deepa.kernel@gmail.com/
> > 
> > I'm afraid of using wrong structure again.
> > Could you give me some advices about this?
> > 
> > Or is there another suitable way to replace timeval
> 
> What exactly are you trying to measure such that you feel you need a
> timeval structure?
> 
Actually I'd like to record timestamp with standard time structure, so I
used 'struct timeval' in the past patch. However it's deprecated, so I
am looking for the alternatives.

Additionally, I have already looked some patches that replacing timeval
with timespec64. I'll do the same way in next version patch.

Many thanks,
Frankie
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v9] binder: transaction latency tracking for user build
  2020-09-08  5:38                                                                   ` Frankie Chang
@ 2020-09-08 14:06                                                                     ` Frankie Chang
  2020-09-08 14:06                                                                       ` [PATCH v9 1/3] binder: move structs from core file to header file Frankie Chang
                                                                                         ` (3 more replies)
  0 siblings, 4 replies; 72+ messages in thread
From: Frankie Chang @ 2020-09-08 14:06 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

Change from v9:
  - rename timestamp to ts in binder_internal.h for conciseness.
  - change 'struct timeval' to 'struct timespec64' in binder_internal.h.

Change from v8:
  - change rtc_time_to_tm to rtc_time64_to_tm.
  - change timeval to __kernel_old_timeval due to 
    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c766d1472c70d25ad475cf56042af1652e792b23
  - export tracepoint symbol for binder_txn_latency_* which binder_transaction_latency_tracer to be ko needed.

Change from v7:
  - Use the passed-in values instead of accessing via t->from/to_proc/to_thread
    for trace_binder_txn_latency_free, when trace_binder_txn_latency_free_enable() return true.
  - make a helper function to do the above.

Change from v6:
  - change CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING type from bool to tristate
  - add comments to @timestamp and @tv under struct binder_transaction
  - make binder_txn_latency threshold configurable
  - enhance lock protection

Change from v5:
  - change config name to the proper one, CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING.
  - change tracepoint name to more descriptive one, trace_binder_txn_latency_(alloc|info|free)
  - enhance some lock protection.

Change from v4:
  - split up into patch series.

Change from v3:
  - use tracepoints for binder_update_info and print_binder_transaction_ext,
    instead of custom registration functions.

Change from v2:
  - create transaction latency module to monitor slow transaction.

Change from v1:
  - first patchset.


Frankie.Chang (3):
  binder: move structs from core file to header file
  binder: add trace at free transaction.
  binder: add transaction latency tracer

 drivers/android/Kconfig                 |   8 +
 drivers/android/Makefile                |   1 +
 drivers/android/binder.c                | 430 ++----------------------
 drivers/android/binder_internal.h       | 418 +++++++++++++++++++++++
 drivers/android/binder_latency_tracer.c | 108 ++++++
 drivers/android/binder_trace.h          |  49 +++
 6 files changed, 608 insertions(+), 406 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v9 1/3] binder: move structs from core file to header file
  2020-09-08 14:06                                                                     ` [PATCH v9] binder: transaction latency tracking for user build Frankie Chang
@ 2020-09-08 14:06                                                                       ` Frankie Chang
  2020-09-08 14:06                                                                       ` [PATCH v9 2/3] binder: add trace at free transaction Frankie Chang
                                                                                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-09-08 14:06 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Frankie.Chang,
	Martijn Coenen, Christian Brauner, Todd Kjos

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Moving all structs to header file makes module more
extendable, and makes all these structs to be defined
in the same file.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
Acked-by: Todd Kjos <tkjos@google.com>
---
 drivers/android/binder.c          |  406 -------------------------------------
 drivers/android/binder_internal.h |  405 ++++++++++++++++++++++++++++++++++++
 2 files changed, 405 insertions(+), 406 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index f936530..943c49c 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -68,11 +68,9 @@
 #include <linux/sizes.h>
 
 #include <uapi/linux/android/binder.h>
-#include <uapi/linux/android/binderfs.h>
 
 #include <asm/cacheflush.h>
 
-#include "binder_alloc.h"
 #include "binder_internal.h"
 #include "binder_trace.h"
 
@@ -160,24 +158,6 @@ static int binder_set_stop_on_user_error(const char *val,
 #define to_binder_fd_array_object(hdr) \
 	container_of(hdr, struct binder_fd_array_object, hdr)
 
-enum binder_stat_types {
-	BINDER_STAT_PROC,
-	BINDER_STAT_THREAD,
-	BINDER_STAT_NODE,
-	BINDER_STAT_REF,
-	BINDER_STAT_DEATH,
-	BINDER_STAT_TRANSACTION,
-	BINDER_STAT_TRANSACTION_COMPLETE,
-	BINDER_STAT_COUNT
-};
-
-struct binder_stats {
-	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
-	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
-	atomic_t obj_created[BINDER_STAT_COUNT];
-	atomic_t obj_deleted[BINDER_STAT_COUNT];
-};
-
 static struct binder_stats binder_stats;
 
 static inline void binder_stats_deleted(enum binder_stat_types type)
@@ -213,278 +193,11 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
 	return e;
 }
 
-/**
- * struct binder_work - work enqueued on a worklist
- * @entry:             node enqueued on list
- * @type:              type of work to be performed
- *
- * There are separate work lists for proc, thread, and node (async).
- */
-struct binder_work {
-	struct list_head entry;
-
-	enum {
-		BINDER_WORK_TRANSACTION = 1,
-		BINDER_WORK_TRANSACTION_COMPLETE,
-		BINDER_WORK_RETURN_ERROR,
-		BINDER_WORK_NODE,
-		BINDER_WORK_DEAD_BINDER,
-		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
-		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
-	} type;
-};
-
-struct binder_error {
-	struct binder_work work;
-	uint32_t cmd;
-};
-
-/**
- * struct binder_node - binder node bookkeeping
- * @debug_id:             unique ID for debugging
- *                        (invariant after initialized)
- * @lock:                 lock for node fields
- * @work:                 worklist element for node work
- *                        (protected by @proc->inner_lock)
- * @rb_node:              element for proc->nodes tree
- *                        (protected by @proc->inner_lock)
- * @dead_node:            element for binder_dead_nodes list
- *                        (protected by binder_dead_nodes_lock)
- * @proc:                 binder_proc that owns this node
- *                        (invariant after initialized)
- * @refs:                 list of references on this node
- *                        (protected by @lock)
- * @internal_strong_refs: used to take strong references when
- *                        initiating a transaction
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_weak_refs:      weak user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_strong_refs:    strong user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @tmp_refs:             temporary kernel refs
- *                        (protected by @proc->inner_lock while @proc
- *                        is valid, and by binder_dead_nodes_lock
- *                        if @proc is NULL. During inc/dec and node release
- *                        it is also protected by @lock to provide safety
- *                        as the node dies and @proc becomes NULL)
- * @ptr:                  userspace pointer for node
- *                        (invariant, no lock needed)
- * @cookie:               userspace cookie for node
- *                        (invariant, no lock needed)
- * @has_strong_ref:       userspace notified of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_strong_ref:   userspace has acked notification of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_weak_ref:         userspace notified of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_weak_ref:     userspace has acked notification of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_async_transaction: async transaction to node in progress
- *                        (protected by @lock)
- * @accept_fds:           file descriptor operations supported for node
- *                        (invariant after initialized)
- * @min_priority:         minimum scheduling priority
- *                        (invariant after initialized)
- * @txn_security_ctx:     require sender's security context
- *                        (invariant after initialized)
- * @async_todo:           list of async work items
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder nodes.
- */
-struct binder_node {
-	int debug_id;
-	spinlock_t lock;
-	struct binder_work work;
-	union {
-		struct rb_node rb_node;
-		struct hlist_node dead_node;
-	};
-	struct binder_proc *proc;
-	struct hlist_head refs;
-	int internal_strong_refs;
-	int local_weak_refs;
-	int local_strong_refs;
-	int tmp_refs;
-	binder_uintptr_t ptr;
-	binder_uintptr_t cookie;
-	struct {
-		/*
-		 * bitfield elements protected by
-		 * proc inner_lock
-		 */
-		u8 has_strong_ref:1;
-		u8 pending_strong_ref:1;
-		u8 has_weak_ref:1;
-		u8 pending_weak_ref:1;
-	};
-	struct {
-		/*
-		 * invariant after initialization
-		 */
-		u8 accept_fds:1;
-		u8 txn_security_ctx:1;
-		u8 min_priority;
-	};
-	bool has_async_transaction;
-	struct list_head async_todo;
-};
-
-struct binder_ref_death {
-	/**
-	 * @work: worklist element for death notifications
-	 *        (protected by inner_lock of the proc that
-	 *        this ref belongs to)
-	 */
-	struct binder_work work;
-	binder_uintptr_t cookie;
-};
-
-/**
- * struct binder_ref_data - binder_ref counts and id
- * @debug_id:        unique ID for the ref
- * @desc:            unique userspace handle for ref
- * @strong:          strong ref count (debugging only if not locked)
- * @weak:            weak ref count (debugging only if not locked)
- *
- * Structure to hold ref count and ref id information. Since
- * the actual ref can only be accessed with a lock, this structure
- * is used to return information about the ref to callers of
- * ref inc/dec functions.
- */
-struct binder_ref_data {
-	int debug_id;
-	uint32_t desc;
-	int strong;
-	int weak;
-};
-
-/**
- * struct binder_ref - struct to track references on nodes
- * @data:        binder_ref_data containing id, handle, and current refcounts
- * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
- * @rb_node_node: node for lookup by @node in proc's rb_tree
- * @node_entry:  list entry for node->refs list in target node
- *               (protected by @node->lock)
- * @proc:        binder_proc containing ref
- * @node:        binder_node of target node. When cleaning up a
- *               ref for deletion in binder_cleanup_ref, a non-NULL
- *               @node indicates the node must be freed
- * @death:       pointer to death notification (ref_death) if requested
- *               (protected by @node->lock)
- *
- * Structure to track references from procA to target node (on procB). This
- * structure is unsafe to access without holding @proc->outer_lock.
- */
-struct binder_ref {
-	/* Lookups needed: */
-	/*   node + proc => ref (transaction) */
-	/*   desc + proc => ref (transaction, inc/dec ref) */
-	/*   node => refs + procs (proc exit) */
-	struct binder_ref_data data;
-	struct rb_node rb_node_desc;
-	struct rb_node rb_node_node;
-	struct hlist_node node_entry;
-	struct binder_proc *proc;
-	struct binder_node *node;
-	struct binder_ref_death *death;
-};
-
 enum binder_deferred_state {
 	BINDER_DEFERRED_FLUSH        = 0x01,
 	BINDER_DEFERRED_RELEASE      = 0x02,
 };
 
-/**
- * struct binder_proc - binder process bookkeeping
- * @proc_node:            element for binder_procs list
- * @threads:              rbtree of binder_threads in this proc
- *                        (protected by @inner_lock)
- * @nodes:                rbtree of binder nodes associated with
- *                        this proc ordered by node->ptr
- *                        (protected by @inner_lock)
- * @refs_by_desc:         rbtree of refs ordered by ref->desc
- *                        (protected by @outer_lock)
- * @refs_by_node:         rbtree of refs ordered by ref->node
- *                        (protected by @outer_lock)
- * @waiting_threads:      threads currently waiting for proc work
- *                        (protected by @inner_lock)
- * @pid                   PID of group_leader of process
- *                        (invariant after initialized)
- * @tsk                   task_struct for group_leader of process
- *                        (invariant after initialized)
- * @deferred_work_node:   element for binder_deferred_list
- *                        (protected by binder_deferred_lock)
- * @deferred_work:        bitmap of deferred work to perform
- *                        (protected by binder_deferred_lock)
- * @is_dead:              process is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @inner_lock)
- * @todo:                 list of work for this process
- *                        (protected by @inner_lock)
- * @stats:                per-process binder statistics
- *                        (atomics, no lock needed)
- * @delivered_death:      list of delivered death notification
- *                        (protected by @inner_lock)
- * @max_threads:          cap on number of binder threads
- *                        (protected by @inner_lock)
- * @requested_threads:    number of binder threads requested but not
- *                        yet started. In current implementation, can
- *                        only be 0 or 1.
- *                        (protected by @inner_lock)
- * @requested_threads_started: number binder threads started
- *                        (protected by @inner_lock)
- * @tmp_ref:              temporary reference to indicate proc is in use
- *                        (protected by @inner_lock)
- * @default_priority:     default scheduler priority
- *                        (invariant after initialized)
- * @debugfs_entry:        debugfs node
- * @alloc:                binder allocator bookkeeping
- * @context:              binder_context for this proc
- *                        (invariant after initialized)
- * @inner_lock:           can nest under outer_lock and/or node lock
- * @outer_lock:           no nesting under innor or node lock
- *                        Lock order: 1) outer, 2) node, 3) inner
- * @binderfs_entry:       process-specific binderfs log file
- *
- * Bookkeeping structure for binder processes
- */
-struct binder_proc {
-	struct hlist_node proc_node;
-	struct rb_root threads;
-	struct rb_root nodes;
-	struct rb_root refs_by_desc;
-	struct rb_root refs_by_node;
-	struct list_head waiting_threads;
-	int pid;
-	struct task_struct *tsk;
-	struct hlist_node deferred_work_node;
-	int deferred_work;
-	bool is_dead;
-
-	struct list_head todo;
-	struct binder_stats stats;
-	struct list_head delivered_death;
-	int max_threads;
-	int requested_threads;
-	int requested_threads_started;
-	int tmp_ref;
-	long default_priority;
-	struct dentry *debugfs_entry;
-	struct binder_alloc alloc;
-	struct binder_context *context;
-	spinlock_t inner_lock;
-	spinlock_t outer_lock;
-	struct dentry *binderfs_entry;
-};
-
 enum {
 	BINDER_LOOPER_STATE_REGISTERED  = 0x01,
 	BINDER_LOOPER_STATE_ENTERED     = 0x02,
@@ -495,125 +208,6 @@ enum {
 };
 
 /**
- * struct binder_thread - binder thread bookkeeping
- * @proc:                 binder process for this thread
- *                        (invariant after initialization)
- * @rb_node:              element for proc->threads rbtree
- *                        (protected by @proc->inner_lock)
- * @waiting_thread_node:  element for @proc->waiting_threads list
- *                        (protected by @proc->inner_lock)
- * @pid:                  PID for this thread
- *                        (invariant after initialization)
- * @looper:               bitmap of looping state
- *                        (only accessed by this thread)
- * @looper_needs_return:  looping thread needs to exit driver
- *                        (no lock needed)
- * @transaction_stack:    stack of in-progress transactions for this thread
- *                        (protected by @proc->inner_lock)
- * @todo:                 list of work to do for this thread
- *                        (protected by @proc->inner_lock)
- * @process_todo:         whether work in @todo should be processed
- *                        (protected by @proc->inner_lock)
- * @return_error:         transaction errors reported by this thread
- *                        (only accessed by this thread)
- * @reply_error:          transaction errors reported by target thread
- *                        (protected by @proc->inner_lock)
- * @wait:                 wait queue for thread work
- * @stats:                per-thread statistics
- *                        (atomics, no lock needed)
- * @tmp_ref:              temporary reference to indicate thread is in use
- *                        (atomic since @proc->inner_lock cannot
- *                        always be acquired)
- * @is_dead:              thread is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder threads.
- */
-struct binder_thread {
-	struct binder_proc *proc;
-	struct rb_node rb_node;
-	struct list_head waiting_thread_node;
-	int pid;
-	int looper;              /* only modified by this thread */
-	bool looper_need_return; /* can be written by other thread */
-	struct binder_transaction *transaction_stack;
-	struct list_head todo;
-	bool process_todo;
-	struct binder_error return_error;
-	struct binder_error reply_error;
-	wait_queue_head_t wait;
-	struct binder_stats stats;
-	atomic_t tmp_ref;
-	bool is_dead;
-};
-
-/**
- * struct binder_txn_fd_fixup - transaction fd fixup list element
- * @fixup_entry:          list entry
- * @file:                 struct file to be associated with new fd
- * @offset:               offset in buffer data to this fixup
- *
- * List element for fd fixups in a transaction. Since file
- * descriptors need to be allocated in the context of the
- * target process, we pass each fd to be processed in this
- * struct.
- */
-struct binder_txn_fd_fixup {
-	struct list_head fixup_entry;
-	struct file *file;
-	size_t offset;
-};
-
-struct binder_transaction {
-	int debug_id;
-	struct binder_work work;
-	struct binder_thread *from;
-	struct binder_transaction *from_parent;
-	struct binder_proc *to_proc;
-	struct binder_thread *to_thread;
-	struct binder_transaction *to_parent;
-	unsigned need_reply:1;
-	/* unsigned is_dead:1; */	/* not used at the moment */
-
-	struct binder_buffer *buffer;
-	unsigned int	code;
-	unsigned int	flags;
-	long	priority;
-	long	saved_priority;
-	kuid_t	sender_euid;
-	struct list_head fd_fixups;
-	binder_uintptr_t security_ctx;
-	/**
-	 * @lock:  protects @from, @to_proc, and @to_thread
-	 *
-	 * @from, @to_proc, and @to_thread can be set to NULL
-	 * during thread teardown
-	 */
-	spinlock_t lock;
-};
-
-/**
- * struct binder_object - union of flat binder object types
- * @hdr:   generic object header
- * @fbo:   binder object (nodes and refs)
- * @fdo:   file descriptor object
- * @bbo:   binder buffer pointer
- * @fdao:  file descriptor array
- *
- * Used for type-independent object copies
- */
-struct binder_object {
-	union {
-		struct binder_object_header hdr;
-		struct flat_binder_object fbo;
-		struct binder_fd_object fdo;
-		struct binder_buffer_object bbo;
-		struct binder_fd_array_object fdao;
-	};
-};
-
-/**
  * binder_proc_lock() - Acquire outer lock for given binder_proc
  * @proc:         struct binder_proc to acquire
  *
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index 283d3cb..872232f 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -12,6 +12,8 @@
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/uidgid.h>
+#include <uapi/linux/android/binderfs.h>
+#include "binder_alloc.h"
 
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
@@ -141,6 +143,409 @@ struct binder_transaction_log {
 	struct binder_transaction_log_entry entry[32];
 };
 
+enum binder_stat_types {
+	BINDER_STAT_PROC,
+	BINDER_STAT_THREAD,
+	BINDER_STAT_NODE,
+	BINDER_STAT_REF,
+	BINDER_STAT_DEATH,
+	BINDER_STAT_TRANSACTION,
+	BINDER_STAT_TRANSACTION_COMPLETE,
+	BINDER_STAT_COUNT
+};
+
+struct binder_stats {
+	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
+	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
+	atomic_t obj_created[BINDER_STAT_COUNT];
+	atomic_t obj_deleted[BINDER_STAT_COUNT];
+};
+
+/**
+ * struct binder_work - work enqueued on a worklist
+ * @entry:             node enqueued on list
+ * @type:              type of work to be performed
+ *
+ * There are separate work lists for proc, thread, and node (async).
+ */
+struct binder_work {
+	struct list_head entry;
+
+	enum {
+		BINDER_WORK_TRANSACTION = 1,
+		BINDER_WORK_TRANSACTION_COMPLETE,
+		BINDER_WORK_RETURN_ERROR,
+		BINDER_WORK_NODE,
+		BINDER_WORK_DEAD_BINDER,
+		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
+		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
+	} type;
+};
+
+struct binder_error {
+	struct binder_work work;
+	uint32_t cmd;
+};
+
+/* struct binder_node - binder node bookkeeping
+ * @debug_id:             unique ID for debugging
+ *                        (invariant after initialized)
+ * @lock:                 lock for node fields
+ * @work:                 worklist element for node work
+ *                        (protected by @proc->inner_lock)
+ * @rb_node:              element for proc->nodes tree
+ *                        (protected by @proc->inner_lock)
+ * @dead_node:            element for binder_dead_nodes list
+ *                        (protected by binder_dead_nodes_lock)
+ * @proc:                 binder_proc that owns this node
+ *                        (invariant after initialized)
+ * @refs:                 list of references on this node
+ *                        (protected by @lock)
+ * @internal_strong_refs: used to take strong references when
+ *                        initiating a transaction
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_weak_refs:      weak user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_strong_refs:    strong user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @tmp_refs:             temporary kernel refs
+ *                        (protected by @proc->inner_lock while @proc
+ *                        is valid, and by binder_dead_nodes_lock
+ *                        if @proc is NULL. During inc/dec and node release
+ *                        it is also protected by @lock to provide safety
+ *                        as the node dies and @proc becomes NULL)
+ * @ptr:                  userspace pointer for node
+ *                        (invariant, no lock needed)
+ * @cookie:               userspace cookie for node
+ *                        (invariant, no lock needed)
+ * @has_strong_ref:       userspace notified of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_strong_ref:   userspace has acked notification of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_weak_ref:         userspace notified of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_weak_ref:     userspace has acked notification of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_async_transaction: async transaction to node in progress
+ *                        (protected by @lock)
+ * @accept_fds:           file descriptor operations supported for node
+ *                        (invariant after initialized)
+ * @min_priority:         minimum scheduling priority
+ *                        (invariant after initialized)
+ * @txn_security_ctx:     require sender's security context
+ *                        (invariant after initialized)
+ * @async_todo:           list of async work items
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder nodes.
+ */
+struct binder_node {
+	int debug_id;
+	spinlock_t lock;
+	struct binder_work work;
+	union {
+		struct rb_node rb_node;
+		struct hlist_node dead_node;
+	};
+	struct binder_proc *proc;
+	struct hlist_head refs;
+	int internal_strong_refs;
+	int local_weak_refs;
+	int local_strong_refs;
+	int tmp_refs;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
+	struct {
+		/*
+		 * bitfield elements protected by
+		 * proc inner_lock
+		 */
+		u8 has_strong_ref:1;
+		u8 pending_strong_ref:1;
+		u8 has_weak_ref:1;
+		u8 pending_weak_ref:1;
+	};
+	struct {
+		/*
+		 * invariant after initialization
+		 */
+		u8 accept_fds:1;
+		u8 txn_security_ctx:1;
+		u8 min_priority;
+	};
+	bool has_async_transaction;
+	struct list_head async_todo;
+};
+
+struct binder_ref_death {
+	/**
+	 * @work: worklist element for death notifications
+	 *        (protected by inner_lock of the proc that
+	 *        this ref belongs to)
+	 */
+	struct binder_work work;
+	binder_uintptr_t cookie;
+};
+
+/**
+ * struct binder_ref_data - binder_ref counts and id
+ * @debug_id:        unique ID for the ref
+ * @desc:            unique userspace handle for ref
+ * @strong:          strong ref count (debugging only if not locked)
+ * @weak:            weak ref count (debugging only if not locked)
+ *
+ * Structure to hold ref count and ref id information. Since
+ * the actual ref can only be accessed with a lock, this structure
+ * is used to return information about the ref to callers of
+ * ref inc/dec functions.
+ */
+struct binder_ref_data {
+	int debug_id;
+	uint32_t desc;
+	int strong;
+	int weak;
+};
+
+/**
+ * struct binder_ref - struct to track references on nodes
+ * @data:        binder_ref_data containing id, handle, and current refcounts
+ * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
+ * @rb_node_node: node for lookup by @node in proc's rb_tree
+ * @node_entry:  list entry for node->refs list in target node
+ *               (protected by @node->lock)
+ * @proc:        binder_proc containing ref
+ * @node:        binder_node of target node. When cleaning up a
+ *               ref for deletion in binder_cleanup_ref, a non-NULL
+ *               @node indicates the node must be freed
+ * @death:       pointer to death notification (ref_death) if requested
+ *               (protected by @node->lock)
+ *
+ * Structure to track references from procA to target node (on procB). This
+ * structure is unsafe to access without holding @proc->outer_lock.
+ */
+struct binder_ref {
+	/* Lookups needed: */
+	/*   node + proc => ref (transaction) */
+	/*   desc + proc => ref (transaction, inc/dec ref) */
+	/*   node => refs + procs (proc exit) */
+	struct binder_ref_data data;
+	struct rb_node rb_node_desc;
+	struct rb_node rb_node_node;
+	struct hlist_node node_entry;
+	struct binder_proc *proc;
+	struct binder_node *node;
+	struct binder_ref_death *death;
+};
+
+/**
+ * struct binder_proc - binder process bookkeeping
+ * @proc_node:            element for binder_procs list
+ * @threads:              rbtree of binder_threads in this proc
+ *                        (protected by @inner_lock)
+ * @nodes:                rbtree of binder nodes associated with
+ *                        this proc ordered by node->ptr
+ *                        (protected by @inner_lock)
+ * @refs_by_desc:         rbtree of refs ordered by ref->desc
+ *                        (protected by @outer_lock)
+ * @refs_by_node:         rbtree of refs ordered by ref->node
+ *                        (protected by @outer_lock)
+ * @waiting_threads:      threads currently waiting for proc work
+ *                        (protected by @inner_lock)
+ * @pid                   PID of group_leader of process
+ *                        (invariant after initialized)
+ * @tsk                   task_struct for group_leader of process
+ *                        (invariant after initialized)
+ * @deferred_work_node:   element for binder_deferred_list
+ *                        (protected by binder_deferred_lock)
+ * @deferred_work:        bitmap of deferred work to perform
+ *                        (protected by binder_deferred_lock)
+ * @is_dead:              process is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @inner_lock)
+ * @todo:                 list of work for this process
+ *                        (protected by @inner_lock)
+ * @stats:                per-process binder statistics
+ *                        (atomics, no lock needed)
+ * @delivered_death:      list of delivered death notification
+ *                        (protected by @inner_lock)
+ * @max_threads:          cap on number of binder threads
+ *                        (protected by @inner_lock)
+ * @requested_threads:    number of binder threads requested but not
+ *                        yet started. In current implementation, can
+ *                        only be 0 or 1.
+ *                        (protected by @inner_lock)
+ * @requested_threads_started: number binder threads started
+ *                        (protected by @inner_lock)
+ * @tmp_ref:              temporary reference to indicate proc is in use
+ *                        (protected by @inner_lock)
+ * @default_priority:     default scheduler priority
+ *                        (invariant after initialized)
+ * @debugfs_entry:        debugfs node
+ * @alloc:                binder allocator bookkeeping
+ * @context:              binder_context for this proc
+ *                        (invariant after initialized)
+ * @inner_lock:           can nest under outer_lock and/or node lock
+ * @outer_lock:           no nesting under innor or node lock
+ *                        Lock order: 1) outer, 2) node, 3) inner
+ * @binderfs_entry:       process-specific binderfs log file
+ *
+ * Bookkeeping structure for binder processes
+ */
+struct binder_proc {
+	struct hlist_node proc_node;
+	struct rb_root threads;
+	struct rb_root nodes;
+	struct rb_root refs_by_desc;
+	struct rb_root refs_by_node;
+	struct list_head waiting_threads;
+	int pid;
+	struct task_struct *tsk;
+	struct hlist_node deferred_work_node;
+	int deferred_work;
+	bool is_dead;
+
+	struct list_head todo;
+	struct binder_stats stats;
+	struct list_head delivered_death;
+	int max_threads;
+	int requested_threads;
+	int requested_threads_started;
+	int tmp_ref;
+	long default_priority;
+	struct dentry *debugfs_entry;
+	struct binder_alloc alloc;
+	struct binder_context *context;
+	spinlock_t inner_lock;
+	spinlock_t outer_lock;
+	struct dentry *binderfs_entry;
+};
+
+/**
+ * struct binder_thread - binder thread bookkeeping
+ * @proc:                 binder process for this thread
+ *                        (invariant after initialization)
+ * @rb_node:              element for proc->threads rbtree
+ *                        (protected by @proc->inner_lock)
+ * @waiting_thread_node:  element for @proc->waiting_threads list
+ *                        (protected by @proc->inner_lock)
+ * @pid:                  PID for this thread
+ *                        (invariant after initialization)
+ * @looper:               bitmap of looping state
+ *                        (only accessed by this thread)
+ * @looper_needs_return:  looping thread needs to exit driver
+ *                        (no lock needed)
+ * @transaction_stack:    stack of in-progress transactions for this thread
+ *                        (protected by @proc->inner_lock)
+ * @todo:                 list of work to do for this thread
+ *                        (protected by @proc->inner_lock)
+ * @process_todo:         whether work in @todo should be processed
+ *                        (protected by @proc->inner_lock)
+ * @return_error:         transaction errors reported by this thread
+ *                        (only accessed by this thread)
+ * @reply_error:          transaction errors reported by target thread
+ *                        (protected by @proc->inner_lock)
+ * @wait:                 wait queue for thread work
+ * @stats:                per-thread statistics
+ *                        (atomics, no lock needed)
+ * @tmp_ref:              temporary reference to indicate thread is in use
+ *                        (atomic since @proc->inner_lock cannot
+ *                        always be acquired)
+ * @is_dead:              thread is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder threads.
+ */
+struct binder_thread {
+	struct binder_proc *proc;
+	struct rb_node rb_node;
+	struct list_head waiting_thread_node;
+	int pid;
+	int looper;              /* only modified by this thread */
+	bool looper_need_return; /* can be written by other thread */
+	struct binder_transaction *transaction_stack;
+	struct list_head todo;
+	bool process_todo;
+	struct binder_error return_error;
+	struct binder_error reply_error;
+	wait_queue_head_t wait;
+	struct binder_stats stats;
+	atomic_t tmp_ref;
+	bool is_dead;
+};
+
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry:          list entry
+ * @file:                 struct file to be associated with new fd
+ * @offset:               offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+	struct list_head fixup_entry;
+	struct file *file;
+	size_t offset;
+};
+
+struct binder_transaction {
+	int debug_id;
+	struct binder_work work;
+	struct binder_thread *from;
+	struct binder_transaction *from_parent;
+	struct binder_proc *to_proc;
+	struct binder_thread *to_thread;
+	struct binder_transaction *to_parent;
+	unsigned need_reply:1;
+	/* unsigned is_dead:1; */       /* not used at the moment */
+
+	struct binder_buffer *buffer;
+	unsigned int    code;
+	unsigned int    flags;
+	long    priority;
+	long    saved_priority;
+	kuid_t  sender_euid;
+	struct list_head fd_fixups;
+	binder_uintptr_t security_ctx;
+	/**
+	 * @lock:  protects @from, @to_proc, and @to_thread
+	 *
+	 * @from, @to_proc, and @to_thread can be set to NULL
+	 * during thread teardown
+	 */
+	spinlock_t lock;
+};
+
+/**
+ * struct binder_object - union of flat binder object types
+ * @hdr:   generic object header
+ * @fbo:   binder object (nodes and refs)
+ * @fdo:   file descriptor object
+ * @bbo:   binder buffer pointer
+ * @fdao:  file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+	union {
+		struct binder_object_header hdr;
+		struct flat_binder_object fbo;
+		struct binder_fd_object fdo;
+		struct binder_buffer_object bbo;
+		struct binder_fd_array_object fdao;
+	};
+};
+
 extern struct binder_transaction_log binder_transaction_log;
 extern struct binder_transaction_log binder_transaction_log_failed;
 #endif /* _LINUX_BINDER_INTERNAL_H */
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v9 2/3] binder: add trace at free transaction.
  2020-09-08 14:06                                                                     ` [PATCH v9] binder: transaction latency tracking for user build Frankie Chang
  2020-09-08 14:06                                                                       ` [PATCH v9 1/3] binder: move structs from core file to header file Frankie Chang
@ 2020-09-08 14:06                                                                       ` Frankie Chang
  2020-09-08 14:06                                                                       ` [PATCH v9 3/3] binder: add transaction latency tracer Frankie Chang
  2020-09-16 15:29                                                                       ` [PATCH v9] binder: transaction latency tracking for user build Greg Kroah-Hartman
  3 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-09-08 14:06 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Frankie.Chang,
	Martijn Coenen, Christian Brauner, Todd Kjos

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Since the original trace_binder_transaction_received cannot
precisely present the real finished time of transaction, adding a
trace_binder_txn_latency_free at the point of free transaction
may be more close to it.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
Acked-by: Todd Kjos <tkjos@google.com>
---
 drivers/android/binder.c       |   18 ++++++++++++++++++
 drivers/android/binder_trace.h |   29 +++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 943c49c..0cab900 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1507,6 +1507,20 @@ static void binder_free_txn_fixups(struct binder_transaction *t)
 	}
 }
 
+static void binder_txn_latency_free(struct binder_transaction *t)
+{
+	int from_proc, from_thread, to_proc, to_thread;
+
+	spin_lock(&t->lock);
+	from_proc = t->from ? t->from->proc->pid : 0;
+	from_thread = t->from ? t->from->pid : 0;
+	to_proc = t->to_proc ? t->to_proc->pid : 0;
+	to_thread = t->to_thread ? t->to_thread->pid : 0;
+	spin_unlock(&t->lock);
+
+	trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc, to_thread);
+}
+
 static void binder_free_transaction(struct binder_transaction *t)
 {
 	struct binder_proc *target_proc = t->to_proc;
@@ -1517,6 +1531,8 @@ static void binder_free_transaction(struct binder_transaction *t)
 			t->buffer->transaction = NULL;
 		binder_inner_proc_unlock(target_proc);
 	}
+	if (trace_binder_txn_latency_free_enabled())
+		binder_txn_latency_free(t);
 	/*
 	 * If the transaction has no target_proc, then
 	 * t->buffer->transaction has already been cleared.
@@ -3096,6 +3112,8 @@ static void binder_transaction(struct binder_proc *proc,
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 err_alloc_tcomplete_failed:
+	if (trace_binder_txn_latency_free_enabled())
+		binder_txn_latency_free(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
 err_alloc_t_failed:
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 6731c3c..8eeccdc 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,35 @@
 		  __entry->thread_todo)
 );
 
+TRACE_EVENT(binder_txn_latency_free,
+	TP_PROTO(struct binder_transaction *t,
+		 int from_proc, int from_thread,
+		 int to_proc, int to_thread),
+	TP_ARGS(t, from_proc, from_thread, to_proc, to_thread),
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, from_proc)
+		__field(int, from_thread)
+		__field(int, to_proc)
+		__field(int, to_thread)
+		__field(unsigned int, code)
+		__field(unsigned int, flags)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->from_proc = from_proc;
+		__entry->from_thread = from_thread;
+		__entry->to_proc = to_proc;
+		__entry->to_thread = to_thread;
+		__entry->code = t->code;
+		__entry->flags = t->flags;
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
+		  __entry->to_proc, __entry->to_thread, __entry->code,
+		  __entry->flags)
+);
+
 TRACE_EVENT(binder_transaction,
 	TP_PROTO(bool reply, struct binder_transaction *t,
 		 struct binder_node *target_node),
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v9 3/3] binder: add transaction latency tracer
  2020-09-08 14:06                                                                     ` [PATCH v9] binder: transaction latency tracking for user build Frankie Chang
  2020-09-08 14:06                                                                       ` [PATCH v9 1/3] binder: move structs from core file to header file Frankie Chang
  2020-09-08 14:06                                                                       ` [PATCH v9 2/3] binder: add trace at free transaction Frankie Chang
@ 2020-09-08 14:06                                                                       ` Frankie Chang
  2020-09-16 17:38                                                                         ` Greg Kroah-Hartman
  2020-09-16 15:29                                                                       ` [PATCH v9] binder: transaction latency tracking for user build Greg Kroah-Hartman
  3 siblings, 1 reply; 72+ messages in thread
From: Frankie Chang @ 2020-09-08 14:06 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Frankie.Chang,
	Martijn Coenen, Christian Brauner, Todd Kjos

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Record start/end timestamp for binder transaction.
When transaction is completed or transaction is free,
it would be checked if transaction latency over threshold
(default 2 sec), if yes, printing related information for tracing.

/* Implement details */
- Add latency tracer module to monitor transaction
  by attaching to new tracepoints introduced
  when transactions are allocated and freed.
  The trace_binder_txn_latency_free would not be enabled
  by default. Monitoring which transaction is too slow to
  cause some of exceptions is important. So we hook the
  tracepoint to call the monitor function.

- Since some of modules would trigger timeout NE
  if their binder transaction don't finish in time,
  such as audio timeout (5 sec), even BT command
  timeout (2 sec), etc.
  Therefore, setting the timeout threshold as default
  2 seconds could be helpful to debug.
  But this timeout threshold is configurable, to let
  all users determine the more suitable threshold.

- The reason why printing the related information to
  kernel information log but not trace buffer is that
  some abnormal transactions may be pending for a long
  time ago, they could not be recorded due to buffer
  limited.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
Acked-by: Todd Kjos <tkjos@google.com>
---
 drivers/android/Kconfig                 |    8 +++
 drivers/android/Makefile                |    1 +
 drivers/android/binder.c                |    6 ++
 drivers/android/binder_internal.h       |   13 ++++
 drivers/android/binder_latency_tracer.c |  108 +++++++++++++++++++++++++++++++
 drivers/android/binder_trace.h          |   26 +++++++-
 6 files changed, 159 insertions(+), 3 deletions(-)
 create mode 100644 drivers/android/binder_latency_tracer.c

diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
index 53b22e2..8aadaf4 100644
--- a/drivers/android/Kconfig
+++ b/drivers/android/Kconfig
@@ -54,6 +54,14 @@ config ANDROID_BINDER_IPC_SELFTEST
 	  exhaustively with combinations of various buffer sizes and
 	  alignments.
 
+config BINDER_TRANSACTION_LATENCY_TRACKING
+	tristate "Android Binder transaction tracking"
+	help
+	  Used for track abnormal binder transaction which is over threshold,
+	  when the transaction is done or be free, this transaction would be
+	  checked whether it executed overtime.
+	  If yes, printing out the detailed info.
+
 endif # if ANDROID
 
 endmenu
diff --git a/drivers/android/Makefile b/drivers/android/Makefile
index c9d3d0c9..c2ffdb6 100644
--- a/drivers/android/Makefile
+++ b/drivers/android/Makefile
@@ -4,3 +4,4 @@ ccflags-y += -I$(src)			# needed for trace events
 obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
 obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
 obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
+obj-$(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)	+= binder_latency_tracer.o
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 0cab900..65ad38c 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2674,6 +2674,7 @@ static void binder_transaction(struct binder_proc *proc,
 		return_error_line = __LINE__;
 		goto err_alloc_t_failed;
 	}
+	trace_binder_txn_latency_alloc(t);
 	INIT_LIST_HEAD(&t->fd_fixups);
 	binder_stats_created(BINDER_STAT_TRANSACTION);
 	spin_lock_init(&t->lock);
@@ -5177,6 +5178,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
 		   to_proc ? to_proc->pid : 0,
 		   t->to_thread ? t->to_thread->pid : 0,
 		   t->code, t->flags, t->priority, t->need_reply);
+	trace_binder_txn_latency_info(m, t);
 	spin_unlock(&t->lock);
 
 	if (proc != to_proc) {
@@ -5818,4 +5820,8 @@ static int __init binder_init(void)
 #define CREATE_TRACE_POINTS
 #include "binder_trace.h"
 
+EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_alloc);
+EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_info);
+EXPORT_TRACEPOINT_SYMBOL(binder_txn_latency_free);
+
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index 872232f..14076ab 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -15,6 +15,11 @@
 #include <uapi/linux/android/binderfs.h>
 #include "binder_alloc.h"
 
+#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
+#include <linux/rtc.h>
+#include <linux/time.h>
+#endif
+
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
 	struct mutex context_mgr_node_lock;
@@ -524,6 +529,14 @@ struct binder_transaction {
 	 * during thread teardown
 	 */
 	spinlock_t lock;
+	/**
+	 * @ts and @real_ts are used to record the time
+	 * that the binder transaction startup
+	 */
+#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
+	struct timespec64 ts;
+	struct timespec64 real_ts;
+#endif
 };
 
 /**
diff --git a/drivers/android/binder_latency_tracer.c b/drivers/android/binder_latency_tracer.c
new file mode 100644
index 0000000..1b889af
--- /dev/null
+++ b/drivers/android/binder_latency_tracer.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ */
+
+#include <linux/module.h>
+#include <uapi/linux/android/binder.h>
+#include "binder_internal.h"
+#include "binder_trace.h"
+
+/**
+ * The reason setting the binder_txn_latency_threshold to 2 sec
+ * is that most of timeout abort is greater or equal to 2 sec.
+ * Making it configurable to let all users determine which
+ * threshold is more suitable.
+ */
+static uint32_t binder_txn_latency_threshold = 2;
+module_param_named(threshold, binder_txn_latency_threshold,
+			uint, 0644);
+
+/*
+ * probe_binder_txn_latency_free - Output info of a delay transaction
+ * @t:          pointer to the over-time transaction
+ */
+void probe_binder_txn_latency_free(void *ignore, struct binder_transaction *t,
+					int from_proc, int from_thread,
+					int to_proc, int to_thread)
+{
+	struct rtc_time tm;
+	struct timespec64 *startime;
+	struct timespec64 cur, sub_t;
+
+	ktime_get_ts64(&cur);
+	startime = &t->ts;
+	sub_t = timespec64_sub(cur, *startime);
+
+	/* if transaction time is over than binder_txn_latency_threshold (sec),
+	 * show timeout warning log.
+	 */
+	if (sub_t.tv_sec < binder_txn_latency_threshold)
+		return;
+
+	rtc_time64_to_tm(t->real_ts.tv_sec, &tm);
+
+	pr_info_ratelimited("%d: from %d:%d to %d:%d",
+			t->debug_id, from_proc, from_thread,
+			to_proc, to_thread);
+
+	pr_info_ratelimited(" total %u.%03ld s code %u start %lu.%03ld android %d-%02d-%02d %02d:%02d:%02d.%03lu\n",
+			(unsigned int)sub_t.tv_sec,
+			(sub_t.tv_nsec / NSEC_PER_MSEC),
+			t->code,
+			(unsigned long)startime->tv_sec,
+			(startime->tv_nsec / NSEC_PER_MSEC),
+			(tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+			tm.tm_hour, tm.tm_min, tm.tm_sec,
+			(unsigned long)(t->real_ts.tv_nsec / NSEC_PER_MSEC));
+}
+
+static void probe_binder_txn_latency_alloc(void *ignore,
+					struct binder_transaction *t)
+{
+	ktime_get_ts64(&t->ts);
+	ktime_get_real_ts64(&t->real_ts);
+	t->real_ts.tv_sec -= (sys_tz.tz_minuteswest * 60);
+}
+
+static void probe_binder_txn_latency_info(void *ignore, struct seq_file *m,
+					struct binder_transaction *t)
+{
+	struct rtc_time tm;
+
+	rtc_time64_to_tm(t->real_ts.tv_sec, &tm);
+	seq_printf(m,
+		   " start %lu.%06lu android %d-%02d-%02d %02d:%02d:%02d.%03lu",
+		   (unsigned long)t->ts.tv_sec,
+		   (t->ts.tv_nsec / NSEC_PER_USEC),
+		   (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday,
+		   tm.tm_hour, tm.tm_min, tm.tm_sec,
+		   (unsigned long)(t->real_ts.tv_nsec / NSEC_PER_MSEC));
+}
+
+static int __init init_binder_latency_tracer(void)
+{
+	register_trace_binder_txn_latency_free(
+			probe_binder_txn_latency_free, NULL);
+	register_trace_binder_txn_latency_alloc(
+			probe_binder_txn_latency_alloc, NULL);
+	register_trace_binder_txn_latency_info(
+			probe_binder_txn_latency_info, NULL);
+
+	return 0;
+}
+
+static void exit_binder_latency_tracer(void)
+{
+	unregister_trace_binder_txn_latency_free(
+			probe_binder_txn_latency_free, NULL);
+	unregister_trace_binder_txn_latency_alloc(
+			probe_binder_txn_latency_alloc, NULL);
+	unregister_trace_binder_txn_latency_info(
+			probe_binder_txn_latency_info, NULL);
+}
+
+module_init(init_binder_latency_tracer);
+module_exit(exit_binder_latency_tracer);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 8eeccdc..0933e63 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,17 @@
 		  __entry->thread_todo)
 );
 
+DECLARE_TRACE(binder_txn_latency_alloc,
+	TP_PROTO(struct binder_transaction *t),
+	TP_ARGS(t)
+);
+
+DECLARE_TRACE(binder_txn_latency_info,
+	TP_PROTO(struct seq_file *m,
+		 struct binder_transaction *t),
+	TP_ARGS(m, t)
+);
+
 TRACE_EVENT(binder_txn_latency_free,
 	TP_PROTO(struct binder_transaction *t,
 		 int from_proc, int from_thread,
@@ -108,6 +119,8 @@
 		__field(int, to_thread)
 		__field(unsigned int, code)
 		__field(unsigned int, flags)
+		__field(unsigned long, start_sec)
+		__field(unsigned long, start_nsec)
 	),
 	TP_fast_assign(
 		__entry->debug_id = t->debug_id;
@@ -117,11 +130,18 @@
 		__entry->to_thread = to_thread;
 		__entry->code = t->code;
 		__entry->flags = t->flags;
-	),
-	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
+		__entry->start_sec = t->ts.tv_sec;
+		__entry->start_nsec = t->ts.tv_nsec / NSEC_PER_MSEC;
+#else
+		__entry->start_sec = 0;
+		__entry->start_nsec = 0;
+#endif
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x start %lu.%03ld",
 		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
 		  __entry->to_proc, __entry->to_thread, __entry->code,
-		  __entry->flags)
+		  __entry->flags, __entry->start_sec, __entry->start_nsec)
 );
 
 TRACE_EVENT(binder_transaction,
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v9] binder: transaction latency tracking for user build
  2020-09-08 14:06                                                                     ` [PATCH v9] binder: transaction latency tracking for user build Frankie Chang
                                                                                         ` (2 preceding siblings ...)
  2020-09-08 14:06                                                                       ` [PATCH v9 3/3] binder: add transaction latency tracer Frankie Chang
@ 2020-09-16 15:29                                                                       ` Greg Kroah-Hartman
  3 siblings, 0 replies; 72+ messages in thread
From: Greg Kroah-Hartman @ 2020-09-16 15:29 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Tue, Sep 08, 2020 at 10:06:45PM +0800, Frankie Chang wrote:
> Change from v9:
>   - rename timestamp to ts in binder_internal.h for conciseness.
>   - change 'struct timeval' to 'struct timespec64' in binder_internal.h.

These just blew up in the 0-day testing, again, so I'm dropping them
from my tree.

Can you please fix them up and resend when you have them properly
building?

thanks,

greg k-h

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v9 3/3] binder: add transaction latency tracer
  2020-09-08 14:06                                                                       ` [PATCH v9 3/3] binder: add transaction latency tracer Frankie Chang
@ 2020-09-16 17:38                                                                         ` Greg Kroah-Hartman
  2020-10-15 17:02                                                                           ` [PATCH v10 " Frankie Chang
  0 siblings, 1 reply; 72+ messages in thread
From: Greg Kroah-Hartman @ 2020-09-16 17:38 UTC (permalink / raw)
  To: Frankie Chang
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

On Tue, Sep 08, 2020 at 10:06:48PM +0800, Frankie Chang wrote:
> +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> +#include <linux/rtc.h>
> +#include <linux/time.h>
> +#endif
> +
>  struct binder_context {
>  	struct binder_node *binder_context_mgr_node;
>  	struct mutex context_mgr_node_lock;
> @@ -524,6 +529,14 @@ struct binder_transaction {
>  	 * during thread teardown
>  	 */
>  	spinlock_t lock;
> +	/**
> +	 * @ts and @real_ts are used to record the time
> +	 * that the binder transaction startup
> +	 */
> +#if IS_ENABLED(CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING)
> +	struct timespec64 ts;
> +	struct timespec64 real_ts;

Why isn't this ktime_t?  Is timespec64 really something to be using
still?

thanks,

greg k-h

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v10 3/3] binder: add transaction latency tracer
  2020-09-16 17:38                                                                         ` Greg Kroah-Hartman
@ 2020-10-15 17:02                                                                           ` Frankie Chang
  2020-10-15 17:02                                                                             ` [PATCH v10 1/3] binder: move structs from core file to header file Frankie Chang
                                                                                               ` (2 more replies)
  0 siblings, 3 replies; 72+ messages in thread
From: Frankie Chang @ 2020-10-15 17:02 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Martijn Coenen,
	Christian Brauner, Todd Kjos

Change from v10:
  - replace timespec64 with ktime_t.
  - fix build warning.

Change from v9:
  - rename timestamp to ts in binder_internal.h for conciseness.
  - change timeval to timespec64 in binder_internal.h

Change from v8:
  - change rtc_time_to_tm to rtc_time64_to_tm.
  - change timeval to __kernel_old_timeval due to 
    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c766d1472c70d25ad475cf56042af1652e792b23
  - export tracepoint symbol for binder_txn_latency_* which binder_transaction_latency_tracer to be ko needed.

Change from v7:
  - Use the passed-in values instead of accessing via t->from/to_proc/to_thread
    for trace_binder_txn_latency_free, when trace_binder_txn_latency_free_enable() return true.
  - make a helper function to do the above.

Change from v6:
  - change CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING type from bool to tristate
  - add comments to @timestamp and @tv under struct binder_transaction
  - make binder_txn_latency threshold configurable
  - enhance lock protection

Change from v5:
  - change config name to the proper one, CONFIG_BINDER_TRANSACTION_LATENCY_TRACKING.
  - change tracepoint name to more descriptive one, trace_binder_txn_latency_(alloc|info|free)
  - enhance some lock protection.

Change from v4:
  - split up into patch series.

Change from v3:
  - use tracepoints for binder_update_info and print_binder_transaction_ext,
    instead of custom registration functions.

Change from v2:
  - create transaction latency module to monitor slow transaction.

Change from v1:
  - first patchset.


Frankie.Chang (3):
  binder: move structs from core file to header file
  binder: add trace at free transaction.
  binder: add transaction latency tracer

 drivers/android/Kconfig                 |   8 +
 drivers/android/Makefile                |   1 +
 drivers/android/binder.c                | 430 ++----------------------
 drivers/android/binder_internal.h       | 418 +++++++++++++++++++++++
 drivers/android/binder_latency_tracer.c | 107 ++++++
 drivers/android/binder_trace.h          |  49 +++
 6 files changed, 607 insertions(+), 406 deletions(-)  create mode 100644 drivers/android/binder_latency_tracer.c
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v10 1/3] binder: move structs from core file to header file
  2020-10-15 17:02                                                                           ` [PATCH v10 " Frankie Chang
@ 2020-10-15 17:02                                                                             ` Frankie Chang
  2020-10-15 17:02                                                                             ` [PATCH v10 2/3] binder: add trace at free transaction Frankie Chang
  2020-10-15 17:02                                                                             ` [PATCH v10 3/3] binder: add transaction latency tracer Frankie Chang
  2 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-10-15 17:02 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Frankie.Chang,
	Martijn Coenen, Christian Brauner, Todd Kjos

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Moving all structs to header file makes module more
extendable, and makes all these structs to be defined
in the same file.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
Acked-by: Todd Kjos <tkjos@google.com>
---
 drivers/android/binder.c          |  406 -------------------------------------
 drivers/android/binder_internal.h |  405 ++++++++++++++++++++++++++++++++++++
 2 files changed, 405 insertions(+), 406 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index f936530..943c49c 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -68,11 +68,9 @@
 #include <linux/sizes.h>
 
 #include <uapi/linux/android/binder.h>
-#include <uapi/linux/android/binderfs.h>
 
 #include <asm/cacheflush.h>
 
-#include "binder_alloc.h"
 #include "binder_internal.h"
 #include "binder_trace.h"
 
@@ -160,24 +158,6 @@ static int binder_set_stop_on_user_error(const char *val,
 #define to_binder_fd_array_object(hdr) \
 	container_of(hdr, struct binder_fd_array_object, hdr)
 
-enum binder_stat_types {
-	BINDER_STAT_PROC,
-	BINDER_STAT_THREAD,
-	BINDER_STAT_NODE,
-	BINDER_STAT_REF,
-	BINDER_STAT_DEATH,
-	BINDER_STAT_TRANSACTION,
-	BINDER_STAT_TRANSACTION_COMPLETE,
-	BINDER_STAT_COUNT
-};
-
-struct binder_stats {
-	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
-	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
-	atomic_t obj_created[BINDER_STAT_COUNT];
-	atomic_t obj_deleted[BINDER_STAT_COUNT];
-};
-
 static struct binder_stats binder_stats;
 
 static inline void binder_stats_deleted(enum binder_stat_types type)
@@ -213,278 +193,11 @@ static struct binder_transaction_log_entry *binder_transaction_log_add(
 	return e;
 }
 
-/**
- * struct binder_work - work enqueued on a worklist
- * @entry:             node enqueued on list
- * @type:              type of work to be performed
- *
- * There are separate work lists for proc, thread, and node (async).
- */
-struct binder_work {
-	struct list_head entry;
-
-	enum {
-		BINDER_WORK_TRANSACTION = 1,
-		BINDER_WORK_TRANSACTION_COMPLETE,
-		BINDER_WORK_RETURN_ERROR,
-		BINDER_WORK_NODE,
-		BINDER_WORK_DEAD_BINDER,
-		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
-		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
-	} type;
-};
-
-struct binder_error {
-	struct binder_work work;
-	uint32_t cmd;
-};
-
-/**
- * struct binder_node - binder node bookkeeping
- * @debug_id:             unique ID for debugging
- *                        (invariant after initialized)
- * @lock:                 lock for node fields
- * @work:                 worklist element for node work
- *                        (protected by @proc->inner_lock)
- * @rb_node:              element for proc->nodes tree
- *                        (protected by @proc->inner_lock)
- * @dead_node:            element for binder_dead_nodes list
- *                        (protected by binder_dead_nodes_lock)
- * @proc:                 binder_proc that owns this node
- *                        (invariant after initialized)
- * @refs:                 list of references on this node
- *                        (protected by @lock)
- * @internal_strong_refs: used to take strong references when
- *                        initiating a transaction
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_weak_refs:      weak user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @local_strong_refs:    strong user refs from local process
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @tmp_refs:             temporary kernel refs
- *                        (protected by @proc->inner_lock while @proc
- *                        is valid, and by binder_dead_nodes_lock
- *                        if @proc is NULL. During inc/dec and node release
- *                        it is also protected by @lock to provide safety
- *                        as the node dies and @proc becomes NULL)
- * @ptr:                  userspace pointer for node
- *                        (invariant, no lock needed)
- * @cookie:               userspace cookie for node
- *                        (invariant, no lock needed)
- * @has_strong_ref:       userspace notified of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_strong_ref:   userspace has acked notification of strong ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_weak_ref:         userspace notified of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @pending_weak_ref:     userspace has acked notification of weak ref
- *                        (protected by @proc->inner_lock if @proc
- *                        and by @lock)
- * @has_async_transaction: async transaction to node in progress
- *                        (protected by @lock)
- * @accept_fds:           file descriptor operations supported for node
- *                        (invariant after initialized)
- * @min_priority:         minimum scheduling priority
- *                        (invariant after initialized)
- * @txn_security_ctx:     require sender's security context
- *                        (invariant after initialized)
- * @async_todo:           list of async work items
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder nodes.
- */
-struct binder_node {
-	int debug_id;
-	spinlock_t lock;
-	struct binder_work work;
-	union {
-		struct rb_node rb_node;
-		struct hlist_node dead_node;
-	};
-	struct binder_proc *proc;
-	struct hlist_head refs;
-	int internal_strong_refs;
-	int local_weak_refs;
-	int local_strong_refs;
-	int tmp_refs;
-	binder_uintptr_t ptr;
-	binder_uintptr_t cookie;
-	struct {
-		/*
-		 * bitfield elements protected by
-		 * proc inner_lock
-		 */
-		u8 has_strong_ref:1;
-		u8 pending_strong_ref:1;
-		u8 has_weak_ref:1;
-		u8 pending_weak_ref:1;
-	};
-	struct {
-		/*
-		 * invariant after initialization
-		 */
-		u8 accept_fds:1;
-		u8 txn_security_ctx:1;
-		u8 min_priority;
-	};
-	bool has_async_transaction;
-	struct list_head async_todo;
-};
-
-struct binder_ref_death {
-	/**
-	 * @work: worklist element for death notifications
-	 *        (protected by inner_lock of the proc that
-	 *        this ref belongs to)
-	 */
-	struct binder_work work;
-	binder_uintptr_t cookie;
-};
-
-/**
- * struct binder_ref_data - binder_ref counts and id
- * @debug_id:        unique ID for the ref
- * @desc:            unique userspace handle for ref
- * @strong:          strong ref count (debugging only if not locked)
- * @weak:            weak ref count (debugging only if not locked)
- *
- * Structure to hold ref count and ref id information. Since
- * the actual ref can only be accessed with a lock, this structure
- * is used to return information about the ref to callers of
- * ref inc/dec functions.
- */
-struct binder_ref_data {
-	int debug_id;
-	uint32_t desc;
-	int strong;
-	int weak;
-};
-
-/**
- * struct binder_ref - struct to track references on nodes
- * @data:        binder_ref_data containing id, handle, and current refcounts
- * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
- * @rb_node_node: node for lookup by @node in proc's rb_tree
- * @node_entry:  list entry for node->refs list in target node
- *               (protected by @node->lock)
- * @proc:        binder_proc containing ref
- * @node:        binder_node of target node. When cleaning up a
- *               ref for deletion in binder_cleanup_ref, a non-NULL
- *               @node indicates the node must be freed
- * @death:       pointer to death notification (ref_death) if requested
- *               (protected by @node->lock)
- *
- * Structure to track references from procA to target node (on procB). This
- * structure is unsafe to access without holding @proc->outer_lock.
- */
-struct binder_ref {
-	/* Lookups needed: */
-	/*   node + proc => ref (transaction) */
-	/*   desc + proc => ref (transaction, inc/dec ref) */
-	/*   node => refs + procs (proc exit) */
-	struct binder_ref_data data;
-	struct rb_node rb_node_desc;
-	struct rb_node rb_node_node;
-	struct hlist_node node_entry;
-	struct binder_proc *proc;
-	struct binder_node *node;
-	struct binder_ref_death *death;
-};
-
 enum binder_deferred_state {
 	BINDER_DEFERRED_FLUSH        = 0x01,
 	BINDER_DEFERRED_RELEASE      = 0x02,
 };
 
-/**
- * struct binder_proc - binder process bookkeeping
- * @proc_node:            element for binder_procs list
- * @threads:              rbtree of binder_threads in this proc
- *                        (protected by @inner_lock)
- * @nodes:                rbtree of binder nodes associated with
- *                        this proc ordered by node->ptr
- *                        (protected by @inner_lock)
- * @refs_by_desc:         rbtree of refs ordered by ref->desc
- *                        (protected by @outer_lock)
- * @refs_by_node:         rbtree of refs ordered by ref->node
- *                        (protected by @outer_lock)
- * @waiting_threads:      threads currently waiting for proc work
- *                        (protected by @inner_lock)
- * @pid                   PID of group_leader of process
- *                        (invariant after initialized)
- * @tsk                   task_struct for group_leader of process
- *                        (invariant after initialized)
- * @deferred_work_node:   element for binder_deferred_list
- *                        (protected by binder_deferred_lock)
- * @deferred_work:        bitmap of deferred work to perform
- *                        (protected by binder_deferred_lock)
- * @is_dead:              process is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @inner_lock)
- * @todo:                 list of work for this process
- *                        (protected by @inner_lock)
- * @stats:                per-process binder statistics
- *                        (atomics, no lock needed)
- * @delivered_death:      list of delivered death notification
- *                        (protected by @inner_lock)
- * @max_threads:          cap on number of binder threads
- *                        (protected by @inner_lock)
- * @requested_threads:    number of binder threads requested but not
- *                        yet started. In current implementation, can
- *                        only be 0 or 1.
- *                        (protected by @inner_lock)
- * @requested_threads_started: number binder threads started
- *                        (protected by @inner_lock)
- * @tmp_ref:              temporary reference to indicate proc is in use
- *                        (protected by @inner_lock)
- * @default_priority:     default scheduler priority
- *                        (invariant after initialized)
- * @debugfs_entry:        debugfs node
- * @alloc:                binder allocator bookkeeping
- * @context:              binder_context for this proc
- *                        (invariant after initialized)
- * @inner_lock:           can nest under outer_lock and/or node lock
- * @outer_lock:           no nesting under innor or node lock
- *                        Lock order: 1) outer, 2) node, 3) inner
- * @binderfs_entry:       process-specific binderfs log file
- *
- * Bookkeeping structure for binder processes
- */
-struct binder_proc {
-	struct hlist_node proc_node;
-	struct rb_root threads;
-	struct rb_root nodes;
-	struct rb_root refs_by_desc;
-	struct rb_root refs_by_node;
-	struct list_head waiting_threads;
-	int pid;
-	struct task_struct *tsk;
-	struct hlist_node deferred_work_node;
-	int deferred_work;
-	bool is_dead;
-
-	struct list_head todo;
-	struct binder_stats stats;
-	struct list_head delivered_death;
-	int max_threads;
-	int requested_threads;
-	int requested_threads_started;
-	int tmp_ref;
-	long default_priority;
-	struct dentry *debugfs_entry;
-	struct binder_alloc alloc;
-	struct binder_context *context;
-	spinlock_t inner_lock;
-	spinlock_t outer_lock;
-	struct dentry *binderfs_entry;
-};
-
 enum {
 	BINDER_LOOPER_STATE_REGISTERED  = 0x01,
 	BINDER_LOOPER_STATE_ENTERED     = 0x02,
@@ -495,125 +208,6 @@ enum {
 };
 
 /**
- * struct binder_thread - binder thread bookkeeping
- * @proc:                 binder process for this thread
- *                        (invariant after initialization)
- * @rb_node:              element for proc->threads rbtree
- *                        (protected by @proc->inner_lock)
- * @waiting_thread_node:  element for @proc->waiting_threads list
- *                        (protected by @proc->inner_lock)
- * @pid:                  PID for this thread
- *                        (invariant after initialization)
- * @looper:               bitmap of looping state
- *                        (only accessed by this thread)
- * @looper_needs_return:  looping thread needs to exit driver
- *                        (no lock needed)
- * @transaction_stack:    stack of in-progress transactions for this thread
- *                        (protected by @proc->inner_lock)
- * @todo:                 list of work to do for this thread
- *                        (protected by @proc->inner_lock)
- * @process_todo:         whether work in @todo should be processed
- *                        (protected by @proc->inner_lock)
- * @return_error:         transaction errors reported by this thread
- *                        (only accessed by this thread)
- * @reply_error:          transaction errors reported by target thread
- *                        (protected by @proc->inner_lock)
- * @wait:                 wait queue for thread work
- * @stats:                per-thread statistics
- *                        (atomics, no lock needed)
- * @tmp_ref:              temporary reference to indicate thread is in use
- *                        (atomic since @proc->inner_lock cannot
- *                        always be acquired)
- * @is_dead:              thread is dead and awaiting free
- *                        when outstanding transactions are cleaned up
- *                        (protected by @proc->inner_lock)
- *
- * Bookkeeping structure for binder threads.
- */
-struct binder_thread {
-	struct binder_proc *proc;
-	struct rb_node rb_node;
-	struct list_head waiting_thread_node;
-	int pid;
-	int looper;              /* only modified by this thread */
-	bool looper_need_return; /* can be written by other thread */
-	struct binder_transaction *transaction_stack;
-	struct list_head todo;
-	bool process_todo;
-	struct binder_error return_error;
-	struct binder_error reply_error;
-	wait_queue_head_t wait;
-	struct binder_stats stats;
-	atomic_t tmp_ref;
-	bool is_dead;
-};
-
-/**
- * struct binder_txn_fd_fixup - transaction fd fixup list element
- * @fixup_entry:          list entry
- * @file:                 struct file to be associated with new fd
- * @offset:               offset in buffer data to this fixup
- *
- * List element for fd fixups in a transaction. Since file
- * descriptors need to be allocated in the context of the
- * target process, we pass each fd to be processed in this
- * struct.
- */
-struct binder_txn_fd_fixup {
-	struct list_head fixup_entry;
-	struct file *file;
-	size_t offset;
-};
-
-struct binder_transaction {
-	int debug_id;
-	struct binder_work work;
-	struct binder_thread *from;
-	struct binder_transaction *from_parent;
-	struct binder_proc *to_proc;
-	struct binder_thread *to_thread;
-	struct binder_transaction *to_parent;
-	unsigned need_reply:1;
-	/* unsigned is_dead:1; */	/* not used at the moment */
-
-	struct binder_buffer *buffer;
-	unsigned int	code;
-	unsigned int	flags;
-	long	priority;
-	long	saved_priority;
-	kuid_t	sender_euid;
-	struct list_head fd_fixups;
-	binder_uintptr_t security_ctx;
-	/**
-	 * @lock:  protects @from, @to_proc, and @to_thread
-	 *
-	 * @from, @to_proc, and @to_thread can be set to NULL
-	 * during thread teardown
-	 */
-	spinlock_t lock;
-};
-
-/**
- * struct binder_object - union of flat binder object types
- * @hdr:   generic object header
- * @fbo:   binder object (nodes and refs)
- * @fdo:   file descriptor object
- * @bbo:   binder buffer pointer
- * @fdao:  file descriptor array
- *
- * Used for type-independent object copies
- */
-struct binder_object {
-	union {
-		struct binder_object_header hdr;
-		struct flat_binder_object fbo;
-		struct binder_fd_object fdo;
-		struct binder_buffer_object bbo;
-		struct binder_fd_array_object fdao;
-	};
-};
-
-/**
  * binder_proc_lock() - Acquire outer lock for given binder_proc
  * @proc:         struct binder_proc to acquire
  *
diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
index 283d3cb..872232f 100644
--- a/drivers/android/binder_internal.h
+++ b/drivers/android/binder_internal.h
@@ -12,6 +12,8 @@
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/uidgid.h>
+#include <uapi/linux/android/binderfs.h>
+#include "binder_alloc.h"
 
 struct binder_context {
 	struct binder_node *binder_context_mgr_node;
@@ -141,6 +143,409 @@ struct binder_transaction_log {
 	struct binder_transaction_log_entry entry[32];
 };
 
+enum binder_stat_types {
+	BINDER_STAT_PROC,
+	BINDER_STAT_THREAD,
+	BINDER_STAT_NODE,
+	BINDER_STAT_REF,
+	BINDER_STAT_DEATH,
+	BINDER_STAT_TRANSACTION,
+	BINDER_STAT_TRANSACTION_COMPLETE,
+	BINDER_STAT_COUNT
+};
+
+struct binder_stats {
+	atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1];
+	atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
+	atomic_t obj_created[BINDER_STAT_COUNT];
+	atomic_t obj_deleted[BINDER_STAT_COUNT];
+};
+
+/**
+ * struct binder_work - work enqueued on a worklist
+ * @entry:             node enqueued on list
+ * @type:              type of work to be performed
+ *
+ * There are separate work lists for proc, thread, and node (async).
+ */
+struct binder_work {
+	struct list_head entry;
+
+	enum {
+		BINDER_WORK_TRANSACTION = 1,
+		BINDER_WORK_TRANSACTION_COMPLETE,
+		BINDER_WORK_RETURN_ERROR,
+		BINDER_WORK_NODE,
+		BINDER_WORK_DEAD_BINDER,
+		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
+		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
+	} type;
+};
+
+struct binder_error {
+	struct binder_work work;
+	uint32_t cmd;
+};
+
+/* struct binder_node - binder node bookkeeping
+ * @debug_id:             unique ID for debugging
+ *                        (invariant after initialized)
+ * @lock:                 lock for node fields
+ * @work:                 worklist element for node work
+ *                        (protected by @proc->inner_lock)
+ * @rb_node:              element for proc->nodes tree
+ *                        (protected by @proc->inner_lock)
+ * @dead_node:            element for binder_dead_nodes list
+ *                        (protected by binder_dead_nodes_lock)
+ * @proc:                 binder_proc that owns this node
+ *                        (invariant after initialized)
+ * @refs:                 list of references on this node
+ *                        (protected by @lock)
+ * @internal_strong_refs: used to take strong references when
+ *                        initiating a transaction
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_weak_refs:      weak user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @local_strong_refs:    strong user refs from local process
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @tmp_refs:             temporary kernel refs
+ *                        (protected by @proc->inner_lock while @proc
+ *                        is valid, and by binder_dead_nodes_lock
+ *                        if @proc is NULL. During inc/dec and node release
+ *                        it is also protected by @lock to provide safety
+ *                        as the node dies and @proc becomes NULL)
+ * @ptr:                  userspace pointer for node
+ *                        (invariant, no lock needed)
+ * @cookie:               userspace cookie for node
+ *                        (invariant, no lock needed)
+ * @has_strong_ref:       userspace notified of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_strong_ref:   userspace has acked notification of strong ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_weak_ref:         userspace notified of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @pending_weak_ref:     userspace has acked notification of weak ref
+ *                        (protected by @proc->inner_lock if @proc
+ *                        and by @lock)
+ * @has_async_transaction: async transaction to node in progress
+ *                        (protected by @lock)
+ * @accept_fds:           file descriptor operations supported for node
+ *                        (invariant after initialized)
+ * @min_priority:         minimum scheduling priority
+ *                        (invariant after initialized)
+ * @txn_security_ctx:     require sender's security context
+ *                        (invariant after initialized)
+ * @async_todo:           list of async work items
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder nodes.
+ */
+struct binder_node {
+	int debug_id;
+	spinlock_t lock;
+	struct binder_work work;
+	union {
+		struct rb_node rb_node;
+		struct hlist_node dead_node;
+	};
+	struct binder_proc *proc;
+	struct hlist_head refs;
+	int internal_strong_refs;
+	int local_weak_refs;
+	int local_strong_refs;
+	int tmp_refs;
+	binder_uintptr_t ptr;
+	binder_uintptr_t cookie;
+	struct {
+		/*
+		 * bitfield elements protected by
+		 * proc inner_lock
+		 */
+		u8 has_strong_ref:1;
+		u8 pending_strong_ref:1;
+		u8 has_weak_ref:1;
+		u8 pending_weak_ref:1;
+	};
+	struct {
+		/*
+		 * invariant after initialization
+		 */
+		u8 accept_fds:1;
+		u8 txn_security_ctx:1;
+		u8 min_priority;
+	};
+	bool has_async_transaction;
+	struct list_head async_todo;
+};
+
+struct binder_ref_death {
+	/**
+	 * @work: worklist element for death notifications
+	 *        (protected by inner_lock of the proc that
+	 *        this ref belongs to)
+	 */
+	struct binder_work work;
+	binder_uintptr_t cookie;
+};
+
+/**
+ * struct binder_ref_data - binder_ref counts and id
+ * @debug_id:        unique ID for the ref
+ * @desc:            unique userspace handle for ref
+ * @strong:          strong ref count (debugging only if not locked)
+ * @weak:            weak ref count (debugging only if not locked)
+ *
+ * Structure to hold ref count and ref id information. Since
+ * the actual ref can only be accessed with a lock, this structure
+ * is used to return information about the ref to callers of
+ * ref inc/dec functions.
+ */
+struct binder_ref_data {
+	int debug_id;
+	uint32_t desc;
+	int strong;
+	int weak;
+};
+
+/**
+ * struct binder_ref - struct to track references on nodes
+ * @data:        binder_ref_data containing id, handle, and current refcounts
+ * @rb_node_desc: node for lookup by @data.desc in proc's rb_tree
+ * @rb_node_node: node for lookup by @node in proc's rb_tree
+ * @node_entry:  list entry for node->refs list in target node
+ *               (protected by @node->lock)
+ * @proc:        binder_proc containing ref
+ * @node:        binder_node of target node. When cleaning up a
+ *               ref for deletion in binder_cleanup_ref, a non-NULL
+ *               @node indicates the node must be freed
+ * @death:       pointer to death notification (ref_death) if requested
+ *               (protected by @node->lock)
+ *
+ * Structure to track references from procA to target node (on procB). This
+ * structure is unsafe to access without holding @proc->outer_lock.
+ */
+struct binder_ref {
+	/* Lookups needed: */
+	/*   node + proc => ref (transaction) */
+	/*   desc + proc => ref (transaction, inc/dec ref) */
+	/*   node => refs + procs (proc exit) */
+	struct binder_ref_data data;
+	struct rb_node rb_node_desc;
+	struct rb_node rb_node_node;
+	struct hlist_node node_entry;
+	struct binder_proc *proc;
+	struct binder_node *node;
+	struct binder_ref_death *death;
+};
+
+/**
+ * struct binder_proc - binder process bookkeeping
+ * @proc_node:            element for binder_procs list
+ * @threads:              rbtree of binder_threads in this proc
+ *                        (protected by @inner_lock)
+ * @nodes:                rbtree of binder nodes associated with
+ *                        this proc ordered by node->ptr
+ *                        (protected by @inner_lock)
+ * @refs_by_desc:         rbtree of refs ordered by ref->desc
+ *                        (protected by @outer_lock)
+ * @refs_by_node:         rbtree of refs ordered by ref->node
+ *                        (protected by @outer_lock)
+ * @waiting_threads:      threads currently waiting for proc work
+ *                        (protected by @inner_lock)
+ * @pid                   PID of group_leader of process
+ *                        (invariant after initialized)
+ * @tsk                   task_struct for group_leader of process
+ *                        (invariant after initialized)
+ * @deferred_work_node:   element for binder_deferred_list
+ *                        (protected by binder_deferred_lock)
+ * @deferred_work:        bitmap of deferred work to perform
+ *                        (protected by binder_deferred_lock)
+ * @is_dead:              process is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @inner_lock)
+ * @todo:                 list of work for this process
+ *                        (protected by @inner_lock)
+ * @stats:                per-process binder statistics
+ *                        (atomics, no lock needed)
+ * @delivered_death:      list of delivered death notification
+ *                        (protected by @inner_lock)
+ * @max_threads:          cap on number of binder threads
+ *                        (protected by @inner_lock)
+ * @requested_threads:    number of binder threads requested but not
+ *                        yet started. In current implementation, can
+ *                        only be 0 or 1.
+ *                        (protected by @inner_lock)
+ * @requested_threads_started: number binder threads started
+ *                        (protected by @inner_lock)
+ * @tmp_ref:              temporary reference to indicate proc is in use
+ *                        (protected by @inner_lock)
+ * @default_priority:     default scheduler priority
+ *                        (invariant after initialized)
+ * @debugfs_entry:        debugfs node
+ * @alloc:                binder allocator bookkeeping
+ * @context:              binder_context for this proc
+ *                        (invariant after initialized)
+ * @inner_lock:           can nest under outer_lock and/or node lock
+ * @outer_lock:           no nesting under innor or node lock
+ *                        Lock order: 1) outer, 2) node, 3) inner
+ * @binderfs_entry:       process-specific binderfs log file
+ *
+ * Bookkeeping structure for binder processes
+ */
+struct binder_proc {
+	struct hlist_node proc_node;
+	struct rb_root threads;
+	struct rb_root nodes;
+	struct rb_root refs_by_desc;
+	struct rb_root refs_by_node;
+	struct list_head waiting_threads;
+	int pid;
+	struct task_struct *tsk;
+	struct hlist_node deferred_work_node;
+	int deferred_work;
+	bool is_dead;
+
+	struct list_head todo;
+	struct binder_stats stats;
+	struct list_head delivered_death;
+	int max_threads;
+	int requested_threads;
+	int requested_threads_started;
+	int tmp_ref;
+	long default_priority;
+	struct dentry *debugfs_entry;
+	struct binder_alloc alloc;
+	struct binder_context *context;
+	spinlock_t inner_lock;
+	spinlock_t outer_lock;
+	struct dentry *binderfs_entry;
+};
+
+/**
+ * struct binder_thread - binder thread bookkeeping
+ * @proc:                 binder process for this thread
+ *                        (invariant after initialization)
+ * @rb_node:              element for proc->threads rbtree
+ *                        (protected by @proc->inner_lock)
+ * @waiting_thread_node:  element for @proc->waiting_threads list
+ *                        (protected by @proc->inner_lock)
+ * @pid:                  PID for this thread
+ *                        (invariant after initialization)
+ * @looper:               bitmap of looping state
+ *                        (only accessed by this thread)
+ * @looper_needs_return:  looping thread needs to exit driver
+ *                        (no lock needed)
+ * @transaction_stack:    stack of in-progress transactions for this thread
+ *                        (protected by @proc->inner_lock)
+ * @todo:                 list of work to do for this thread
+ *                        (protected by @proc->inner_lock)
+ * @process_todo:         whether work in @todo should be processed
+ *                        (protected by @proc->inner_lock)
+ * @return_error:         transaction errors reported by this thread
+ *                        (only accessed by this thread)
+ * @reply_error:          transaction errors reported by target thread
+ *                        (protected by @proc->inner_lock)
+ * @wait:                 wait queue for thread work
+ * @stats:                per-thread statistics
+ *                        (atomics, no lock needed)
+ * @tmp_ref:              temporary reference to indicate thread is in use
+ *                        (atomic since @proc->inner_lock cannot
+ *                        always be acquired)
+ * @is_dead:              thread is dead and awaiting free
+ *                        when outstanding transactions are cleaned up
+ *                        (protected by @proc->inner_lock)
+ *
+ * Bookkeeping structure for binder threads.
+ */
+struct binder_thread {
+	struct binder_proc *proc;
+	struct rb_node rb_node;
+	struct list_head waiting_thread_node;
+	int pid;
+	int looper;              /* only modified by this thread */
+	bool looper_need_return; /* can be written by other thread */
+	struct binder_transaction *transaction_stack;
+	struct list_head todo;
+	bool process_todo;
+	struct binder_error return_error;
+	struct binder_error reply_error;
+	wait_queue_head_t wait;
+	struct binder_stats stats;
+	atomic_t tmp_ref;
+	bool is_dead;
+};
+
+/**
+ * struct binder_txn_fd_fixup - transaction fd fixup list element
+ * @fixup_entry:          list entry
+ * @file:                 struct file to be associated with new fd
+ * @offset:               offset in buffer data to this fixup
+ *
+ * List element for fd fixups in a transaction. Since file
+ * descriptors need to be allocated in the context of the
+ * target process, we pass each fd to be processed in this
+ * struct.
+ */
+struct binder_txn_fd_fixup {
+	struct list_head fixup_entry;
+	struct file *file;
+	size_t offset;
+};
+
+struct binder_transaction {
+	int debug_id;
+	struct binder_work work;
+	struct binder_thread *from;
+	struct binder_transaction *from_parent;
+	struct binder_proc *to_proc;
+	struct binder_thread *to_thread;
+	struct binder_transaction *to_parent;
+	unsigned need_reply:1;
+	/* unsigned is_dead:1; */       /* not used at the moment */
+
+	struct binder_buffer *buffer;
+	unsigned int    code;
+	unsigned int    flags;
+	long    priority;
+	long    saved_priority;
+	kuid_t  sender_euid;
+	struct list_head fd_fixups;
+	binder_uintptr_t security_ctx;
+	/**
+	 * @lock:  protects @from, @to_proc, and @to_thread
+	 *
+	 * @from, @to_proc, and @to_thread can be set to NULL
+	 * during thread teardown
+	 */
+	spinlock_t lock;
+};
+
+/**
+ * struct binder_object - union of flat binder object types
+ * @hdr:   generic object header
+ * @fbo:   binder object (nodes and refs)
+ * @fdo:   file descriptor object
+ * @bbo:   binder buffer pointer
+ * @fdao:  file descriptor array
+ *
+ * Used for type-independent object copies
+ */
+struct binder_object {
+	union {
+		struct binder_object_header hdr;
+		struct flat_binder_object fbo;
+		struct binder_fd_object fdo;
+		struct binder_buffer_object bbo;
+		struct binder_fd_array_object fdao;
+	};
+};
+
 extern struct binder_transaction_log binder_transaction_log;
 extern struct binder_transaction_log binder_transaction_log_failed;
 #endif /* _LINUX_BINDER_INTERNAL_H */
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v10 2/3] binder: add trace at free transaction.
  2020-10-15 17:02                                                                           ` [PATCH v10 " Frankie Chang
  2020-10-15 17:02                                                                             ` [PATCH v10 1/3] binder: move structs from core file to header file Frankie Chang
@ 2020-10-15 17:02                                                                             ` Frankie Chang
  2020-10-15 17:02                                                                             ` [PATCH v10 3/3] binder: add transaction latency tracer Frankie Chang
  2 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-10-15 17:02 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Frankie.Chang,
	Martijn Coenen, Christian Brauner, Todd Kjos

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Since the original trace_binder_transaction_received cannot
precisely present the real finished time of transaction, adding a
trace_binder_txn_latency_free at the point of free transaction
may be more close to it.

Signed-off-by: Frankie.Chang <Frankie.Chang@mediatek.com>
Acked-by: Todd Kjos <tkjos@google.com>
---
 drivers/android/binder.c       |   18 ++++++++++++++++++
 drivers/android/binder_trace.h |   29 +++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 943c49c..0cab900 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1507,6 +1507,20 @@ static void binder_free_txn_fixups(struct binder_transaction *t)
 	}
 }
 
+static void binder_txn_latency_free(struct binder_transaction *t)
+{
+	int from_proc, from_thread, to_proc, to_thread;
+
+	spin_lock(&t->lock);
+	from_proc = t->from ? t->from->proc->pid : 0;
+	from_thread = t->from ? t->from->pid : 0;
+	to_proc = t->to_proc ? t->to_proc->pid : 0;
+	to_thread = t->to_thread ? t->to_thread->pid : 0;
+	spin_unlock(&t->lock);
+
+	trace_binder_txn_latency_free(t, from_proc, from_thread, to_proc, to_thread);
+}
+
 static void binder_free_transaction(struct binder_transaction *t)
 {
 	struct binder_proc *target_proc = t->to_proc;
@@ -1517,6 +1531,8 @@ static void binder_free_transaction(struct binder_transaction *t)
 			t->buffer->transaction = NULL;
 		binder_inner_proc_unlock(target_proc);
 	}
+	if (trace_binder_txn_latency_free_enabled())
+		binder_txn_latency_free(t);
 	/*
 	 * If the transaction has no target_proc, then
 	 * t->buffer->transaction has already been cleared.
@@ -3096,6 +3112,8 @@ static void binder_transaction(struct binder_proc *proc,
 	kfree(tcomplete);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
 err_alloc_tcomplete_failed:
+	if (trace_binder_txn_latency_free_enabled())
+		binder_txn_latency_free(t);
 	kfree(t);
 	binder_stats_deleted(BINDER_STAT_TRANSACTION);
 err_alloc_t_failed:
diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h
index 6731c3c..8eeccdc 100644
--- a/drivers/android/binder_trace.h
+++ b/drivers/android/binder_trace.h
@@ -95,6 +95,35 @@
 		  __entry->thread_todo)
 );
 
+TRACE_EVENT(binder_txn_latency_free,
+	TP_PROTO(struct binder_transaction *t,
+		 int from_proc, int from_thread,
+		 int to_proc, int to_thread),
+	TP_ARGS(t, from_proc, from_thread, to_proc, to_thread),
+	TP_STRUCT__entry(
+		__field(int, debug_id)
+		__field(int, from_proc)
+		__field(int, from_thread)
+		__field(int, to_proc)
+		__field(int, to_thread)
+		__field(unsigned int, code)
+		__field(unsigned int, flags)
+	),
+	TP_fast_assign(
+		__entry->debug_id = t->debug_id;
+		__entry->from_proc = from_proc;
+		__entry->from_thread = from_thread;
+		__entry->to_proc = to_proc;
+		__entry->to_thread = to_thread;
+		__entry->code = t->code;
+		__entry->flags = t->flags;
+	),
+	TP_printk("transaction=%d from %d:%d to %d:%d flags=0x%x code=0x%x",
+		  __entry->debug_id, __entry->from_proc, __entry->from_thread,
+		  __entry->to_proc, __entry->to_thread, __entry->code,
+		  __entry->flags)
+);
+
 TRACE_EVENT(binder_transaction,
 	TP_PROTO(bool reply, struct binder_transaction *t,
 		 struct binder_node *target_node),
-- 
1.7.9.5
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v10 3/3] binder: add transaction latency tracer
  2020-10-15 17:02                                                                           ` [PATCH v10 " Frankie Chang
  2020-10-15 17:02                                                                             ` [PATCH v10 1/3] binder: move structs from core file to header file Frankie Chang
  2020-10-15 17:02                                                                             ` [PATCH v10 2/3] binder: add trace at free transaction Frankie Chang
@ 2020-10-15 17:02                                                                             ` Frankie Chang
  2 siblings, 0 replies; 72+ messages in thread
From: Frankie Chang @ 2020-10-15 17:02 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: wsd_upstream, linux-kernel, Arve Hjønnevåg,
	Jian-Min Liu, linux-mediatek, Joel Fernandes, Frankie.Chang,
	Martijn Coenen, Christian Brauner, Todd Kjos

From: "Frankie.Chang" <Frankie.Chang@mediatek.com>

Record start/end timestamp for binder transaction.
When transaction is completed or transaction is free,
it wou