Skip to content

Commit

Permalink
trace,smp: Add tracepoints for scheduling remotelly called functions
Browse files Browse the repository at this point in the history
Add a tracepoint for when a CSD is queued to a remote CPU's
call_single_queue. This allows finding exactly which CPU queued a given CSD
when looking at a csd_function_{entry,exit} event, and also enables us to
accurately measure IPI delivery time with e.g. a synthetic event:

  $ echo 'hist:keys=cpu,csd.hex:ts=common_timestamp.usecs' >\
      /sys/kernel/tracing/events/smp/csd_queue_cpu/trigger
  $ echo 'csd_latency unsigned int dst_cpu; unsigned long csd; u64 time' >\
      /sys/kernel/tracing/synthetic_events
  $ echo \
  'hist:keys=common_cpu,csd.hex:'\
  'time=common_timestamp.usecs-$ts:'\
  'onmatch(smp.csd_queue_cpu).trace(csd_latency,common_cpu,csd,$time)' >\
      /sys/kernel/tracing/events/smp/csd_function_entry/trigger

  $ trace-cmd record -e 'synthetic:csd_latency' hackbench
  $ trace-cmd report
  <...>-467   [001]    21.824263: csd_queue_cpu:        cpu=0 callsite=try_to_wake_up+0x2ea func=sched_ttwu_pending csd=0xffff8880076148b8
  <...>-467   [001]    21.824280: ipi_send_cpu:         cpu=0 callsite=try_to_wake_up+0x2ea callback=generic_smp_call_function_single_interrupt+0x0
  <...>-489   [000]    21.824299: csd_function_entry:   func=sched_ttwu_pending csd=0xffff8880076148b8
  <...>-489   [000]    21.824320: csd_latency:          dst_cpu=0, csd=18446612682193848504, time=36

Suggested-by: Valentin Schneider <[email protected]>
Signed-off-by: Leonardo Bras <[email protected]>
Tested-and-reviewed-by: Valentin Schneider <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
  • Loading branch information
Leonardo Bras authored and Peter Zijlstra committed Jun 16, 2023
1 parent 949fa3f commit bf5a8c2
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 11 deletions.
27 changes: 27 additions & 0 deletions include/trace/events/csd.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,33 @@

#include <linux/tracepoint.h>

TRACE_EVENT(csd_queue_cpu,

TP_PROTO(const unsigned int cpu,
unsigned long callsite,
smp_call_func_t func,
struct __call_single_data *csd),

TP_ARGS(cpu, callsite, func, csd),

TP_STRUCT__entry(
__field(unsigned int, cpu)
__field(void *, callsite)
__field(void *, func)
__field(void *, csd)
),

TP_fast_assign(
__entry->cpu = cpu;
__entry->callsite = (void *)callsite;
__entry->func = func;
__entry->csd = csd;
),

TP_printk("cpu=%u callsite=%pS func=%ps csd=%p",
__entry->cpu, __entry->callsite, __entry->func, __entry->csd)
);

/*
* Tracepoints for a function which is called as an effect of smp_call_function.*
*/
Expand Down
16 changes: 5 additions & 11 deletions kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,15 +340,15 @@ void __smp_call_single_queue(int cpu, struct llist_node *node)
* even if we haven't sent the smp_call IPI yet (e.g. the stopper
* executes migration_cpu_stop() on the remote CPU).
*/
if (trace_ipi_send_cpu_enabled()) {
if (trace_csd_queue_cpu_enabled()) {
call_single_data_t *csd;
smp_call_func_t func;

csd = container_of(node, call_single_data_t, node.llist);
func = CSD_TYPE(csd) == CSD_TYPE_TTWU ?
sched_ttwu_pending : csd->func;

trace_ipi_send_cpu(cpu, _RET_IP_, func);
trace_csd_queue_cpu(cpu, _RET_IP_, func, csd);
}

/*
Expand Down Expand Up @@ -741,7 +741,7 @@ static void smp_call_function_many_cond(const struct cpumask *mask,
int cpu, last_cpu, this_cpu = smp_processor_id();
struct call_function_data *cfd;
bool wait = scf_flags & SCF_WAIT;
int nr_cpus = 0, nr_queued = 0;
int nr_cpus = 0;
bool run_remote = false;
bool run_local = false;

Expand Down Expand Up @@ -799,21 +799,15 @@ static void smp_call_function_many_cond(const struct cpumask *mask,
csd->node.src = smp_processor_id();
csd->node.dst = cpu;
#endif
trace_csd_queue_cpu(cpu, _RET_IP_, func, csd);

if (llist_add(&csd->node.llist, &per_cpu(call_single_queue, cpu))) {
__cpumask_set_cpu(cpu, cfd->cpumask_ipi);
nr_cpus++;
last_cpu = cpu;
}
nr_queued++;
}

/*
* Trace each smp_function_call_*() as an IPI, actual IPIs
* will be traced with func==generic_smp_call_function_single_ipi().
*/
if (nr_queued)
trace_ipi_send_cpumask(cfd->cpumask, _RET_IP_, func);

/*
* Choose the most efficient way to send an IPI. Note that the
* number of CPUs might be zero due to concurrent changes to the
Expand Down

0 comments on commit bf5a8c2

Please sign in to comment.