Hi Vincent,
On 14/04/15 14:33, Vincent Guittot wrote:
On 13 April 2015 at 15:35, Juri Lelli juri.lelli@arm.com wrote:
Hi,
On 20/03/15 08:45, pi-cheng.chen wrote:
From: Vincent Guittot vincent.guittot@linaro.org
remove useless space align tab remove useless comment
I understand that this patch cleans things up by applying same kind of changes over and over, but I'd still split it in several smaller patches. Maybe a patch for each of the above points?
I have squashed them in one patch in order to minimize the number of patches but they can be split if you prefer
Yes, please. I understand your point, but IMHO it's easier to keep track of changes with littler patches.
Signed-off-by: Vincent Guittot vincent.guittot@linaro.org Signed-off-by: Kevin Hilman khilman@linaro.org
src/rt-app.c | 191 +++++++++++++++++++++++++--------------------- src/rt-app_args.c | 77 ++++++++++--------- src/rt-app_parse_config.c | 31 ++++++-- src/rt-app_utils.c | 3 + src/rt-app_utils.h | 4 +- 5 files changed, 174 insertions(+), 132 deletions(-)
diff --git a/src/rt-app.c b/src/rt-app.c index 3c293e7..4629980 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -27,17 +27,13 @@ static volatile int continue_running; static pthread_t *threads; static int nthreads; rtapp_options_t opts;
static ftrace_data_t ft_data = {
.debugfs = "/debug",
.debugfs = "/sys/kernel/debug",
This maybe deserves a standalone patch, as it doesn't fit in any of the points in the changelog.
.trace_fd = -1, .marker_fd = -1,
};
-static inline unsigned int max_run(int min, int max) -{
return min + (((double) rand()) / RAND_MAX) * (max - min);
-}
This as well.
static inline busywait(struct timespec *to) { struct timespec t_step; @@ -52,27 +48,29 @@ void run(int ind, struct timespec *min, struct timespec *max, rtapp_tasks_resource_list_t *blockages, int nblockages) { int i;
//int m = max_run(timespec_to_msec(min), timespec_to_msec(max));
//struct timespec t_start, t_step, t_exec = msec_to_timespec(m); struct timespec t_start, now, t_exec, t_totexec = *max; rtapp_resource_access_list_t *lock, *last;
/* get the start time */
/* Get the start time */ clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t_start); for (i = 0; i < nblockages; i++) {
/* Lock resources */ lock = blockages[i].acl; while (lock != NULL) { log_debug("[%d] locking %d", ind, lock->res->index); if (opts.ftrace) log_ftrace(ft_data.marker_fd,
"[%d] locking %d",
ind, lock->res->index);
"[%d] locking %d",
ind, lock->res->index);
I generally prefer to keep arguments aligned with the first argument. Can we keep this convention?
i'm fine with this point. This change was to align the arguments (but stay aligned with tab width) which were not aligned with my text editor (which tab width are you using ?)
8-char.
If you want to be aligned, tab should be replaced by withe space
I usually align parameters with spaces after the last tab, but that's only personal taste I guess :).
pthread_mutex_lock(&lock->res->mtx); last = lock; lock = lock->next; }
/* Busy wait */ clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now); t_exec = timespec_add(&now, &blockages[i].usage); log_debug("[%d] busywait for %lu", ind, timespec_to_usec(&blockages[i].usage));
@@ -81,19 +79,21 @@ void run(int ind, struct timespec *min, struct timespec *max, "[%d] busywait for %d", ind, timespec_to_usec(&blockages[i].usage)); busywait(&t_exec);
/* Unlock resources */ lock = last; while (lock != NULL) { log_debug("[%d] unlocking %d", ind, lock->res->index); if (opts.ftrace) log_ftrace(ft_data.marker_fd,
"[%d] unlocking %d",
ind, lock->res->index);
"[%d] unlocking %d",
ind, lock->res->index); pthread_mutex_unlock(&lock->res->mtx); lock = lock->prev; } }
/* compute finish time for CPUTIME_ID clock */
/* Compute finish time for CPUTIME_ID clock */ t_exec = timespec_add(&t_start, &t_totexec); busywait(&t_exec);
} @@ -108,6 +108,7 @@ shutdown(int sig) { pthread_join(threads[i], NULL); }
if (opts.ftrace) { log_notice("stopping ftrace"); log_ftrace(ft_data.marker_fd, "main ends\n");
@@ -115,6 +116,7 @@ shutdown(int sig) close(ft_data.trace_fd); close(ft_data.marker_fd); }
exit(EXIT_SUCCESS);
}
@@ -122,7 +124,7 @@ void *thread_body(void *arg) { thread_data_t *data = (thread_data_t*) arg; struct sched_param param;
struct timespec t, t_next;
struct timespec t_now, t_next;
Maybe a standalone patch, even if it's just renaming?
unsigned long t_start_usec; unsigned long my_duration_usec; int nperiods;
@@ -162,11 +164,11 @@ void *thread_body(void *arg) case rr: case fifo: fprintf(data->log_handler, "# Policy : %s\n",
(data->sched_policy == rr ? "SCHED_RR" : "SCHED_FIFO"));
(data->sched_policy == rr ? "SCHED_RR" : "SCHED_FIFO")); param.sched_priority = data->sched_prio; ret = pthread_setschedparam(pthread_self(),
data->sched_policy,
¶m);
data->sched_policy,
¶m); if (ret != 0) { errno = ret; perror("pthread_setschedparam");
@@ -174,49 +176,56 @@ void *thread_body(void *arg) }
log_notice("[%d] starting thread with period: %lu, exec: %lu,"
"deadline: %lu, priority: %d",
data->ind,
timespec_to_usec(&data->period),
timespec_to_usec(&data->min_et),
timespec_to_usec(&data->deadline),
data->sched_prio
);
"deadline: %lu, priority: %d",
data->ind,
timespec_to_usec(&data->period),
timespec_to_usec(&data->min_et),
timespec_to_usec(&data->deadline),
data->sched_prio); break; case other: fprintf(data->log_handler, "# Policy : SCHED_OTHER\n");
/* add priority setting */
log_notice("[%d] starting thread with period: %lu, exec: %lu,"
"deadline: %lu",
data->ind,
timespec_to_usec(&data->period),
timespec_to_usec(&data->min_et),
timespec_to_usec(&data->deadline)
);
"deadline: %lu",
data->ind,
timespec_to_usec(&data->period),
timespec_to_usec(&data->min_et),
timespec_to_usec(&data->deadline));
data->lock_pages = 0; /* forced off for SCHED_OTHER */ break;
#ifdef AQUOSA case aquosa: fprintf(data->log_handler, "# Policy : AQUOSA\n");
data->params.Q_min = round((timespec_to_usec(&data->min_et) * (( 100.0 + data->sched_prio ) / 100)) / (data->fragment * 1.0));
data->params.Q = round((timespec_to_usec(&data->max_et) * (( 100.0 + data->sched_prio ) / 100)) / (data->fragment * 1.0));
data->params.P = round(timespec_to_usec(&data->period) / (data->fragment * 1.0));
data->params.Q_min = round((timespec_to_usec(&data->min_et)
* (( 100.0 + data->sched_prio ) / 100)) / (data->fragment * 1.0));
data->params.Q = round((timespec_to_usec(&data->max_et)
* (( 100.0 + data->sched_prio ) / 100)) / (data->fragment * 1.0));
data->params.P = round(timespec_to_usec(&data->period)
/ (data->fragment * 1.0)); data->params.flags = 0;
log_notice("[%d] Creating QRES Server with Q=%ld, P=%ld",
data->ind,data->params.Q, data->params.P);
data->ind,data->params.Q, data->params.P); qos_chk_ok_exit(qres_init());
qos_chk_ok_exit(qres_create_server(&data->params,
&data->sid));
qos_chk_ok_exit(qres_create_server(&data->params,
&data->sid)); log_notice("[%d] AQuoSA server ID: %d", data->ind, data->sid); log_notice("[%d] attaching thread (deadline: %lu) to server %d",
data->ind,
timespec_to_usec(&data->deadline),
data->sid
);
qos_chk_ok_exit(qres_attach_thread(data->sid, 0, 0));
data->ind,
timespec_to_usec(&data->deadline),
data->sid);
break;
qos_chk_ok_exit(qres_attach_thread(data->sid, 0, 0));
break;
#endif
#ifdef DLSCHED case deadline: fprintf(data->log_handler, "# Policy : SCHED_DEADLINE\n"); @@ -226,16 +235,16 @@ void *thread_body(void *arg) attr.sched_policy = SCHED_DEADLINE; attr.sched_priority = 0; attr.sched_runtime = timespec_to_nsec(&data->max_et) +
(timespec_to_nsec(&data->max_et) /100) * BUDGET_OVERP;
(timespec_to_nsec(&data->max_et) /100) * BUDGET_OVERP; attr.sched_deadline = timespec_to_nsec(&data->period); attr.sched_period = timespec_to_nsec(&data->period);
break;
break;
#endif
default: log_error("Unknown scheduling policy %d",
data->sched_policy);
data->sched_policy);
exit(EXIT_FAILURE); }
@@ -253,45 +262,46 @@ void *thread_body(void *arg) if (data->wait_before_start > 0) { log_notice("[%d] Waiting %ld usecs... ", data->ind, data->wait_before_start);
clock_gettime(CLOCK_MONOTONIC, &t);
clock_gettime(CLOCK_MONOTONIC, &t_now); t_next = msec_to_timespec(data->wait_before_start);
t_next = timespec_add(&t, &t_next);
t_next = timespec_add(&t_now, &t_next); clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t_next, NULL); log_notice("[%d] Starting...", data->ind); }
/* if we know the duration we can calculate how many periods we will * do at most, and the log to memory, instead of logging to file. */ timings = NULL; if (data->duration > 0) {
my_duration_usec = (data->duration * 10e6) -
(data->wait_before_start * 1000);
nperiods = (int) ceil( my_duration_usec /
(double) timespec_to_usec(&data->period));
my_duration_usec = (data->duration * 10e6) -
(data->wait_before_start * 1000);
nperiods = (int) ceil( my_duration_usec /
(double) timespec_to_usec(&data->period)); timings = malloc ( nperiods * sizeof(timing_point_t)); } fprintf(data->log_handler, "#idx\tperiod\tmin_et\tmax_et\trel_st\tstart"
"\t\tend\t\tdeadline\tdur.\tslack"
"\tBudget\tUsed Budget\n");
"\t\tend\t\tdeadline\tdur.\tslack"
"\tBudget\tUsed Budget\n");
#ifdef DLSCHED
/* TODO find a better way to handle that constraint */ /* * Set the task to SCHED_DEADLINE as far as possible touching its * budget as little as possible for the first iteration. */ if (data->sched_policy == SCHED_DEADLINE) { log_notice("[%d] starting thread with period: %lu, exec: %lu,"
"deadline: %lu, priority: %d",
data->ind,
attr.sched_period / 1000,
attr.sched_runtime / 1000,
attr.sched_deadline / 1000,
attr.sched_priority
);
"deadline: %lu, priority: %d",
data->ind,
attr.sched_period / 1000,
attr.sched_runtime / 1000,
attr.sched_deadline / 1000,
attr.sched_priority); ret = sched_setattr(tid, &attr, flags); if (ret != 0) {
@@ -306,15 +316,17 @@ void *thread_body(void *arg)
if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] starts", data->ind);
clock_gettime(CLOCK_MONOTONIC, &t);
t_next = t;
data->deadline = timespec_add(&t, &data->deadline);
clock_gettime(CLOCK_MONOTONIC, &t_now);
t_next = t_now;
data->deadline = timespec_add(&t_now, &data->deadline); while (continue_running) { struct timespec t_start, t_end, t_diff, t_slack; if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] begins loop %d", data->ind, i);
clock_gettime(CLOCK_MONOTONIC, &t_start); run(data->ind, &data->min_et, &data->max_et, data->blockages, data->nblockages);
@@ -328,6 +340,7 @@ void *thread_body(void *arg) curr_timing = &timings[i]; else curr_timing = &tmp_timing;
curr_timing->ind = data->ind; curr_timing->period = timespec_to_usec(&data->period); curr_timing->min_et = timespec_to_usec(&data->min_et);
@@ -339,14 +352,15 @@ void *thread_body(void *arg) curr_timing->deadline = timespec_to_usec(&data->deadline); curr_timing->duration = timespec_to_usec(&t_diff); curr_timing->slack = timespec_to_lusec(&t_slack);
#ifdef AQUOSA if (data->sched_policy == aquosa) { curr_timing->budget = data->params.Q; qres_get_exec_time(data->sid,
&abs_used_budget,
NULL);
&abs_used_budget,
NULL); curr_timing->used_budget =
abs_used_budget - prev_abs_used_budget;
abs_used_budget - prev_abs_used_budget; prev_abs_used_budget = abs_used_budget; } else {
@@ -359,9 +373,11 @@ void *thread_body(void *arg)
t_next = timespec_add(&t_next, &data->period); data->deadline = timespec_add(&data->deadline, &data->period);
if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] end loop %d", data->ind, i);
if (curr_timing->slack < 0 && opts.die_on_dmiss) { log_critical("[%d] DEADLINE MISS !!!", data->ind); if (opts.ftrace)
@@ -370,7 +386,11 @@ void *thread_body(void *arg) shutdown(SIGTERM); goto exit_miss; }
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t_next, NULL);
clock_gettime(CLOCK_MONOTONIC, &t_now);
if (timespec_lower(&t_now, &t_next))
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t_next, NULL);
Can you explain, maybe in a separate patch, why we need this change?
To be honest i can't remember the root cause of such change. I would have say to not sleep if we have run longer than expected but clock_nanosleep handles such situation.
Yeah, right. Don't know, but we can still have this as a separate change, though.
i++; }
@@ -393,18 +413,17 @@ exit_miss: log_ftrace(ft_data.marker_fd, "[%d] exiting", data->ind); log_notice("[%d] Exiting.", data->ind); fclose(data->log_handler);
#ifdef AQUOSA if (data->sched_policy == aquosa) { qres_destroy_server(data->sid); qres_cleanup(); } #endif
pthread_exit(NULL);
}
-/* parse a thread token in the form $period:$exec:$deadline:$policy:$prio and
- fills the thread_data structure
- */
int main(int argc, char* argv[]) { @@ -416,6 +435,7 @@ int main(int argc, char* argv[])
parse_command_line(argc, argv, &opts);
/* allocated threads */ nthreads = opts.nthreads; threads = malloc(nthreads * sizeof(pthread_t));
@@ -425,7 +445,7 @@ int main(int argc, char* argv[]) signal(SIGHUP, shutdown); signal(SIGINT, shutdown);
/* if using ftrace open trace and marker fds */
/* if using ftrace, open trace and marker fds */ if (opts.ftrace) { log_notice("configuring ftrace"); strcpy(tmp, ft_data.debugfs);
@@ -454,8 +474,7 @@ int main(int argc, char* argv[]) clock_gettime(CLOCK_MONOTONIC, &t_start);
/* start threads */
for (i = 0; i < nthreads; i++)
{
for (i = 0; i < nthreads; i++) { tdata = &opts.threads_data[i]; if (opts.spacing > 0 ) { /* start the thread, then it will sleep accordingly
@@ -466,19 +485,21 @@ int main(int argc, char* argv[]) } else { tdata->wait_before_start = 0; }
tdata->duration = opts.duration; tdata->main_app_start = t_start; tdata->lock_pages = opts.lock_pages;
#ifdef AQUOSA tdata->fragment = opts.fragment; #endif
if (opts.logdir) { snprintf(tmp, PATH_LENGTH, "%s/%s-%s.log", opts.logdir, opts.logbasename, tdata->name); tdata->log_handler = fopen(tmp, "w");
if (!tdata->log_handler){
if (!tdata->log_handler) { log_error("Cannot open logfile %s", tmp); exit(EXIT_FAILURE); }
@@ -494,8 +515,7 @@ int main(int argc, char* argv[]) }
/* print gnuplot files */
if (opts.logdir && opts.gnuplot)
{
if (opts.logdir && opts.gnuplot) { snprintf(tmp, PATH_LENGTH, "%s/%s-duration.plot", opts.logdir, opts.logbasename); gnuplot_script = fopen(tmp, "w+");
@@ -511,8 +531,7 @@ int main(int argc, char* argv[]) "set ylabel "Exec Time [usec]"\n" "plot ", tmp);
for (i=0; i<nthreads; i++)
{
for (i=0; i<nthreads; i++) { snprintf(tmp, PATH_LENGTH, "%s/%s-duration.plot", opts.logdir, opts.logbasename);
@@ -528,11 +547,12 @@ int main(int argc, char* argv[]) else fprintf(gnuplot_script, ", "); }
fprintf(gnuplot_script, "set terminal wxt\nreplot\n"); fclose(gnuplot_script); snprintf(tmp, PATH_LENGTH, "%s/%s-slack.plot",
opts.logdir, opts.logbasename);
opts.logdir, opts.logbasename); gnuplot_script = fopen(tmp, "w+"); snprintf(tmp, PATH_LENGTH, "%s-slack.eps", opts.logbasename);
@@ -547,8 +567,7 @@ int main(int argc, char* argv[]) "set ylabel "Slack/Tardiness [usec]"\n" "plot ", tmp);
for (i=0; i < nthreads; i++)
{
for (i=0; i < nthreads; i++) { fprintf(gnuplot_script, "\"%s-%s.log\" u ($5/1000):10 w l" " title \"thread [%s] (%s)\"",
@@ -562,19 +581,19 @@ int main(int argc, char* argv[]) fprintf(gnuplot_script, ", ");
}
fprintf(gnuplot_script, "set terminal wxt\nreplot\n"); fclose(gnuplot_script); }
if (opts.duration > 0)
{
if (opts.duration > 0) { sleep(opts.duration); if (opts.ftrace) log_ftrace(ft_data.marker_fd, "main shutdown\n"); shutdown(SIGTERM); }
for (i = 0; i < nthreads; i++) {
for (i = 0; i < nthreads; i++) { pthread_join(threads[i], NULL); }
diff --git a/src/rt-app_args.c b/src/rt-app_args.c index 36e7e51..49ff749 100644 --- a/src/rt-app_args.c +++ b/src/rt-app_args.c @@ -28,7 +28,7 @@ usage (const char* msg, int ex_code) "rt-app <taskset.json>\nOR\n"); #endif printf("rt-app [options] -t <period>:<exec>[:policy"
"[:CPU affinity[:prio[:deadline]]]] -t ...\n\n");
"[:CPU affinity[:prio[:deadline]]]] -t ...\n\n"); printf("-h, --help\t\t:\tshow this help\n"); printf("-f, --fifo\t\t:\tset default policy for threads to SCHED_FIFO\n"); printf("-r, --rr\t\t:\tset default policy fior threads to SCHED_RR\n");
@@ -81,6 +81,7 @@ parse_thread_args(char *arg, int idx, thread_data_t *tdata, policy_t def_policy) token = strtok(str, ":"); tdata->name = malloc(sizeof(char) * 5); tdata->ind = idx;
/* default name for command line threads */ snprintf(tdata->name, 1, "t%d", tdata->ind); tdata->sched_prio = DEFAULT_THREAD_PRIORITY;
@@ -105,10 +106,10 @@ parse_thread_args(char *arg, int idx, thread_data_t *tdata, policy_t def_policy) //TODO: add support for max_et somehow if (exec > period) usage("Exec time cannot be greater than"
" period.", EXIT_INV_COMMANDLINE);
" period.", EXIT_INV_COMMANDLINE); if (exec <= 0 ) usage("Cannot set negative exec time",
EXIT_INV_COMMANDLINE);
EXIT_INV_COMMANDLINE); tdata->min_et = usec_to_timespec(exec); tdata->max_et = usec_to_timespec(exec); i++;
@@ -173,6 +174,7 @@ parse_thread_args(char *arg, int idx, thread_data_t *tdata, policy_t def_policy) } token = strtok(NULL, ":"); }
if ( i < 2 ) { printf("Period and exec time are mandatory\n"); exit(EXIT_INV_COMMANDLINE);
@@ -224,25 +226,27 @@ parse_command_line_options(int argc, char **argv, rtapp_options_t *opts) #ifdef AQUOSA opts->fragment = 1; #endif
static struct option long_options[] = {
{"help", 0, 0, 'h'},
{"fifo", 0, 0, 'f'},
{"rr", 0, 0, 'r'},
{"thread", 1, 0, 't'},
{"spacing", 1, 0, 's'},
{"logdir", 1, 0, 'l'},
{"baselog", 1, 0, 'b'},
{"gnuplot", 1, 0, 'G'},
{"duration", 1, 0, 'D'},
{"ftrace", 0, 0, 'T'},
{"pi_enabled", 0, 0, 'T'},
{"die_on_dmiss", 0, 0, 'M'},
{"help", 0, 0, 'h'},
{"fifo", 0, 0, 'f'},
{"rr", 0, 0, 'r'},
{"thread", 1, 0, 't'},
{"spacing", 1, 0, 's'},
{"logdir", 1, 0, 'l'},
{"baselog", 1, 0, 'b'},
{"gnuplot", 1, 0, 'G'},
{"duration", 1, 0, 'D'},
{"ftrace", 0, 0, 'T'},
{"pi_enabled", 0, 0, 'T'},
{"die_on_dmiss", 0, 0, 'M'},
#ifdef AQUOSA
{"qos", 0, 0, 'q'},
{"frag",1, 0, 'g'},
{"qos", 0, 0, 'q'},
{"frag",1, 0, 'g'},
#endif
{0, 0, 0, 0}
};
{0, 0, 0, 0}
};
#ifdef AQUOSA while (( ch = getopt_long(argc,argv,"D:GKhfrb:s:l:qg:t:TM", long_options, &longopt_idx)) != -1) @@ -259,13 +263,13 @@ parse_command_line_options(int argc, char **argv, rtapp_options_t *opts) case 'f': if (opts->policy != other) usage("Cannot set multiple policies",
EXIT_INV_COMMANDLINE);
EXIT_INV_COMMANDLINE); opts->policy = fifo; break; case 'r': if (opts->policy != other) usage("Cannot set multiple policies",
EXIT_INV_COMMANDLINE);
EXIT_INV_COMMANDLINE); opts->policy = rr; break; case 'b':
@@ -277,26 +281,26 @@ parse_command_line_options(int argc, char **argv, rtapp_options_t *opts) opts->spacing = strtol(optarg, NULL, 0); if (opts->spacing < 0) usage("Cannot set negative spacing",
EXIT_INV_COMMANDLINE);
EXIT_INV_COMMANDLINE); break; case 'l': opts->logdir = strdup(optarg); lstat(opts->logdir, &dirstat); if (! S_ISDIR(dirstat.st_mode)) usage("Cannot stat log directory",
EXIT_INV_COMMANDLINE);
EXIT_INV_COMMANDLINE); break; case 't': if (opts->nthreads > 0) { opts->threads_data = realloc(
opts->threads_data,
(opts->nthreads+1) * \
opts->threads_data,
(opts->nthreads+1) * \ sizeof(thread_data_t)); } parse_thread_args(optarg, opts->nthreads,
&opts->threads_data[opts->nthreads],
opts->policy);
&opts->threads_data[opts->nthreads],
opts->policy); opts->nthreads++; break; case 'G':
@@ -306,7 +310,7 @@ parse_command_line_options(int argc, char **argv, rtapp_options_t *opts) opts->duration = strtol(optarg, NULL, 10); if (opts->duration < 0) usage("Cannot set negative duration",
EXIT_INV_COMMANDLINE);
EXIT_INV_COMMANDLINE); break; case 'K': opts->lock_pages = 0;
@@ -324,26 +328,25 @@ parse_command_line_options(int argc, char **argv, rtapp_options_t *opts) case 'q': if (opts->policy != other) usage("Cannot set multiple policies",
EXIT_INV_COMMANDLINE);
EXIT_INV_COMMANDLINE); opts->policy = aquosa; break; case 'g': opts->fragment = strtol(optarg, NULL, 10); if (opts->fragment < 1 || opts->fragment > 16) usage("Fragment divisor must be between"
"1 and 16", EXIT_INV_COMMANDLINE);
"1 and 16", EXIT_INV_COMMANDLINE); break;
#endif default: log_error("Invalid option %c", ch); usage(NULL, EXIT_INV_COMMANDLINE);
}
}
if ( opts->nthreads < 1) usage("You have to set parameters for at least one thread",
EXIT_INV_COMMANDLINE);
EXIT_INV_COMMANDLINE);
}
@@ -351,18 +354,20 @@ void parse_command_line(int argc, char **argv, rtapp_options_t *opts) { #ifdef JSON
struct stat config_file_stat;
if (argc < 2) usage(NULL, EXIT_SUCCESS);
struct stat config_file_stat;
if (stat(argv[1], &config_file_stat) == 0) { parse_config(argv[1], opts); return;
}
else if (strcmp(argv[1], "-") == 0) {
} else if (strcmp(argv[1], "-") == 0) { parse_config_stdin(opts); return; }
#endif
parse_command_line_options(argc, argv, opts); opts->resources = NULL; opts->nresources = 0;
diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index 4d8bff8..7411b45 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -246,7 +246,6 @@ serialize_acl(rtapp_resource_access_list_t **acl, /* recurse on the rest of resources */ serialize_acl(&(*acl), next_idx, task_resources, resources); }
}
static void @@ -261,10 +260,11 @@ parse_thread_resources(const rtapp_options_t *opts, struct json_object *locks, rtapp_resource_access_list_t *tmp, *head, *last; char debug_msg[512], tmpmsg[512];
data->blockages = malloc(sizeof(rtapp_tasks_resource_list_t) *
json_object_array_length(locks)); data->nblockages = json_object_array_length(locks);
for (i = 0; i< json_object_array_length(locks); i++)
data->blockages = malloc(sizeof(rtapp_tasks_resource_list_t) *
data->nblockages);
for (i = 0; i< data->nblockages; i++)
This might deserve a separate patch as well.
{ res = json_object_array_get_idx(locks, i); if (!json_object_is_type(res, json_type_int)){
@@ -286,6 +286,7 @@ parse_thread_resources(const rtapp_options_t *opts, struct json_object *locks, last = tmp; tmp = tmp->next; } while (tmp != NULL);
/* move first element to list end */ if (last != head) { data->blockages[i].acl = head->next;
@@ -318,7 +319,7 @@ parse_thread_resources(const rtapp_options_t *opts, struct json_object *locks, data->blockages[i].usage = usec_to_timespec(usage_usec); } log_info(PIN "res %d, usage: %d acl: %s", cur_res_idx,
usage_usec, debug_msg);
usage_usec, debug_msg); }
}
@@ -363,6 +364,18 @@ parse_thread_data(char *name, struct json_object *obj, int idx, data->min_et = usec_to_timespec(exec); data->max_et = usec_to_timespec(exec);
/* deadline */
dline = get_int_value_from(obj, "deadline", TRUE, period);
if (dline < exec) {
log_critical(PIN2 "Deadline cannot be less than exec time");
exit(EXIT_INV_CONFIG);
}
if (dline > period) {
log_critical(PIN2 "Deadline cannot be greater than period");
exit(EXIT_INV_CONFIG);
}
data->deadline = usec_to_timespec(dline);
Separate patch for this change as well?
/* policy */ policy_to_string(opts->policy, def_policy); policy = get_string_value_from(obj, "policy", TRUE, def_policy);
@@ -376,7 +389,7 @@ parse_thread_data(char *name, struct json_object *obj, int idx,
/* priority */ data->sched_prio = get_int_value_from(obj, "priority", TRUE,
DEFAULT_THREAD_PRIORITY);
DEFAULT_THREAD_PRIORITY); /* deadline */ dline = get_int_value_from(obj, "deadline", TRUE, period);
@@ -502,8 +515,10 @@ get_opts_from_json_object(struct json_object *root, rtapp_options_t *opts) void parse_config_stdin(rtapp_options_t *opts) {
/* read from stdin until EOF, write to temp file and parse
* as a "normal" config file */
/*
* Read from stdin until EOF, write to temp file and parse
* as a "normal" config file
*/ size_t in_length; char buf[JSON_FILE_BUF_SIZE]; struct json_object *js;
diff --git a/src/rt-app_utils.c b/src/rt-app_utils.c index 0c08f02..9719053 100644 --- a/src/rt-app_utils.c +++ b/src/rt-app_utils.c @@ -224,17 +224,20 @@ void ftrace_write(int mark_fd, const char *fmt, ...) va_start(ap, fmt); n = vsnprintf(tmp, BUF_SIZE, fmt, ap); va_end(ap);
/* If it worked return success */ if (n > -1 && n < size) { write(mark_fd, tmp, n); free(tmp); return; }
/* Else try again with more space */ if (n > -1) /* glibc 2.1 */ size = n+1; else /* glibc 2.0 */ size *= 2;
if ((ntmp = realloc(tmp, size)) == NULL) { free(tmp); log_error("Cannot reallocate ftrace buffer");
diff --git a/src/rt-app_utils.h b/src/rt-app_utils.h index c7444dc..ba01f56 100644 --- a/src/rt-app_utils.h +++ b/src/rt-app_utils.h @@ -121,10 +121,10 @@ timespec_to_nsec(struct timespec *ts); #endif
int -string_to_policy(const char *policy_name, policy_t *policy); +policy_to_string(policy_t policy, char *policy_name);
Is this fixing complaints from compiler? Maybe fix it in a separate patch?
yes
Thanks a lot,
- Juri
Regards, Vincent
int -policy_to_string(policy_t policy, char *policy_name); +string_to_policy(const char *policy_name, policy_t *policy);
void ftrace_write(int mark_fd, const char *fmt, ...); -- 1.9.1
Thanks a lot again for this effort!
Best,
- Juri