Skip to content

Commit 54c53df

Browse files
committed
tracing: Add common_comm to histograms
If one wants to trace the name of the task that wakes up a process and pass that to the synthetic events, there's nothing currently that lets the synthetic events do that. Add a "common_comm" to the histogram logic that allows histograms save the current->comm as a variable that can be passed through and added to a synthetic event: # cd /sys/kernel/tracing # echo 's:wake_lat char[] waker; char[] wakee; u64 delta;' >> dynamic_events # echo 'hist:keys=pid:comm=common_comm:ts=common_timestamp.usecs if !(common_flags & 0x18)' > events/sched/sched_waking/trigger # echo 'hist:keys=next_pid:wake_comm=$comm:delta=common_timestamp.usecs-$ts:onmatch(sched.sched_waking).trace(wake_lat,$wake_comm,next_comm,$delta)' > events/sched/sched_switch/trigger The above will create a synthetic trace event that will save both the name of the waker and the wakee but only if the wakeup did not happen in a hard or soft interrupt context. The "common_comm" is used to save the task->comm at the time of the initial event and is passed via the "comm" variable to the second event, and that is saved as the "waker" field in the "wake_lat" synthetic event. Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Link: https://lore.kernel.org/20250407154912.3c6c6246@gandalf.local.home Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Reviewed-by: Tom Zanussi <zanussi@kernel.org> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
1 parent 7ab0fc6 commit 54c53df

1 file changed

Lines changed: 42 additions & 9 deletions

File tree

kernel/trace/trace_events_hist.c

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ enum hist_field_fn {
114114
HIST_FIELD_FN_BUCKET,
115115
HIST_FIELD_FN_TIMESTAMP,
116116
HIST_FIELD_FN_CPU,
117+
HIST_FIELD_FN_COMM,
117118
HIST_FIELD_FN_STRING,
118119
HIST_FIELD_FN_DYNSTRING,
119120
HIST_FIELD_FN_RELDYNSTRING,
@@ -506,6 +507,7 @@ enum hist_field_flags {
506507
HIST_FIELD_FL_CONST = 1 << 18,
507508
HIST_FIELD_FL_PERCENT = 1 << 19,
508509
HIST_FIELD_FL_GRAPH = 1 << 20,
510+
HIST_FIELD_FL_COMM = 1 << 21,
509511
};
510512

511513
struct var_defs {
@@ -885,6 +887,15 @@ static u64 hist_field_cpu(struct hist_field *hist_field,
885887
return cpu;
886888
}
887889

890+
static u64 hist_field_comm(struct hist_field *hist_field,
891+
struct tracing_map_elt *elt,
892+
struct trace_buffer *buffer,
893+
struct ring_buffer_event *rbe,
894+
void *event)
895+
{
896+
return (u64)(unsigned long)current->comm;
897+
}
898+
888899
/**
889900
* check_field_for_var_ref - Check if a VAR_REF field references a variable
890901
* @hist_field: The VAR_REF field to check
@@ -1338,6 +1349,8 @@ static const char *hist_field_name(struct hist_field *field,
13381349
field_name = hist_field_name(field->operands[0], ++level);
13391350
else if (field->flags & HIST_FIELD_FL_CPU)
13401351
field_name = "common_cpu";
1352+
else if (field->flags & HIST_FIELD_FL_COMM)
1353+
field_name = "common_comm";
13411354
else if (field->flags & HIST_FIELD_FL_EXPR ||
13421355
field->flags & HIST_FIELD_FL_VAR_REF) {
13431356
if (field->system) {
@@ -2015,6 +2028,13 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data,
20152028
goto out;
20162029
}
20172030

2031+
if (flags & HIST_FIELD_FL_COMM) {
2032+
hist_field->fn_num = HIST_FIELD_FN_COMM;
2033+
hist_field->size = MAX_FILTER_STR_VAL;
2034+
hist_field->type = "char[]";
2035+
goto out;
2036+
}
2037+
20182038
if (WARN_ON_ONCE(!field))
20192039
goto out;
20202040

@@ -2359,9 +2379,11 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
23592379
hist_data->attrs->ts_in_usecs = true;
23602380
} else if (strcmp(field_name, "common_stacktrace") == 0) {
23612381
*flags |= HIST_FIELD_FL_STACKTRACE;
2362-
} else if (strcmp(field_name, "common_cpu") == 0)
2382+
} else if (strcmp(field_name, "common_cpu") == 0) {
23632383
*flags |= HIST_FIELD_FL_CPU;
2364-
else if (strcmp(field_name, "hitcount") == 0)
2384+
} else if (strcmp(field_name, "common_comm") == 0) {
2385+
*flags |= HIST_FIELD_FL_COMM | HIST_FIELD_FL_STRING;
2386+
} else if (strcmp(field_name, "hitcount") == 0)
23652387
*flags |= HIST_FIELD_FL_HITCOUNT;
23662388
else {
23672389
field = trace_find_event_field(file->event_call, field_name);
@@ -2377,6 +2399,8 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
23772399
*flags |= HIST_FIELD_FL_CPU;
23782400
} else if (field && field->filter_type == FILTER_STACKTRACE) {
23792401
*flags |= HIST_FIELD_FL_STACKTRACE;
2402+
} else if (field && field->filter_type == FILTER_COMM) {
2403+
*flags |= HIST_FIELD_FL_COMM | HIST_FIELD_FL_STRING;
23802404
} else {
23812405
hist_err(tr, HIST_ERR_FIELD_NOT_FOUND,
23822406
errpos(field_name));
@@ -4327,6 +4351,8 @@ static u64 hist_fn_call(struct hist_field *hist_field,
43274351
return hist_field_timestamp(hist_field, elt, buffer, rbe, event);
43284352
case HIST_FIELD_FN_CPU:
43294353
return hist_field_cpu(hist_field, elt, buffer, rbe, event);
4354+
case HIST_FIELD_FN_COMM:
4355+
return hist_field_comm(hist_field, elt, buffer, rbe, event);
43304356
case HIST_FIELD_FN_STRING:
43314357
return hist_field_string(hist_field, elt, buffer, rbe, event);
43324358
case HIST_FIELD_FN_DYNSTRING:
@@ -5212,14 +5238,19 @@ static inline void add_to_key(char *compound_key, void *key,
52125238
size_t size = key_field->size;
52135239

52145240
if (key_field->flags & HIST_FIELD_FL_STRING) {
5215-
struct ftrace_event_field *field;
52165241

5217-
field = key_field->field;
5218-
if (field->filter_type == FILTER_DYN_STRING ||
5219-
field->filter_type == FILTER_RDYN_STRING)
5220-
size = *(u32 *)(rec + field->offset) >> 16;
5221-
else if (field->filter_type == FILTER_STATIC_STRING)
5222-
size = field->size;
5242+
if (key_field->flags & HIST_FIELD_FL_COMM) {
5243+
size = strlen((char *)key);
5244+
} else {
5245+
struct ftrace_event_field *field;
5246+
5247+
field = key_field->field;
5248+
if (field->filter_type == FILTER_DYN_STRING ||
5249+
field->filter_type == FILTER_RDYN_STRING)
5250+
size = *(u32 *)(rec + field->offset) >> 16;
5251+
else if (field->filter_type == FILTER_STATIC_STRING)
5252+
size = field->size;
5253+
}
52235254

52245255
/* ensure NULL-termination */
52255256
if (size > key_field->size - 1)
@@ -6097,6 +6128,8 @@ static void hist_field_print(struct seq_file *m, struct hist_field *hist_field)
60976128

60986129
if (hist_field->flags & HIST_FIELD_FL_CPU)
60996130
seq_puts(m, "common_cpu");
6131+
if (hist_field->flags & HIST_FIELD_FL_COMM)
6132+
seq_puts(m, "common_comm");
61006133
else if (hist_field->flags & HIST_FIELD_FL_CONST)
61016134
seq_printf(m, "%llu", hist_field->constant);
61026135
else if (field_name) {

0 commit comments

Comments
 (0)