With the new mechanism that is used to describe a scenario, it becomes more complex to estimate how many logs will be generated during the execution of a use case. As a result, the record of the logs in temporary buffer had been disable and the logs were saved directly in files. The potential side effect of such mecanism is to block threads on io access, which disturbs the use case behavior.
A new parameter is added to define the saving policy of the logs. You can now disable the logs, save them directly in a file like previously, define the size of a temporary buffer but with the risk to lost some logs if the buffer overflow. You can also ask rt-app to evaluate how many logs will be generated and allocate the temporary buffer accordingly. This last mode is not yet implemented and it will be part of a dedicated patch.
Full details of the new parameter is available in the update of the documentation
Signed-off-by: Vincent Guittot vincent.guittot@linaro.org --- doc/tutorial.txt | 15 ++++++++++++++ src/rt-app.c | 34 +++++++++++++++++++++++-------- src/rt-app_parse_config.c | 51 ++++++++++++++++++++++++++++++++++++++--------- src/rt-app_types.h | 1 + 4 files changed, 84 insertions(+), 17 deletions(-)
diff --git a/doc/tutorial.txt b/doc/tutorial.txt index 12aba47..8341b2e 100644 --- a/doc/tutorial.txt +++ b/doc/tutorial.txt @@ -61,6 +61,20 @@ the current directory (./). * log_basename : Text. Prefix used for all log files of the use case. "rt-app-" is used by default.
+* log_size : String or Integer. A Integer defines a fix size in MB of the +temporary buffer (size per thread) that will be used to store the log data +before saving them in a file. This temporary buffer is used as a cicular +buffer so the oldest data will be lost in case of overflow. A string is used +to set a predifined behavior: + - "file" will be used to store the log data directly in the file without + using a temporary buffer. + - "Disable" will disable the log mecahnism. + - "Auto" will let rt-app compute the buffer size to not overflow the latter + during the use case. +The use of a temporary buffer prevents the threads of unexpected wait during +io access. The "Auto" mode is not implemented yet and fallback to "file" mode +for the moment. + * ftrace: Boolean. If enable, rt-app logs in ftrace the main events of the use case. Default value is False.
@@ -75,6 +89,7 @@ each threads (see gnuplot section for more details). Default value is False. "pi_enabled" : false, "lock_pages" : false, "logdir" : "./", + "log_size" : "file", "log_basename" : "rt-app", "ftrace" : false, "gnuplot" : false, diff --git a/src/rt-app.c b/src/rt-app.c index 6a27308..805cc35 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -391,10 +391,11 @@ void *thread_body(void *arg) timing_point_t *curr_timing; timing_point_t *timings; timing_point_t tmp_timing; + unsigned int timings_size, timing_loop; pid_t tid; struct sched_attr attr; unsigned int flags = 0; - int ret, i, j, loop; + int ret, i, j, loop, idx;
/* Set thread name */ ret = pthread_setname_np(pthread_self(), data->name); @@ -488,6 +489,15 @@ void *thread_body(void *arg) exit(EXIT_FAILURE); }
+ if (opts.logsize > 0) { + timings = malloc(opts.logsize); + timings_size = opts.logsize / sizeof(timing_point_t); + } else { + timings = NULL; + timings_size = 0; + } + timing_loop = 0; + /* Lock pages */ if (data->lock_pages == 1) { @@ -502,8 +512,6 @@ void *thread_body(void *arg)
log_notice("[%d] starting thread ...\n", data->ind);
- timings = NULL; - fprintf(data->log_handler, "#idx\tperf\trun\tperiod\tstart\t\tend\t\trel_st\n");
if (opts.ftrace) @@ -526,7 +534,7 @@ void *thread_body(void *arg) } } #endif - i = j = loop = 0; + i = j = loop = idx = 0;
while (continue_running && (i != data->loop)) { struct timespec t_diff, t_rel_start; @@ -541,7 +549,7 @@ void *thread_body(void *arg) clock_gettime(CLOCK_MONOTONIC, &t_end);
if (timings) - curr_timing = &timings[loop]; + curr_timing = &timings[idx]; else curr_timing = &tmp_timing;
@@ -556,7 +564,7 @@ void *thread_body(void *arg) curr_timing->duration = duration; curr_timing->perf = perf;
- if (!timings) + if (opts.logsize && !timings) log_timing(data->log_handler, curr_timing);
if (opts.ftrace) @@ -575,6 +583,12 @@ void *thread_body(void *arg)
pdata = &data->phases[j]; } + + idx++; + if (idx >= timings_size) { + timing_loop = 1; + idx = 0; + } }
param.sched_priority = 0; @@ -587,9 +601,13 @@ void *thread_body(void *arg) exit(EXIT_FAILURE); }
- if (timings) - for (j=0; j < loop; j++) + if (timings) { + for (j = idx; timing_loop && (j < timings_size); j++) + log_timing(data->log_handler, &timings[j]); + for (j = 0; j < idx; j++) log_timing(data->log_handler, &timings[j]); + } +
if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] exiting", data->ind); diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index def3070..98374cd 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -744,8 +744,8 @@ parse_tasks(struct json_object *tasks, rtapp_options_t *opts) static void parse_global(struct json_object *global, rtapp_options_t *opts) { - char *policy, *cal_str; - struct json_object *cal_obj; + char *policy, *tmp_str; + struct json_object *tmp_obj; int scan_cnt;
log_info(PFX "Parsing global section"); @@ -760,6 +760,7 @@ parse_global(struct json_object *global, rtapp_options_t *opts) opts->logdir = strdup("./"); opts->lock_pages = 1; opts->logbasename = strdup("rt-app"); + opts->logsize = 0; opts->ftrace = 0; opts->pi_enabled = 0; opts->io_device = strdup("/dev/null"); @@ -781,27 +782,27 @@ parse_global(struct json_object *global, rtapp_options_t *opts) */ free(policy);
- cal_obj = get_in_object(global, "calibration", TRUE); - if (cal_obj == NULL) { + tmp_obj = get_in_object(global, "calibration", TRUE); + if (tmp_obj == NULL) { /* no setting ? Calibrate CPU0 */ opts->calib_cpu = 0; opts->calib_ns_per_loop = 0; log_error("missing calibration setting force CPU0"); } else { - if (json_object_is_type(cal_obj, json_type_int)) { + if (json_object_is_type(tmp_obj, json_type_int)) { /* integer (no " ") detected. */ - opts->calib_ns_per_loop = json_object_get_int(cal_obj); + opts->calib_ns_per_loop = json_object_get_int(tmp_obj); log_debug("ns_per_loop %d", opts->calib_ns_per_loop); } else { /* Get CPU number */ - cal_str = get_string_value_from(global, "calibration", + tmp_str = get_string_value_from(global, "calibration", TRUE, "CPU0"); - scan_cnt = sscanf(cal_str, "CPU%d", &opts->calib_cpu); + scan_cnt = sscanf(tmp_str, "CPU%d", &opts->calib_cpu); /* * get_string_value_from allocate the string so with have to free it * once useless */ - free(cal_str); + free(tmp_str); if (!scan_cnt) { log_critical(PFX "Invalid calibration CPU%d", opts->calib_cpu); exit(EXIT_INV_CONFIG); @@ -810,6 +811,38 @@ parse_global(struct json_object *global, rtapp_options_t *opts) } }
+ tmp_obj = get_in_object(global, "log_size", TRUE); + if (tmp_obj == NULL) { + /* no size ? use file system */ + opts->logsize = -2; + } else { + if (json_object_is_type(tmp_obj, json_type_int)) { + /* integer (no " ") detected. */ + /* buffer size is set in MB */ + opts->logsize = json_object_get_int(tmp_obj) << 20; + log_notice("Log buffer size fixed to %dMB per threads", (opts->logsize >> 20)); + } else { + /* Get CPU number */ + tmp_str = get_string_value_from(global, "log_size", + TRUE, "disable"); + + if (strcmp(tmp_str, "disable")) + opts->logsize = 0; + else if (strcmp(tmp_str, "file")) + opts->logsize = -2; + else if (strcmp(tmp_str, "auto")) + opts->logsize = -2; /* Automatic buffer size computation is not supported yet so we fall back on file system mode */ + + log_debug("Log buffer set to %s mode", tmp_str); + + /* + * get_string_value_from allocate the string so with have to free it + * once useless + */ + free(tmp_str); + } + } + opts->logdir = get_string_value_from(global, "logdir", TRUE, "./"); opts->lock_pages = get_bool_value_from(global, "lock_pages", TRUE, 1); opts->logbasename = get_string_value_from(global, "log_basename", diff --git a/src/rt-app_types.h b/src/rt-app_types.h index aab96a7..2ce9c9d 100644 --- a/src/rt-app_types.h +++ b/src/rt-app_types.h @@ -170,6 +170,7 @@ typedef struct _rtapp_options_t {
char *logdir; char *logbasename; + int logsize; int gnuplot; int calib_cpu; int calib_ns_per_loop;