struct sched_attr sched_param;
struct trace_events *events;
enum timerlat_tracing_mode mode;
- struct actions actions;
+
+ struct actions threshold_actions;
+ struct actions end_actions;
+
union {
struct {
/* top only */
" --trace-buffer-size kB: set the per-cpu trace buffer size in kB",
" --deepest-idle-state n: only go down to idle state n on cpus used by timerlat to reduce exit from idle latency",
" --on-threshold <action>: define action to be executed at latency threshold, multiple are allowed",
+ " --on-end <action>: define action to be executed at measurement end, multiple are allowed",
NULL,
};
if (!params)
exit(1);
- actions_init(¶ms->actions);
+ actions_init(¶ms->threshold_actions);
+ actions_init(¶ms->end_actions);
/* disabled by default */
params->dma_latency = -1;
{"trace-buffer-size", required_argument, 0, '\3'},
{"deepest-idle-state", required_argument, 0, '\4'},
{"on-threshold", required_argument, 0, '\5'},
+ {"on-end", required_argument, 0, '\6'},
{0, 0, 0, 0}
};
params->deepest_idle_state = get_llong_from_str(optarg);
break;
case '\5':
- retval = actions_parse(¶ms->actions, optarg);
+ retval = actions_parse(¶ms->threshold_actions, optarg);
+ if (retval) {
+ err_msg("Invalid action %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case '\6':
+ retval = actions_parse(¶ms->end_actions, optarg);
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
}
if (trace_output)
- actions_add_trace_output(¶ms->actions, trace_output);
+ actions_add_trace_output(¶ms->threshold_actions, trace_output);
if (geteuid()) {
err_msg("rtla needs root permission\n");
* mixed mode
*/
if (params->mode == TRACING_MODE_BPF &&
- (params->actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa))
+ (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->end_actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa))
params->mode = TRACING_MODE_MIXED;
return params;
}
}
- if (params->actions.present[ACTION_TRACE_OUTPUT]) {
+ if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->end_actions.present[ACTION_TRACE_OUTPUT]) {
record = osnoise_init_trace_tool("timerlat");
if (!record) {
err_msg("Failed to enable the trace instance\n");
goto out_free;
}
- params->actions.trace_output_inst = record->trace.inst;
+ params->threshold_actions.trace_output_inst = record->trace.inst;
+ params->end_actions.trace_output_inst = record->trace.inst;
if (params->events) {
retval = trace_events_enable(&record->trace, params->events);
* tracing while enabling other instances. The trace instance is the
* one with most valuable information.
*/
- if (params->actions.present[ACTION_TRACE_OUTPUT])
+ if (record)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
}
if (osnoise_trace_is_off(tool, record)) {
- actions_perform(¶ms->actions);
+ actions_perform(¶ms->threshold_actions);
- if (!params->actions.continue_flag)
+ if (!params->threshold_actions.continue_flag)
/* continue flag not set, break */
break;
/* continue action reached, re-enable tracing */
- if (params->actions.present[ACTION_TRACE_OUTPUT])
+ if (record)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
if (!stop_tracing) {
/* Threshold overflow, perform actions on threshold */
- actions_perform(¶ms->actions);
+ actions_perform(¶ms->threshold_actions);
- if (!params->actions.continue_flag)
+ if (!params->threshold_actions.continue_flag)
/* continue flag not set, break */
break;
/* continue action reached, re-enable tracing */
- if (params->actions.present[ACTION_TRACE_OUTPUT])
+ if (record)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
timerlat_print_stats(params, tool);
+ actions_perform(¶ms->end_actions);
+
return_value = PASSED;
if (osnoise_trace_is_off(tool, record) && !stop_tracing) {
osnoise_destroy_tool(aa);
osnoise_destroy_tool(record);
osnoise_destroy_tool(tool);
- actions_destroy(¶ms->actions);
+ actions_destroy(¶ms->threshold_actions);
+ actions_destroy(¶ms->end_actions);
if (params->mode != TRACING_MODE_TRACEFS)
timerlat_bpf_destroy();
free(params);
" --trace-buffer-size kB: set the per-cpu trace buffer size in kB",
" --deepest-idle-state n: only go down to idle state n on cpus used by timerlat to reduce exit from idle latency",
" --on-threshold <action>: define action to be executed at latency threshold, multiple are allowed",
+ " --on-end: define action to be executed at measurement end, multiple are allowed",
NULL,
};
if (!params)
exit(1);
- actions_init(¶ms->actions);
+ actions_init(¶ms->threshold_actions);
+ actions_init(¶ms->end_actions);
/* disabled by default */
params->dma_latency = -1;
{"trace-buffer-size", required_argument, 0, '7'},
{"deepest-idle-state", required_argument, 0, '8'},
{"on-threshold", required_argument, 0, '9'},
+ {"on-end", required_argument, 0, '\1'},
{0, 0, 0, 0}
};
/* set trace */
trace_output = "timerlat_trace.txt";
+
break;
case '5':
/* it is here because it is similar to -a */
params->deepest_idle_state = get_llong_from_str(optarg);
break;
case '9':
- retval = actions_parse(¶ms->actions, optarg);
+ retval = actions_parse(¶ms->threshold_actions, optarg);
+ if (retval) {
+ err_msg("Invalid action %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case '\1':
+ retval = actions_parse(¶ms->end_actions, optarg);
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
}
if (trace_output)
- actions_add_trace_output(¶ms->actions, trace_output);
+ actions_add_trace_output(¶ms->threshold_actions, trace_output);
if (geteuid()) {
err_msg("rtla needs root permission\n");
* mixed mode
*/
if (params->mode == TRACING_MODE_BPF &&
- (params->actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa))
+ (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->end_actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa))
params->mode = TRACING_MODE_MIXED;
return params;
timerlat_print_stats(params, top);
if (osnoise_trace_is_off(top, record)) {
- actions_perform(¶ms->actions);
+ actions_perform(¶ms->threshold_actions);
- if (!params->actions.continue_flag)
+ if (!params->threshold_actions.continue_flag)
/* continue flag not set, break */
break;
/* continue action reached, re-enable tracing */
- if (params->actions.present[ACTION_TRACE_OUTPUT])
+ if (record)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
if (wait_retval == 1) {
/* Stopping requested by tracer */
- actions_perform(¶ms->actions);
+ actions_perform(¶ms->threshold_actions);
- if (!params->actions.continue_flag)
+ if (!params->threshold_actions.continue_flag)
/* continue flag not set, break */
break;
/* continue action reached, re-enable tracing */
- if (params->actions.present[ACTION_TRACE_OUTPUT])
+ if (record)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
}
}
- if (params->actions.present[ACTION_TRACE_OUTPUT]) {
+ if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->end_actions.present[ACTION_TRACE_OUTPUT]) {
record = osnoise_init_trace_tool("timerlat");
if (!record) {
err_msg("Failed to enable the trace instance\n");
goto out_free;
}
- params->actions.trace_output_inst = record->trace.inst;
+ params->threshold_actions.trace_output_inst = record->trace.inst;
+ params->end_actions.trace_output_inst = record->trace.inst;
if (params->events) {
retval = trace_events_enable(&record->trace, params->events);
* tracing while enabling other instances. The trace instance is the
* one with most valuable information.
*/
- if (params->actions.present[ACTION_TRACE_OUTPUT])
+ if (record)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
timerlat_print_stats(params, top);
+ actions_perform(¶ms->end_actions);
+
return_value = PASSED;
if (osnoise_trace_is_off(top, record) && !stop_tracing) {
osnoise_destroy_tool(aa);
osnoise_destroy_tool(record);
osnoise_destroy_tool(top);
- actions_destroy(¶ms->actions);
+ actions_destroy(¶ms->threshold_actions);
+ actions_destroy(¶ms->end_actions);
if (params->mode != TRACING_MODE_TRACEFS)
timerlat_bpf_destroy();
free(params);