Re: [PATCH v7 2/2] perf/core: add mux switch to skip to the current CPU's events list on mux interrupt

2017-08-23 Thread Alexey Budankov
On 23.08.2017 14:54, Alexander Shishkin wrote:
> Alexey Budankov  writes:
> 
>> This patch implements mux switch that triggers skipping to the 
>> current CPU's events list at mulitplexing hrtimer interrupt 
>> handler as well as adoption of the switch in the existing 
>> implementation.
>>
>> perf_event_groups_iterate_cpu() API is introduced to implement 
>> iteration thru the certain CPU groups list skipping groups 
> 
> "through"
> 
>> allocated for the other CPUs.
>>
>> Signed-off-by: Alexey Budankov 
>> ---
>>  kernel/events/core.c | 193 
>> ---
>>  1 file changed, 137 insertions(+), 56 deletions(-)
>>
>> diff --git a/kernel/events/core.c b/kernel/events/core.c
>> index 08ccfb2..aeb0f81 100644
>> --- a/kernel/events/core.c
>> +++ b/kernel/events/core.c
>> @@ -556,11 +556,11 @@ void perf_sample_event_took(u64 sample_len_ns)
>>  static atomic64_t perf_event_id;
>>  
>>  static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
>> -  enum event_type_t event_type);
>> +  enum event_type_t event_type, int mux);
>>  
>>  static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
>>   enum event_type_t event_type,
>> - struct task_struct *task);
>> + struct task_struct *task, int mux);
>>  
>>  static void update_context_time(struct perf_event_context *ctx);
>>  static u64 perf_event_time(struct perf_event *event);
>> @@ -702,6 +702,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
>> int mode)
>>  struct perf_cpu_context *cpuctx;
>>  struct list_head *list;
>>  unsigned long flags;
>> +int mux = 0;
>>  
>>  /*
>>   * Disable interrupts and preemption to avoid this CPU's
>> @@ -717,7 +718,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
>> int mode)
>>  perf_pmu_disable(cpuctx->ctx.pmu);
>>  
>>  if (mode & PERF_CGROUP_SWOUT) {
>> -cpu_ctx_sched_out(cpuctx, EVENT_ALL);
>> +cpu_ctx_sched_out(cpuctx, EVENT_ALL, mux);
>>  /*
>>   * must not be done before ctxswout due
>>   * to event_filter_match() in event_sched_out()
>> @@ -736,7 +737,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
>> int mode)
>>   */
>>  cpuctx->cgrp = perf_cgroup_from_task(task,
>>   >ctx);
>> -cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
>> +cpu_ctx_sched_in(cpuctx, EVENT_ALL, task, mux);
> 
> 'mux' is always zero in this function, isn't it?
> 
>>  }
>>  perf_pmu_enable(cpuctx->ctx.pmu);
>>  perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
>> @@ -1613,8 +1614,16 @@ perf_event_groups_rotate(struct rb_root *groups, int 
>> cpu)
>>   */
>>  #define perf_event_groups_for_each(event, iter, tree, node, list, link) \
>> for (iter = rb_first(tree); iter; iter = rb_next(iter))  \
>> -list_for_each_entry(event, &(rb_entry(iter, \
>> -typeof(*event), node)->list), link)
>> +list_for_each_entry(event, &(rb_entry(iter, \
>> +typeof(*event), node)->list), link)
> 
> Is this an indentation change? What is it doing here?
> 
>> +
>> +/*
>> + * Iterate event groups related to specific cpu.
>> + */
>> +#define perf_event_groups_for_each_cpu(event, cpu, tree, list, link)
>> \
>> +list = perf_event_groups_get_list(tree, cpu);   \
>> +if (list)   \
>> +list_for_each_entry(event, list, link)
> 
> ..or not, if there's no list.
> 
>>  
>>  /*
>>   * Add a event from the lists for its context.
>> @@ -2397,36 +2406,38 @@ static void add_event_to_ctx(struct perf_event 
>> *event,
>>  
>>  static void ctx_sched_out(struct perf_event_context *ctx,
>>struct perf_cpu_context *cpuctx,
>> -  enum event_type_t event_type);
>> +  enum event_type_t event_type, int mux);
>>  static void
>>  ctx_sched_in(struct perf_event_context *ctx,
>>   struct perf_cpu_context *cpuctx,
>>   enum event_type_t event_type,
>> - struct task_struct *task);
>> + struct task_struct *task, int mux);
>>  
>>  static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
>> struct perf_event_context *ctx,
>> enum event_type_t event_type)
>>  {
>> +int mux = 0;
>> +
>>  if (!cpuctx->task_ctx)
>>  return;
>>  
>>  if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
>>  return;
>>  
>> -ctx_sched_out(ctx, cpuctx, event_type);

Re: [PATCH v7 2/2] perf/core: add mux switch to skip to the current CPU's events list on mux interrupt

2017-08-23 Thread Alexey Budankov
On 23.08.2017 14:54, Alexander Shishkin wrote:
> Alexey Budankov  writes:
> 
>> This patch implements mux switch that triggers skipping to the 
>> current CPU's events list at mulitplexing hrtimer interrupt 
>> handler as well as adoption of the switch in the existing 
>> implementation.
>>
>> perf_event_groups_iterate_cpu() API is introduced to implement 
>> iteration thru the certain CPU groups list skipping groups 
> 
> "through"
> 
>> allocated for the other CPUs.
>>
>> Signed-off-by: Alexey Budankov 
>> ---
>>  kernel/events/core.c | 193 
>> ---
>>  1 file changed, 137 insertions(+), 56 deletions(-)
>>
>> diff --git a/kernel/events/core.c b/kernel/events/core.c
>> index 08ccfb2..aeb0f81 100644
>> --- a/kernel/events/core.c
>> +++ b/kernel/events/core.c
>> @@ -556,11 +556,11 @@ void perf_sample_event_took(u64 sample_len_ns)
>>  static atomic64_t perf_event_id;
>>  
>>  static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
>> -  enum event_type_t event_type);
>> +  enum event_type_t event_type, int mux);
>>  
>>  static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
>>   enum event_type_t event_type,
>> - struct task_struct *task);
>> + struct task_struct *task, int mux);
>>  
>>  static void update_context_time(struct perf_event_context *ctx);
>>  static u64 perf_event_time(struct perf_event *event);
>> @@ -702,6 +702,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
>> int mode)
>>  struct perf_cpu_context *cpuctx;
>>  struct list_head *list;
>>  unsigned long flags;
>> +int mux = 0;
>>  
>>  /*
>>   * Disable interrupts and preemption to avoid this CPU's
>> @@ -717,7 +718,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
>> int mode)
>>  perf_pmu_disable(cpuctx->ctx.pmu);
>>  
>>  if (mode & PERF_CGROUP_SWOUT) {
>> -cpu_ctx_sched_out(cpuctx, EVENT_ALL);
>> +cpu_ctx_sched_out(cpuctx, EVENT_ALL, mux);
>>  /*
>>   * must not be done before ctxswout due
>>   * to event_filter_match() in event_sched_out()
>> @@ -736,7 +737,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
>> int mode)
>>   */
>>  cpuctx->cgrp = perf_cgroup_from_task(task,
>>   >ctx);
>> -cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
>> +cpu_ctx_sched_in(cpuctx, EVENT_ALL, task, mux);
> 
> 'mux' is always zero in this function, isn't it?
> 
>>  }
>>  perf_pmu_enable(cpuctx->ctx.pmu);
>>  perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
>> @@ -1613,8 +1614,16 @@ perf_event_groups_rotate(struct rb_root *groups, int 
>> cpu)
>>   */
>>  #define perf_event_groups_for_each(event, iter, tree, node, list, link) \
>> for (iter = rb_first(tree); iter; iter = rb_next(iter))  \
>> -list_for_each_entry(event, &(rb_entry(iter, \
>> -typeof(*event), node)->list), link)
>> +list_for_each_entry(event, &(rb_entry(iter, \
>> +typeof(*event), node)->list), link)
> 
> Is this an indentation change? What is it doing here?
> 
>> +
>> +/*
>> + * Iterate event groups related to specific cpu.
>> + */
>> +#define perf_event_groups_for_each_cpu(event, cpu, tree, list, link)
>> \
>> +list = perf_event_groups_get_list(tree, cpu);   \
>> +if (list)   \
>> +list_for_each_entry(event, list, link)
> 
> ..or not, if there's no list.
> 
>>  
>>  /*
>>   * Add a event from the lists for its context.
>> @@ -2397,36 +2406,38 @@ static void add_event_to_ctx(struct perf_event 
>> *event,
>>  
>>  static void ctx_sched_out(struct perf_event_context *ctx,
>>struct perf_cpu_context *cpuctx,
>> -  enum event_type_t event_type);
>> +  enum event_type_t event_type, int mux);
>>  static void
>>  ctx_sched_in(struct perf_event_context *ctx,
>>   struct perf_cpu_context *cpuctx,
>>   enum event_type_t event_type,
>> - struct task_struct *task);
>> + struct task_struct *task, int mux);
>>  
>>  static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
>> struct perf_event_context *ctx,
>> enum event_type_t event_type)
>>  {
>> +int mux = 0;
>> +
>>  if (!cpuctx->task_ctx)
>>  return;
>>  
>>  if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
>>  return;
>>  
>> -ctx_sched_out(ctx, cpuctx, event_type);
>> +ctx_sched_out(ctx, cpuctx, event_type, mux);
> 
> Just use 

Re: [PATCH v7 2/2] perf/core: add mux switch to skip to the current CPU's events list on mux interrupt

2017-08-23 Thread Alexander Shishkin
Alexey Budankov  writes:

> This patch implements mux switch that triggers skipping to the 
> current CPU's events list at mulitplexing hrtimer interrupt 
> handler as well as adoption of the switch in the existing 
> implementation.
>
> perf_event_groups_iterate_cpu() API is introduced to implement 
> iteration thru the certain CPU groups list skipping groups 

"through"

> allocated for the other CPUs.
>
> Signed-off-by: Alexey Budankov 
> ---
>  kernel/events/core.c | 193 
> ---
>  1 file changed, 137 insertions(+), 56 deletions(-)
>
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 08ccfb2..aeb0f81 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -556,11 +556,11 @@ void perf_sample_event_took(u64 sample_len_ns)
>  static atomic64_t perf_event_id;
>  
>  static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
> -   enum event_type_t event_type);
> +   enum event_type_t event_type, int mux);
>  
>  static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
>enum event_type_t event_type,
> -  struct task_struct *task);
> +  struct task_struct *task, int mux);
>  
>  static void update_context_time(struct perf_event_context *ctx);
>  static u64 perf_event_time(struct perf_event *event);
> @@ -702,6 +702,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
> int mode)
>   struct perf_cpu_context *cpuctx;
>   struct list_head *list;
>   unsigned long flags;
> + int mux = 0;
>  
>   /*
>* Disable interrupts and preemption to avoid this CPU's
> @@ -717,7 +718,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
> int mode)
>   perf_pmu_disable(cpuctx->ctx.pmu);
>  
>   if (mode & PERF_CGROUP_SWOUT) {
> - cpu_ctx_sched_out(cpuctx, EVENT_ALL);
> + cpu_ctx_sched_out(cpuctx, EVENT_ALL, mux);
>   /*
>* must not be done before ctxswout due
>* to event_filter_match() in event_sched_out()
> @@ -736,7 +737,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
> int mode)
>*/
>   cpuctx->cgrp = perf_cgroup_from_task(task,
>>ctx);
> - cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
> + cpu_ctx_sched_in(cpuctx, EVENT_ALL, task, mux);

'mux' is always zero in this function, isn't it?

>   }
>   perf_pmu_enable(cpuctx->ctx.pmu);
>   perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
> @@ -1613,8 +1614,16 @@ perf_event_groups_rotate(struct rb_root *groups, int 
> cpu)
>   */
>  #define perf_event_groups_for_each(event, iter, tree, node, list, link) \
>  for (iter = rb_first(tree); iter; iter = rb_next(iter))  \
> - list_for_each_entry(event, &(rb_entry(iter, \
> - typeof(*event), node)->list), link)
> + list_for_each_entry(event, &(rb_entry(iter, \
> + typeof(*event), node)->list), link)

Is this an indentation change? What is it doing here?

> +
> +/*
> + * Iterate event groups related to specific cpu.
> + */
> +#define perf_event_groups_for_each_cpu(event, cpu, tree, list, link) \
> + list = perf_event_groups_get_list(tree, cpu);   \
> + if (list)   \
> + list_for_each_entry(event, list, link)

..or not, if there's no list.

>  
>  /*
>   * Add a event from the lists for its context.
> @@ -2397,36 +2406,38 @@ static void add_event_to_ctx(struct perf_event *event,
>  
>  static void ctx_sched_out(struct perf_event_context *ctx,
> struct perf_cpu_context *cpuctx,
> -   enum event_type_t event_type);
> +   enum event_type_t event_type, int mux);
>  static void
>  ctx_sched_in(struct perf_event_context *ctx,
>struct perf_cpu_context *cpuctx,
>enum event_type_t event_type,
> -  struct task_struct *task);
> +  struct task_struct *task, int mux);
>  
>  static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
>  struct perf_event_context *ctx,
>  enum event_type_t event_type)
>  {
> + int mux = 0;
> +
>   if (!cpuctx->task_ctx)
>   return;
>  
>   if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
>   return;
>  
> - ctx_sched_out(ctx, cpuctx, event_type);
> + ctx_sched_out(ctx, cpuctx, event_type, mux);

Just use 0.

>  }
>  
>  static void perf_event_sched_in(struct perf_cpu_context *cpuctx,
>  

Re: [PATCH v7 2/2] perf/core: add mux switch to skip to the current CPU's events list on mux interrupt

2017-08-23 Thread Alexander Shishkin
Alexey Budankov  writes:

> This patch implements mux switch that triggers skipping to the 
> current CPU's events list at mulitplexing hrtimer interrupt 
> handler as well as adoption of the switch in the existing 
> implementation.
>
> perf_event_groups_iterate_cpu() API is introduced to implement 
> iteration thru the certain CPU groups list skipping groups 

"through"

> allocated for the other CPUs.
>
> Signed-off-by: Alexey Budankov 
> ---
>  kernel/events/core.c | 193 
> ---
>  1 file changed, 137 insertions(+), 56 deletions(-)
>
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 08ccfb2..aeb0f81 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -556,11 +556,11 @@ void perf_sample_event_took(u64 sample_len_ns)
>  static atomic64_t perf_event_id;
>  
>  static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
> -   enum event_type_t event_type);
> +   enum event_type_t event_type, int mux);
>  
>  static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
>enum event_type_t event_type,
> -  struct task_struct *task);
> +  struct task_struct *task, int mux);
>  
>  static void update_context_time(struct perf_event_context *ctx);
>  static u64 perf_event_time(struct perf_event *event);
> @@ -702,6 +702,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
> int mode)
>   struct perf_cpu_context *cpuctx;
>   struct list_head *list;
>   unsigned long flags;
> + int mux = 0;
>  
>   /*
>* Disable interrupts and preemption to avoid this CPU's
> @@ -717,7 +718,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
> int mode)
>   perf_pmu_disable(cpuctx->ctx.pmu);
>  
>   if (mode & PERF_CGROUP_SWOUT) {
> - cpu_ctx_sched_out(cpuctx, EVENT_ALL);
> + cpu_ctx_sched_out(cpuctx, EVENT_ALL, mux);
>   /*
>* must not be done before ctxswout due
>* to event_filter_match() in event_sched_out()
> @@ -736,7 +737,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
> int mode)
>*/
>   cpuctx->cgrp = perf_cgroup_from_task(task,
>>ctx);
> - cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
> + cpu_ctx_sched_in(cpuctx, EVENT_ALL, task, mux);

'mux' is always zero in this function, isn't it?

>   }
>   perf_pmu_enable(cpuctx->ctx.pmu);
>   perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
> @@ -1613,8 +1614,16 @@ perf_event_groups_rotate(struct rb_root *groups, int 
> cpu)
>   */
>  #define perf_event_groups_for_each(event, iter, tree, node, list, link) \
>  for (iter = rb_first(tree); iter; iter = rb_next(iter))  \
> - list_for_each_entry(event, &(rb_entry(iter, \
> - typeof(*event), node)->list), link)
> + list_for_each_entry(event, &(rb_entry(iter, \
> + typeof(*event), node)->list), link)

Is this an indentation change? What is it doing here?

> +
> +/*
> + * Iterate event groups related to specific cpu.
> + */
> +#define perf_event_groups_for_each_cpu(event, cpu, tree, list, link) \
> + list = perf_event_groups_get_list(tree, cpu);   \
> + if (list)   \
> + list_for_each_entry(event, list, link)

..or not, if there's no list.

>  
>  /*
>   * Add a event from the lists for its context.
> @@ -2397,36 +2406,38 @@ static void add_event_to_ctx(struct perf_event *event,
>  
>  static void ctx_sched_out(struct perf_event_context *ctx,
> struct perf_cpu_context *cpuctx,
> -   enum event_type_t event_type);
> +   enum event_type_t event_type, int mux);
>  static void
>  ctx_sched_in(struct perf_event_context *ctx,
>struct perf_cpu_context *cpuctx,
>enum event_type_t event_type,
> -  struct task_struct *task);
> +  struct task_struct *task, int mux);
>  
>  static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
>  struct perf_event_context *ctx,
>  enum event_type_t event_type)
>  {
> + int mux = 0;
> +
>   if (!cpuctx->task_ctx)
>   return;
>  
>   if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
>   return;
>  
> - ctx_sched_out(ctx, cpuctx, event_type);
> + ctx_sched_out(ctx, cpuctx, event_type, mux);

Just use 0.

>  }
>  
>  static void perf_event_sched_in(struct perf_cpu_context *cpuctx,
>   struct perf_event_context *ctx,
> -  

[PATCH v7 2/2] perf/core: add mux switch to skip to the current CPU's events list on mux interrupt

2017-08-17 Thread Alexey Budankov
This patch implements mux switch that triggers skipping to the 
current CPU's events list at mulitplexing hrtimer interrupt 
handler as well as adoption of the switch in the existing 
implementation.

perf_event_groups_iterate_cpu() API is introduced to implement 
iteration thru the certain CPU groups list skipping groups 
allocated for the other CPUs.

Signed-off-by: Alexey Budankov 
---
 kernel/events/core.c | 193 ---
 1 file changed, 137 insertions(+), 56 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 08ccfb2..aeb0f81 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -556,11 +556,11 @@ void perf_sample_event_took(u64 sample_len_ns)
 static atomic64_t perf_event_id;
 
 static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
- enum event_type_t event_type);
+ enum event_type_t event_type, int mux);
 
 static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
 enum event_type_t event_type,
-struct task_struct *task);
+struct task_struct *task, int mux);
 
 static void update_context_time(struct perf_event_context *ctx);
 static u64 perf_event_time(struct perf_event *event);
@@ -702,6 +702,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
int mode)
struct perf_cpu_context *cpuctx;
struct list_head *list;
unsigned long flags;
+   int mux = 0;
 
/*
 * Disable interrupts and preemption to avoid this CPU's
@@ -717,7 +718,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
int mode)
perf_pmu_disable(cpuctx->ctx.pmu);
 
if (mode & PERF_CGROUP_SWOUT) {
-   cpu_ctx_sched_out(cpuctx, EVENT_ALL);
+   cpu_ctx_sched_out(cpuctx, EVENT_ALL, mux);
/*
 * must not be done before ctxswout due
 * to event_filter_match() in event_sched_out()
@@ -736,7 +737,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
int mode)
 */
cpuctx->cgrp = perf_cgroup_from_task(task,
 >ctx);
-   cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
+   cpu_ctx_sched_in(cpuctx, EVENT_ALL, task, mux);
}
perf_pmu_enable(cpuctx->ctx.pmu);
perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
@@ -1613,8 +1614,16 @@ perf_event_groups_rotate(struct rb_root *groups, int cpu)
  */
 #define perf_event_groups_for_each(event, iter, tree, node, list, link) \
   for (iter = rb_first(tree); iter; iter = rb_next(iter))  \
-   list_for_each_entry(event, &(rb_entry(iter, \
-   typeof(*event), node)->list), link)
+   list_for_each_entry(event, &(rb_entry(iter, \
+   typeof(*event), node)->list), link)
+
+/*
+ * Iterate event groups related to specific cpu.
+ */
+#define perf_event_groups_for_each_cpu(event, cpu, tree, list, link)   \
+   list = perf_event_groups_get_list(tree, cpu);   \
+   if (list)   \
+   list_for_each_entry(event, list, link)
 
 /*
  * Add a event from the lists for its context.
@@ -2397,36 +2406,38 @@ static void add_event_to_ctx(struct perf_event *event,
 
 static void ctx_sched_out(struct perf_event_context *ctx,
  struct perf_cpu_context *cpuctx,
- enum event_type_t event_type);
+ enum event_type_t event_type, int mux);
 static void
 ctx_sched_in(struct perf_event_context *ctx,
 struct perf_cpu_context *cpuctx,
 enum event_type_t event_type,
-struct task_struct *task);
+struct task_struct *task, int mux);
 
 static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
   struct perf_event_context *ctx,
   enum event_type_t event_type)
 {
+   int mux = 0;
+
if (!cpuctx->task_ctx)
return;
 
if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
return;
 
-   ctx_sched_out(ctx, cpuctx, event_type);
+   ctx_sched_out(ctx, cpuctx, event_type, mux);
 }
 
 static void perf_event_sched_in(struct perf_cpu_context *cpuctx,
struct perf_event_context *ctx,
-   struct task_struct *task)
+   struct task_struct *task, int mux)
 {
-   cpu_ctx_sched_in(cpuctx, EVENT_PINNED, task);
+   cpu_ctx_sched_in(cpuctx, EVENT_PINNED, task, mux);
if (ctx)
-   

[PATCH v7 2/2] perf/core: add mux switch to skip to the current CPU's events list on mux interrupt

2017-08-17 Thread Alexey Budankov
This patch implements mux switch that triggers skipping to the 
current CPU's events list at mulitplexing hrtimer interrupt 
handler as well as adoption of the switch in the existing 
implementation.

perf_event_groups_iterate_cpu() API is introduced to implement 
iteration thru the certain CPU groups list skipping groups 
allocated for the other CPUs.

Signed-off-by: Alexey Budankov 
---
 kernel/events/core.c | 193 ---
 1 file changed, 137 insertions(+), 56 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 08ccfb2..aeb0f81 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -556,11 +556,11 @@ void perf_sample_event_took(u64 sample_len_ns)
 static atomic64_t perf_event_id;
 
 static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
- enum event_type_t event_type);
+ enum event_type_t event_type, int mux);
 
 static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
 enum event_type_t event_type,
-struct task_struct *task);
+struct task_struct *task, int mux);
 
 static void update_context_time(struct perf_event_context *ctx);
 static u64 perf_event_time(struct perf_event *event);
@@ -702,6 +702,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
int mode)
struct perf_cpu_context *cpuctx;
struct list_head *list;
unsigned long flags;
+   int mux = 0;
 
/*
 * Disable interrupts and preemption to avoid this CPU's
@@ -717,7 +718,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
int mode)
perf_pmu_disable(cpuctx->ctx.pmu);
 
if (mode & PERF_CGROUP_SWOUT) {
-   cpu_ctx_sched_out(cpuctx, EVENT_ALL);
+   cpu_ctx_sched_out(cpuctx, EVENT_ALL, mux);
/*
 * must not be done before ctxswout due
 * to event_filter_match() in event_sched_out()
@@ -736,7 +737,7 @@ static void perf_cgroup_switch(struct task_struct *task, 
int mode)
 */
cpuctx->cgrp = perf_cgroup_from_task(task,
 >ctx);
-   cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
+   cpu_ctx_sched_in(cpuctx, EVENT_ALL, task, mux);
}
perf_pmu_enable(cpuctx->ctx.pmu);
perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
@@ -1613,8 +1614,16 @@ perf_event_groups_rotate(struct rb_root *groups, int cpu)
  */
 #define perf_event_groups_for_each(event, iter, tree, node, list, link) \
   for (iter = rb_first(tree); iter; iter = rb_next(iter))  \
-   list_for_each_entry(event, &(rb_entry(iter, \
-   typeof(*event), node)->list), link)
+   list_for_each_entry(event, &(rb_entry(iter, \
+   typeof(*event), node)->list), link)
+
+/*
+ * Iterate event groups related to specific cpu.
+ */
+#define perf_event_groups_for_each_cpu(event, cpu, tree, list, link)   \
+   list = perf_event_groups_get_list(tree, cpu);   \
+   if (list)   \
+   list_for_each_entry(event, list, link)
 
 /*
  * Add a event from the lists for its context.
@@ -2397,36 +2406,38 @@ static void add_event_to_ctx(struct perf_event *event,
 
 static void ctx_sched_out(struct perf_event_context *ctx,
  struct perf_cpu_context *cpuctx,
- enum event_type_t event_type);
+ enum event_type_t event_type, int mux);
 static void
 ctx_sched_in(struct perf_event_context *ctx,
 struct perf_cpu_context *cpuctx,
 enum event_type_t event_type,
-struct task_struct *task);
+struct task_struct *task, int mux);
 
 static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
   struct perf_event_context *ctx,
   enum event_type_t event_type)
 {
+   int mux = 0;
+
if (!cpuctx->task_ctx)
return;
 
if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
return;
 
-   ctx_sched_out(ctx, cpuctx, event_type);
+   ctx_sched_out(ctx, cpuctx, event_type, mux);
 }
 
 static void perf_event_sched_in(struct perf_cpu_context *cpuctx,
struct perf_event_context *ctx,
-   struct task_struct *task)
+   struct task_struct *task, int mux)
 {
-   cpu_ctx_sched_in(cpuctx, EVENT_PINNED, task);
+   cpu_ctx_sched_in(cpuctx, EVENT_PINNED, task, mux);
if (ctx)
-   ctx_sched_in(ctx, cpuctx, EVENT_PINNED, task);