diff options
author | Vincent Guittot <vincent.guittot@linaro.org> | 2015-08-11 09:33:40 +0200 |
---|---|---|
committer | Vincent Guittot <vincent.guittot@linaro.org> | 2015-08-24 14:16:28 +0200 |
commit | 743afaa928f0e52f6459afe9d980f91c050bd466 (patch) | |
tree | 5ceda1bca3f269e86a640d9dc883fad29551faec | |
parent | 1eba97039c3f991e35e6004a971506e770e89ac7 (diff) |
rt-app: add log buffer in memory
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>
-rw-r--r-- | doc/tutorial.txt | 15 | ||||
-rw-r--r-- | src/rt-app.c | 34 | ||||
-rw-r--r-- | src/rt-app_parse_config.c | 51 | ||||
-rw-r--r-- | 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 20383a2..7f9dda0 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -343,10 +343,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); @@ -440,6 +441,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) { @@ -454,8 +464,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) @@ -478,7 +486,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; @@ -493,7 +501,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; @@ -508,7 +516,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) @@ -527,6 +535,12 @@ void *thread_body(void *arg) pdata = &data->phases[j]; } + + idx++; + if (idx >= timings_size) { + timing_loop = 1; + idx = 0; + } } param.sched_priority = 0; @@ -539,9 +553,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 96e5517..c2407dc 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -692,8 +692,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"); @@ -708,6 +708,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; return; @@ -727,27 +728,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); @@ -756,6 +757,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 1075f64..eca8ff1 100644 --- a/src/rt-app_types.h +++ b/src/rt-app_types.h @@ -156,6 +156,7 @@ typedef struct _rtapp_options_t { char *logdir; char *logbasename; + int logsize; int gnuplot; int calib_cpu; int calib_ns_per_loop; |