From: Vincent Guittot vincent.guittot@linaro.org
Remove lock_order and resources objects in per-task objects. Instead, just describe the events sequence. Each event name must be unique and start with the known prefix: run : run a load sleep : sleep for a duration lock : lock a mutex unlock : unlock a mutex
As an example: "run0" : 275, "lock0" : "trig1_mutex", "run1" : 4725, "unlock0" : "trig1_mutex", "sleep1" : 19000,
Signed-off-by: Vincent Guittot vincent.guittot@linaro.org Signed-off-by: Pi-Cheng Chen pi-cheng.chen@linaro.org --- src/rt-app.c | 287 +++++++++++++++------------------------------- src/rt-app_parse_config.c | 284 ++++++++++++++------------------------------- src/rt-app_types.h | 35 +++--- src/rt-app_utils.c | 13 +-- 4 files changed, 195 insertions(+), 424 deletions(-)
diff --git a/src/rt-app.c b/src/rt-app.c index 957f3fe..e7bade0 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -165,93 +165,82 @@ int calibrate_cpu_cycles(int clock)
}
-static inline loadwait(struct timespec *exec_time) +static inline int loadwait(unsigned long exec) { - unsigned long exec, load_count; + unsigned long load_count;
- exec = timespec_to_usec(exec_time); load_count = (exec * 1000)/p_load; waste_cpu_cycles(load_count); + + return load_count; }
-int get_resource(rtapp_resource_access_list_t *lock, struct timespec *usage) +static int run_event(event_data_t *event, int dry_run, + unsigned long *perf, unsigned long *duration) { - int busywait = 1; - - switch(lock->res->type) { - case rtapp_mutex: - pthread_mutex_lock(&(lock->res->res.mtx.obj)); - break; - case rtapp_sleep: - nanosleep(usage, NULL); - busywait = 0; - break; + unsigned long lock = 0; + + switch(event->type) { + case rtapp_lock: + log_debug("lock %s ", event->res->name); + pthread_mutex_lock(&(event->res->res.mtx.obj)); + lock = 1; + break; + case rtapp_unlock: + log_debug("unlock %s ", event->res->name); + pthread_mutex_unlock(&(event->res->res.mtx.obj)); + lock = -1; + break; }
- return busywait; -} + if (dry_run) + return lock;
-void put_resource(rtapp_resource_access_list_t *lock) -{ - if (lock->res->type == rtapp_mutex) - pthread_mutex_unlock(&(lock->res->res.mtx.obj)); + switch(event->type) { + case rtapp_sleep: + { + struct timespec sleep; + sleep = usec_to_timespec(event->duration); + log_debug("sleep %d ", event->duration); + nanosleep(&sleep, NULL); + } + break; + case rtapp_run: + { + struct timespec t_start, t_end; + log_debug("run %d ", event->duration); + clock_gettime(CLOCK_MONOTONIC, &t_start); + *perf += loadwait(event->duration); + clock_gettime(CLOCK_MONOTONIC, &t_end); + t_end = timespec_sub(&t_end, &t_start); + *duration += timespec_to_usec(&t_end); + } + break; + } + + return lock; }
-void run(int ind, struct timespec *min, struct timespec *max, - rtapp_tasks_resource_list_t *blockages, int nblockages) +int run(int ind, event_data_t *events, + int nbevents, unsigned long *duration) { - int i, is_busywait = 1; - struct timespec t_exec; - rtapp_resource_access_list_t *lock, *last; + int i, lock = 0; + unsigned long perf = 0;
- t_exec = *min; - - for (i = 0; i < nblockages; i++) + for (i = 0; i < nbevents; i++) { - /* Lock resources sequence including the busy wait */ - 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); - is_busywait = get_resource(lock, &blockages[i].usage); - last = lock; - lock = lock->next; - } - - if (is_busywait) { - /* Busy wait */ - log_debug("[%d] busywait for %lu", ind, timespec_to_usec(&blockages[i].usage)); - if (opts.ftrace) - log_ftrace(ft_data.marker_fd, - "[%d] busywait for %d", - ind, timespec_to_usec(&blockages[i].usage)); - loadwait(&blockages[i].usage); - t_exec = timespec_sub(&t_exec, &blockages[i].usage); - } + if (!continue_running && !lock) + return;
- /* Unlock resources */ - lock = last; - while (lock != NULL) { - log_debug("[%d] unlocking %d", ind, lock->res->index); - if (opts.ftrace) + log_debug("[%d] runs events %d type %d ", ind, i, events[i].type); + if (opts.ftrace) log_ftrace(ft_data.marker_fd, - "[%d] unlocking %d", - ind, lock->res->index); - put_resource(lock); - lock = lock->prev; - } + "[%d] locking %d", + ind, events[i].type); + lock += run_event(&events[i], !continue_running, &perf, duration); }
- /* Compute finish time for CPUTIME_ID clock */ - log_debug("[%d] busywait for %lu", ind, timespec_to_usec(&t_exec)); - if (opts.ftrace) - log_ftrace(ft_data.marker_fd, - "[%d] busywait for %lu", - ind, timespec_to_usec(&t_exec)); - loadwait(&t_exec); + return perf; }
static void @@ -281,10 +270,9 @@ void *thread_body(void *arg) thread_data_t *data = (thread_data_t*) arg; phase_data_t *pdata; struct sched_param param; - struct timespec t_now, t_next; + struct timespec t_start, t_end; unsigned long t_start_usec; - unsigned long my_duration_usec; - int nperiods; + unsigned long perf, duration; timing_point_t *timings; timing_point_t tmp_timing; timing_point_t *curr_timing; @@ -387,10 +375,6 @@ void *thread_body(void *arg) attr.sched_flags = 0; attr.sched_policy = SCHED_DEADLINE; attr.sched_priority = 0; - attr.sched_runtime = timespec_to_nsec(&pdata->max_et) + - (timespec_to_nsec(&pdata->max_et) /100) * BUDGET_OVERP; - attr.sched_deadline = timespec_to_nsec(&pdata->deadline); - attr.sched_period = timespec_to_nsec(&pdata->period); break; #endif
@@ -412,54 +396,11 @@ void *thread_body(void *arg) } }
- log_notice("[%d] starting thread with period: %lu, exec: %lu," - "deadline: %lu", - data->ind, - timespec_to_usec(&pdata->period), - timespec_to_usec(&pdata->min_et), - timespec_to_usec(&pdata->deadline)); - - /* 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. - * In case of several phase, we still use the logging file instead of - * memory. - * TODO: parse all the phase to compute the memory phase - */ - nperiods = 0; - if ((data->duration > 0) && (data->duration > data->wait_before_start) - && (data->nphases < 2)) { - my_duration_usec = (data->duration * 1000000) - - data->wait_before_start; - nperiods = (my_duration_usec + timespec_to_usec(&data->phases_data->period) - 1) - / timespec_to_usec(&data->phases_data->period) + 1; - } + log_notice("[%d] starting thread ...\n", data->ind);
- if ((pdata->loop > 0) && (pdata->loop < nperiods)) { - nperiods = data->loop + 1 ; - } + timings = NULL;
- if (nperiods) - timings = malloc(nperiods * sizeof(timing_point_t)); - else - timings = NULL; - - fprintf(data->log_handler, "#idx\tperiod\tmin_et\tmax_et\trel_st\tstart" - "\t\tend\t\tdeadline\tdur.\tslack" - "\tBudget\tUsed Budget\n"); - - - if (data->wait_before_start > 0) { - log_notice("[%d] Waiting %ld usecs... ", data->ind, - data->wait_before_start); - clock_gettime(CLOCK_MONOTONIC, &t_now); - t_next = usec_to_timespec(data->wait_before_start); - t_next = timespec_add(&t_now, &t_next); - clock_nanosleep(CLOCK_MONOTONIC, - TIMER_ABSTIME, - &t_next, - NULL); - log_notice("[%d] Starting...", data->ind); - } + fprintf(data->log_handler, "#idx\tperf\trun\tperiod\tstart\t\tend\t\trel_st\n");
#ifdef DLSCHED /* TODO find a better way to handle that constraint */ @@ -468,14 +409,6 @@ void *thread_body(void *arg) * budget as little as possible for the first iteration. */ if (data->sched_policy == SCHED_DEADLINE) { - log_notice("[%d] starting thread with period: %llu, exec: %llu," - "deadline: %llu, 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) { log_critical("[%d] sched_setattr " @@ -490,44 +423,38 @@ void *thread_body(void *arg) if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] starts", data->ind);
- clock_gettime(CLOCK_MONOTONIC, &t_now); - t_next = t_now; - pdata->deadline = timespec_add(&t_now, &pdata->deadline); - i = j = loop = 0; while (continue_running && (i != data->loop)) { - struct timespec t_start, t_end, t_diff, t_slack; + struct timespec t_diff;
if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] begins loop %d phase %d step %d", data->ind, i, j, loop);
+ log_debug("[%d] begins loop %d phase %d step %d", data->ind, i, j, loop);; + clock_gettime(CLOCK_MONOTONIC, &t_start); - run(data->ind, &pdata->min_et, &pdata->max_et, pdata->blockages, - pdata->nblockages); + perf = run(data->ind, pdata->events, pdata->nbevents, &duration); clock_gettime(CLOCK_MONOTONIC, &t_end);
- t_diff = timespec_sub(&t_end, &t_start); - t_slack = timespec_sub(&pdata->deadline, &t_end); - - t_start_usec = timespec_to_usec(&t_start); if (timings) curr_timing = &timings[i]; else curr_timing = &tmp_timing;
+ t_diff = timespec_sub(&t_end, &t_start); + + t_start_usec = timespec_to_usec(&t_start); + curr_timing->ind = data->ind; - curr_timing->period = timespec_to_usec(&pdata->period); - curr_timing->min_et = timespec_to_usec(&pdata->min_et); - curr_timing->max_et = timespec_to_usec(&pdata->max_et); curr_timing->rel_start_time = t_start_usec - timespec_to_usec(&data->main_app_start); - curr_timing->abs_start_time = t_start_usec; + curr_timing->start_time = t_start_usec; curr_timing->end_time = timespec_to_usec(&t_end); - curr_timing->deadline = timespec_to_usec(&pdata->deadline); - curr_timing->duration = timespec_to_usec(&t_diff); - curr_timing->slack = timespec_to_lusec(&t_slack); + curr_timing->period = timespec_to_usec(&t_diff); + curr_timing->duration = duration; + curr_timing->perf = perf;
#ifdef AQUOSA if (data->sched_policy == aquosa) { @@ -547,35 +474,15 @@ void *thread_body(void *arg) if (!timings) log_timing(data->log_handler, curr_timing);
- t_next = timespec_add(&t_next, &pdata->period); - pdata->deadline = timespec_add(&pdata->deadline, &pdata->period); - if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] end loop %d phase %d step %d", data->ind, i, j, loop);
- if (curr_timing->slack < 0 && opts.die_on_dmiss) { - log_critical("[%d] DEADLINE MISS !!!", data->ind); - if (opts.ftrace) - log_ftrace(ft_data.marker_fd, - "[%d] DEADLINE MISS!!", data->ind); - shutdown(SIGTERM); - goto exit_miss; - } - - clock_gettime(CLOCK_MONOTONIC, &t_now); - if (timespec_lower(&t_now, &t_next)) - clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t_next, NULL); - loop++; if (loop == pdata->loop) { loop = 0;
- clock_gettime(CLOCK_MONOTONIC, &t_now); - t_next = t_now; - pdata->deadline = timespec_add(&t_now, &pdata->deadline); - j++; if (j == data->nphases) { j = 0; @@ -587,7 +494,6 @@ void *thread_body(void *arg) } }
-exit_miss: param.sched_priority = 0; ret = pthread_setschedparam(pthread_self(), SCHED_OTHER, @@ -620,7 +526,7 @@ exit_miss:
int main(int argc, char* argv[]) { - struct timespec t_curr, t_next, t_start; + struct timespec t_start; FILE *gnuplot_script = NULL; int i, res; thread_data_t *tdata; @@ -687,15 +593,6 @@ int main(int argc, char* argv[]) /* start threads */ for (i = 0; i < nthreads; i++) { tdata = &opts.threads_data[i]; - if (opts.spacing > 0 ) { - /* start the thread, then it will sleep accordingly - * to its position. We don't sleep here anymore as - * this would mean that - * duration = spacing * nthreads + duration */ - tdata->wait_before_start = opts.spacing * (i+1); - } else { - tdata->wait_before_start = 0; - }
tdata->duration = opts.duration; tdata->main_app_start = t_start; @@ -727,27 +624,24 @@ int main(int argc, char* argv[])
/* print gnuplot files */ if (opts.logdir && opts.gnuplot) { - snprintf(tmp, PATH_LENGTH, "%s/%s-duration.plot", + snprintf(tmp, PATH_LENGTH, "%s/%s-period.plot", opts.logdir, opts.logbasename); gnuplot_script = fopen(tmp, "w+"); - snprintf(tmp, PATH_LENGTH, "%s-duration.eps", + snprintf(tmp, PATH_LENGTH, "%s-period.eps", opts.logbasename); fprintf(gnuplot_script, "set terminal postscript enhanced color\n" "set output '%s'\n" "set grid\n" "set key outside right\n" - "set title "Measured exec time per period"\n" - "set xlabel "Cycle start time [usec]"\n" - "set ylabel "Exec Time [usec]"\n" + "set title "Measured time per period"\n" + "set xlabel "Loop start time [usec]"\n" + "set ylabel "Period Time [usec]"\n" "plot ", tmp);
- for (i=0; i<nthreads; i++) { - snprintf(tmp, PATH_LENGTH, "%s/%s-duration.plot", - opts.logdir, opts.logbasename); - + for (i = 0; i < nthreads; i++) { fprintf(gnuplot_script, - ""%s-%s.log" u ($5/1000):9 w l" + ""%s-%s.log" u ($5/1000):4 w l" " title "thread [%s] (%s)"", opts.logbasename, opts.threads_data[i].name, opts.threads_data[i].name, @@ -762,10 +656,11 @@ int main(int argc, char* argv[]) fprintf(gnuplot_script, "set terminal wxt\nreplot\n"); fclose(gnuplot_script);
- snprintf(tmp, PATH_LENGTH, "%s/%s-slack.plot", + /* gnuplot of the run time */ + snprintf(tmp, PATH_LENGTH, "%s/%s-run.plot", opts.logdir, opts.logbasename); gnuplot_script = fopen(tmp, "w+"); - snprintf(tmp, PATH_LENGTH, "%s-slack.eps", + snprintf(tmp, PATH_LENGTH, "%s-run.eps", opts.logbasename);
fprintf(gnuplot_script, @@ -773,21 +668,21 @@ int main(int argc, char* argv[]) "set output '%s'\n" "set grid\n" "set key outside right\n" - "set title "Slack (negative = tardiness)"\n" - "set xlabel "Cycle start time [msec]"\n" - "set ylabel "Slack/Tardiness [usec]"\n" + "set title "Measured run time per loop"\n" + "set xlabel "Loop start time [usec]"\n" + "set ylabel "Run Time [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" + ""%s-%s.log" u ($5/1000):3 w l" " title "thread [%s] (%s)"", opts.logbasename, opts.threads_data[i].name, opts.threads_data[i].name, opts.threads_data[i].sched_policy_descr);
if ( i == nthreads-1) - fprintf(gnuplot_script, ", 0 notitle\n"); + fprintf(gnuplot_script, "\n"); else fprintf(gnuplot_script, ", ");
diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index b399916..0f8998e 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -235,220 +235,107 @@ static int get_resource_index(const char *name, rtapp_resource_t *resources) }
static void -serialize_acl(rtapp_resource_access_list_t **acl, - const char *name, - struct json_object *task_resources, - rtapp_resource_t *resources) +parse_thread_event_data(char *name, struct json_object *obj, + event_data_t *data, const rtapp_options_t *opts) { - int i, idx, found; - struct json_object *access, *res, *next_res; - rtapp_resource_access_list_t *tmp; - const char * next_name; - - idx = get_resource_index(name, resources); - - if (!(*acl)) { - *acl = malloc( sizeof(rtapp_resource_access_list_t)); - (*acl)->res = &resources[idx]; -// (*acl)->index = idx; - (*acl)->next = NULL; - (*acl)->prev = NULL; - tmp = *acl; - } else { - found = 0; - tmp = *acl; - while (tmp->next != NULL) { - if (tmp->res->index == idx) - found = 1; - tmp = tmp->next; - } - if (found == 0) { - /* add the resource to the acl only if it is not already - * present in the list */ - tmp->next = malloc ( sizeof (rtapp_resource_access_list_t)); - // tmp->next->index = idx; - tmp->next->next = NULL; - tmp->next->prev = tmp; - tmp->next->res = &resources[idx]; - } - } + int i;
- res = get_in_object(task_resources, name, TRUE); - if (!res) - return; - assure_type_is(res, task_resources, name, json_type_object); + if (!strncmp(name, "run", strlen("run")) || + !strncmp(name, "sleep", strlen("sleep"))) { + if (!json_object_is_type(obj, json_type_int)) + goto unknown_event;
- access = get_in_object(res, "access", TRUE); - if (!access) + data->duration = json_object_get_int(obj); + + if (!strncmp(name, "sleep", strlen("sleep"))) + data->type = rtapp_sleep; + else + data->type = rtapp_run; + + log_info(PIN2 "type %d duration %d", data->type, data->duration); return; - assure_type_is(access, res, "access", json_type_array); + }
- for (i=0; i<json_object_array_length(access); i++) - { - char res_name[5]; + if (!strncmp(name, "lock", strlen("lock")) || + !strncmp(name, "unlock", strlen("unlock"))) { + if (!json_object_is_type(obj, json_type_string)) + goto unknown_event;
- next_res = json_object_array_get_idx(access, i); - if (!json_object_is_type(next_res, json_type_string)){ - if (!json_object_is_type(next_res, json_type_int)){ - log_critical("Invalid resource index"); - exit(EXIT_INV_CONFIG); - } else { - snprintf(res_name, 5, "%d", json_object_get_int(next_res)); - next_name = res_name; - } - log_critical("Legacy resource index"); - } else - next_name = json_object_get_string(next_res); - /* recurse on the rest of resources */ - serialize_acl(&(*acl), next_name, task_resources, resources); + i = get_resource_index(json_object_get_string(obj), + opts->resources); + + if (i >= opts->nresources) + goto unknown_event; + + data->res = &opts->resources[i]; + + if (!strncmp(name, "lock", strlen("lock"))) + data->type = rtapp_lock; + else + data->type = rtapp_unlock; + + log_info(PIN2 "type %d target %s", data->type, data->res->name); + return; } + +unknown_event: + data->duration = 0; + data->type = rtapp_run; + log_info(PIN2 "unknown type %d duration %d", data->type, data->duration); }
-static void -parse_thread_resources(const rtapp_options_t *opts, struct json_object *locks, - struct json_object *task_resources, phase_data_t *data) +static int +obj_is_event(char *name) { - int i, j, usage_usec; - struct json_object *res; - int res_dur; - char res_name[5]; - const char *cur_res_name; - - rtapp_resource_access_list_t *tmp, *head, *last; - char debug_msg[512], tmpmsg[512]; - - data->nblockages = json_object_array_length(locks); - 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_string)) { - if (!json_object_is_type(res, json_type_int)) { - log_critical("Invalid resource index"); - exit(EXIT_INV_CONFIG); - } else { - snprintf(res_name, 5, "%d", json_object_get_int(res)); - cur_res_name = res_name; - } - log_critical("Legacy resource index"); - } else - cur_res_name = json_object_get_string(res); - - data->blockages[i].usage = usec_to_timespec(0); - data->blockages[i].acl = NULL; - serialize_acl(&data->blockages[i].acl, cur_res_name, - task_resources, opts->resources); - - /* since the "current" resource is returned as the first - * element in the list, we move it to the back */ - tmp = data->blockages[i].acl; - head = data->blockages[i].acl; - do { - last = tmp; - tmp = tmp->next; - } while (tmp != NULL); - - /* move first element to list end */ - if (last != head) { - data->blockages[i].acl = head->next; - data->blockages[i].acl->prev = NULL; - last->next = head; - head->next = NULL; - head->prev = last; - } - - tmp = data->blockages[i].acl; - debug_msg[0] = '\0'; - do { - snprintf(tmpmsg, 512, "%s %d", debug_msg, tmp->res->index); - strncpy(debug_msg, tmpmsg, 512); - last = tmp; - tmp = tmp->next; - } while (tmp != NULL); - - log_info(PIN "key: acl %s", debug_msg); - - res = get_in_object(task_resources, cur_res_name, TRUE); - if (!res) { - usage_usec = 0; - data->blockages[i].usage = usec_to_timespec(0); - } else { - assure_type_is(res, task_resources, res_name, - json_type_object); - usage_usec = get_int_value_from(res, "duration", TRUE, 0); - data->blockages[i].usage = usec_to_timespec(usage_usec); - } - log_info(PIN "res %s, usage: %d acl: %s", cur_res_name, - usage_usec, debug_msg); - } + if (!strncmp(name, "lock", strlen("lock"))) + return 1; + if (!strncmp(name, "unlock", strlen("unlock"))) + return 1; + if (!strncmp(name, "sleep", strlen("sleep"))) + return 1; + if (!strncmp(name, "run", strlen("run"))) + return 1; + + return 0; }
static void -parse_thread_phase_data(struct json_object *obj, int idx, - phase_data_t *data, const rtapp_options_t *opts) +parse_thread_phase_data(struct json_object *obj, phase_data_t *data, + const rtapp_options_t *opts) { - long exec, period, dline; - struct json_object *resources, *locks; + /* used in the foreach macro */ + struct lh_entry *entry; char *key; struct json_object *val; int idx; + int i;
/* loop */ data->loop = get_int_value_from(obj, "loop", TRUE, -1);
- /* exec time */ - exec = get_int_value_from(obj, "exec", FALSE, 0); - if (exec < 0) { - log_critical(PIN2 "Cannot set negative exec time"); - exit(EXIT_INV_CONFIG); + /* Count number of events */ + data->nbevents = 0; + foreach(obj, entry, key, val, idx) { + if (obj_is_event(key)) + data->nbevents++; } - data->min_et = usec_to_timespec(exec); - data->max_et = usec_to_timespec(exec); + log_info(PIN "Found %d events", data->nbevents);
- /* period */ - period = get_int_value_from(obj, "period", TRUE, exec); - if (period <= 0) { - log_critical(PIN2 "Cannot set negative period"); - exit(EXIT_INV_CONFIG); - } - if (exec > period) { - log_critical(PIN2 "Period must be greater or equal than period"); - exit(EXIT_INV_CONFIG); - } + if (data->nbevents == 0) + return;
- data->period = usec_to_timespec(period); + data->events = malloc(data->nbevents * sizeof(event_data_t));
- /* 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); - - /* resources */ - resources = get_in_object(obj, "resources", TRUE); - locks = get_in_object(obj, "lock_order", TRUE); - if (locks) { - assure_type_is(locks, obj, "lock_order", json_type_array); - log_info(PIN "key: lock_order %s", json_object_to_json_string(locks)); - if (resources) { - assure_type_is(resources, obj, "resources", - json_type_object); - log_info(PIN "key: resources %s", - json_object_to_json_string(resources)); + /* Parse events */ + i = 0; + foreach(obj, entry, key, val, idx) { + if (obj_is_event(key)) { + log_info(PIN "Parsing event %s", key); + parse_thread_event_data(key, val, &data->events[i], opts); + i++; } - parse_thread_resources(opts, locks, resources, data); - } else { - data->nblockages = 0; } }
static void -parse_thread_data(char *name, struct json_object *obj, int idx, +parse_thread_data(char *name, struct json_object *obj, int index, thread_data_t *data, const rtapp_options_t *opts) { long exec, period, dline; @@ -458,19 +345,16 @@ parse_thread_data(char *name, struct json_object *obj, int idx, struct json_object *cpuset_obj, *phases_obj, *cpu, *resources, *locks; int i, cpu_idx;
- log_info(PFX "Parsing thread %s [%d]", name, idx); + log_info(PFX "Parsing thread %s [%d]", name, index);
/* common and defaults */ - data->ind = idx; + data->ind = index; data->name = strdup(name); data->lock_pages = opts->lock_pages; data->sched_prio = DEFAULT_THREAD_PRIORITY; data->cpuset = NULL; data->cpuset_str = NULL;
- /* loop */ - data->loop = get_int_value_from(obj, "loop", TRUE, -1); - /* policy */ policy_to_string(opts->policy, def_policy); policy = get_string_value_from(obj, "policy", TRUE, def_policy); @@ -486,7 +370,7 @@ parse_thread_data(char *name, struct json_object *obj, int idx, data->sched_prio = get_int_value_from(obj, "priority", TRUE, DEFAULT_THREAD_PRIORITY);
- /* cpu set */ + /* cpuset */ cpuset_obj = get_in_object(obj, "cpus", TRUE); if (cpuset_obj) { assure_type_is(cpuset_obj, obj, "cpus", json_type_array); @@ -494,7 +378,7 @@ parse_thread_data(char *name, struct json_object *obj, int idx, data->cpuset = malloc(sizeof(cpu_set_t)); cpuset = json_object_get_array(cpuset_obj); CPU_ZERO(data->cpuset); - for (i=0; i < json_object_array_length(cpuset_obj); i++) { + for (i = 0; i < json_object_array_length(cpuset_obj); i++) { cpu = json_object_array_get_idx(cpuset_obj, i); cpu_idx = json_object_get_int(cpu); CPU_SET(cpu_idx, data->cpuset); @@ -505,7 +389,7 @@ parse_thread_data(char *name, struct json_object *obj, int idx, } log_info(PIN "key: cpus %s", data->cpuset_str);
- /* phases */ + /* Get phases */ phases_obj = get_in_object(obj, "phases", TRUE); if (phases_obj) { /* used in the foreach macro */ @@ -518,17 +402,22 @@ parse_thread_data(char *name, struct json_object *obj, int idx, foreach(phases_obj, entry, key, val, idx) { data->nphases++; } + log_info(PIN "Found %d phases", data->nphases); data->phases_data = malloc(sizeof(phase_data_t) * data->nphases); foreach(phases_obj, entry, key, val, idx) { log_info(PIN "Parsing phase %s", key); - parse_thread_phase_data(val, idx, &data->phases_data[idx], opts); + parse_thread_phase_data(val, &data->phases_data[idx], opts); } + + /* Get loop number */ + data->loop = get_int_value_from(obj, "loop", TRUE, -1); + } else { data->nphases = 1; data->phases_data = malloc(sizeof(phase_data_t) * data->nphases); + parse_thread_phase_data(obj, &data->phases_data[0], opts); data->loop = 1; - parse_thread_phase_data(obj, 0, data->phases_data, opts); } }
@@ -558,7 +447,6 @@ parse_global(struct json_object *global, rtapp_options_t *opts) int scan_cnt;
log_info(PFX "Parsing global section"); - opts->spacing = get_int_value_from(global, "spacing", TRUE, 0); opts->duration = get_int_value_from(global, "duration", TRUE, -1); opts->gnuplot = get_bool_value_from(global, "gnuplot", TRUE, 0); policy = get_string_value_from(global, "default_policy", diff --git a/src/rt-app_types.h b/src/rt-app_types.h index b8988f7..aeea37d 100644 --- a/src/rt-app_types.h +++ b/src/rt-app_types.h @@ -61,7 +61,9 @@ typedef enum resource_t { rtapp_mutex = 0, rtapp_sleep, - rtapp_run + rtapp_run, + rtapp_lock, + rtapp_unlock } resource_t;
struct _rtapp_mutex { @@ -79,23 +81,17 @@ typedef struct _rtapp_resource_t { char *name; } rtapp_resource_t;
-typedef struct _rtapp_resource_access_list_t { +typedef struct _event_data_t { + resource_t type; rtapp_resource_t *res; - struct _rtapp_resource_access_list_t *next; - struct _rtapp_resource_access_list_t *prev; -} rtapp_resource_access_list_t; - -typedef struct _rtapp_tasks_resource_list_t { - struct timespec usage; - struct _rtapp_resource_access_list_t *acl; -} rtapp_tasks_resource_list_t; + int duration; + int count; +} event_data_t;
typedef struct _phase_data_t { - struct timespec min_et, max_et; - struct timespec period, deadline; - int loop, sleep; - rtapp_tasks_resource_list_t *blockages; - int nblockages; + int loop; + event_data_t *events; + int nbevents; } phase_data_t;
typedef struct _thread_data_t { @@ -105,7 +101,6 @@ typedef struct _thread_data_t { int duration; cpu_set_t *cpuset; char *cpuset_str; - unsigned long wait_before_start; struct timespec main_app_start; int loop; int nphases; @@ -141,7 +136,6 @@ typedef struct _rtapp_options_t {
policy_t policy; int duration; - unsigned long spacing;
char *logdir; char *logbasename; @@ -164,14 +158,11 @@ typedef struct _rtapp_options_t { typedef struct _timing_point_t { int ind; unsigned long period; - unsigned long min_et; - unsigned long max_et; unsigned long rel_start_time; - unsigned long abs_start_time; + unsigned long start_time; unsigned long end_time; - unsigned long deadline; unsigned long duration; - long slack; + unsigned long perf; #ifdef AQUOSA qres_time_t budget; qres_time_t used_budget; diff --git a/src/rt-app_utils.c b/src/rt-app_utils.c index 1e13ee0..46de2b6 100644 --- a/src/rt-app_utils.c +++ b/src/rt-app_utils.c @@ -137,17 +137,14 @@ void log_timing(FILE *handler, timing_point_t *t) { fprintf(handler, - "%d\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu\t%ld", + "%d\t%lu\t%lu\t%lu\t%lu\t%lu\t%lu", t->ind, + t->perf, + t->duration, t->period, - t->min_et, - t->max_et, - t->rel_start_time, - t->abs_start_time, + t->start_time, t->end_time, - t->deadline, - t->duration, - t->slack + t->rel_start_time ); #ifdef AQUOSA fprintf(handler,