From: Vincent Guittot vincent.guittot@linaro.org
remove useless space align tab remove useless comment
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", .trace_fd = -1, .marker_fd = -1, };
-static inline unsigned int max_run(int min, int max) -{ - return min + (((double) rand()) / RAND_MAX) * (max - min); -} - 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); 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; 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); + 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++) { 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); + /* 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);
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, ...);