summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVincent Guittot <vincent.guittot@linaro.org>2014-09-10 09:30:42 +0200
committerVincent Guittot <vincent.guittot@linaro.org>2014-09-10 09:41:55 +0200
commit82dae3e5ee2fdb1d759364d9d261e5c404d56269 (patch)
tree305833cc3c5c86dde5d38e91ac26b07f2e945377 /src
parent101a6f17cca9c4274c43a4b77963c92652e1ba91 (diff)
simplify the grammar
Remove the lock_order and ressources objects Instead just describe the events sequence. Each event name must be unique and start with one of the below known prefix: run : run a load sleep : sleep for a duration lock : lock a mutex unlock : unlock a mutex wait : wait for a signal signal : send a signal broadcast : braodcast a signal sync : atomic signal and wait event As an example: "run0" : 275, "lock0" : "trig1_mutex", "signal0" : "trig1", "unlock0" : "trig1_mutex", "run1" : 4725, "sleep1" : 19000,
Diffstat (limited to 'src')
-rw-r--r--src/rt-app.c311
-rw-r--r--src/rt-app_parse_config.c335
-rw-r--r--src/rt-app_types.h29
3 files changed, 249 insertions, 426 deletions
diff --git a/src/rt-app.c b/src/rt-app.c
index 578447d..32ce417 100644
--- a/src/rt-app.c
+++ b/src/rt-app.c
@@ -100,127 +100,98 @@ int calibrate_cpu_cycles(int clock)
return 0;
}
-static inline loadwait(struct timespec *exec_time)
+static inline 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;
- rtapp_resource_access_list_t *prev;
+ unsigned long lock = 0;
- switch(lock->res->type) {
- case rtapp_mutex:
- pthread_mutex_lock(&(lock->res->res.mtx.obj));
+ 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;
+ }
+
+ if (dry_run)
+ return lock;
+
+ switch(event->type) {
case rtapp_wait:
- prev = lock->prev;
- pthread_cond_wait(&(lock->res->res.cond.obj), &(prev->res->res.mtx.obj));
+ log_debug("wait %s ", event->res->name);
+ pthread_cond_wait(&(event->res->res.cond.obj), &(event->dep->res.mtx.obj));
break;
case rtapp_signal:
- pthread_cond_signal(lock->res->res.signal.target);
+ log_debug("signal %s ", event->res->name);
+ pthread_cond_signal(event->res->res.signal.target);
break;
case rtapp_sig_and_wait:
- pthread_cond_signal(lock->res->res.signal.target);
- prev = lock->prev;
- pthread_cond_wait(lock->res->res.signal.target, &(prev->res->res.mtx.obj));
+ log_debug("signal and wait %s", event->res->name);
+ pthread_cond_signal(event->res->res.signal.target);
+ pthread_cond_wait(event->res->res.signal.target, &(event->dep->res.mtx.obj));
break;
case rtapp_broadcast:
- pthread_cond_broadcast(lock->res->res.signal.target);
+ pthread_cond_broadcast(event->res->res.signal.target);
break;
case rtapp_sleep:
- nanosleep(usage, NULL);
- busywait = 0;
+ {
+ struct timespec 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;
break;
}
- return busywait;
-}
-
-void put_resource(rtapp_resource_access_list_t *lock)
-{
- if (lock->res->type == rtapp_mutex)
- pthread_mutex_unlock(&(lock->res->res.mtx.obj));
+ return lock;
}
-void run(int ind, struct timespec *min, rtapp_tasks_resource_list_t *blockages,
- int nblockages, struct timespec *t_start)
+int run(int ind, event_data_t *events,
+ int nbevents, unsigned long *duration)
{
- int i, busywait = 1;
- struct timespec t_exec;
- rtapp_resource_access_list_t *lock, *last;
+ int i, lock = 0;
+ unsigned long perf = 0;
- t_exec = *min;
-
- log_debug("[%d] loop for %lu", ind, timespec_to_usec(&t_exec));
-
- for (i = 0; i < nblockages; i++)
+ for (i = 0; i < nbevents; i++)
{
- if (!continue_running)
+ if (!continue_running && !lock)
return;
- /* Lock resources sequence including the busy wait */
- lock = blockages[i].acl;
- while (lock != NULL && continue_running) {
- log_debug("[%d] locking %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] locking %d",
- ind, lock->res->index);
- busywait = get_resource(lock, &blockages[i].usage);
- last = lock;
- lock = lock->next;
- }
-
- if (!i && t_start)
- clock_gettime(CLOCK_MONOTONIC, t_start);
-
- if (continue_running && 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);
-
- /* Check consistency between exec and sum of usage */
- if (timespec_lower(&t_exec, &blockages[i].usage))
- t_exec = usec_to_timespec(0);
- else
- t_exec = timespec_sub(&t_exec, &blockages[i].usage);
- }
-
- /* 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);
- put_resource(lock);
- lock = lock->prev;
- }
-
+ ind, events[i].type);
+ lock += run_event(&events[i], !continue_running, &perf, duration);
}
- if (!continue_running)
- return;
-
- /* 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 %d",
- ind, timespec_to_usec(&t_exec));
- loadwait(&t_exec);
+ return perf;
}
static void
@@ -262,13 +233,12 @@ 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 *curr_timing;
timing_point_t *timings;
timing_point_t tmp_timing;
- timing_point_t *curr_timing;
pid_t tid;
struct sched_attr attr;
unsigned int flags = 0;
@@ -281,7 +251,7 @@ void *thread_body(void *arg)
}
/* Get the 1st phase's data */
- pdata = &data->phases_data[0];
+ pdata = &data->phases[0];
/* Set thread affinity */
if (data->cpuset != NULL)
@@ -350,10 +320,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->exec) +
- (timespec_to_nsec(&pdata->exec) /100) * BUDGET_OVERP;
- attr.sched_deadline = timespec_to_nsec(&pdata->deadline);
- attr.sched_period = timespec_to_nsec(&pdata->period);
break;
#endif
@@ -376,53 +342,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->exec),
- timespec_to_usec(&pdata->deadline));
+ log_notice("[%d] starting thread ...\n", data->ind);
- /*
- * If we know the duration we can calculate how many periods we will
- * do at most, and log to memory, instead of logging to file.
- * In case of several phase, we use the logging file until we fix the way
- * to compute the number of period
- * TODO: parse all phases to compute the memory size
- */
- 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;
- }
-
- 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\trel_st\tstart"
- "\t\tend\t\tdur.\tslack\n");
-
- /* Delay the start of the pattern if required */
- 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");
if (opts.ftrace)
log_ftrace(ft_data.marker_fd, "[%d] starts", data->ind);
@@ -434,14 +358,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 "
@@ -452,82 +368,59 @@ void *thread_body(void *arg)
}
}
#endif
-
- /* Get the start time */
- clock_gettime(CLOCK_MONOTONIC, &t_next);
-
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);;
+ duration = 0;
clock_gettime(CLOCK_MONOTONIC, &t_start);
- run(data->ind, &pdata->exec, pdata->blockages, pdata->nblockages,
- pdata->sleep ? NULL: &t_start);
+ 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_diff);
-
- t_start_usec = timespec_to_usec(&t_start);
-
if (timings)
curr_timing = &timings[loop];
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->exec = timespec_to_usec(&pdata->exec);
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->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;
if (!timings)
log_timing(data->log_handler, curr_timing);
- t_next = timespec_add(&t_next, &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 (pdata->sleep && 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_next);
-
j++;
if (j == data->nphases) {
j = 0;
i++;
}
- pdata = &data->phases_data[j];
+ pdata = &data->phases[j];
}
}
-exit_miss:
param.sched_priority = 0;
ret = pthread_setschedparam(pthread_self(),
SCHED_OTHER,
@@ -553,10 +446,11 @@ 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;
+ int i, res, nresources;
thread_data_t *tdata;
+ rtapp_resource_t *rdata;
char tmp[PATH_LENGTH];
static cpu_set_t orig_set;
@@ -618,7 +512,7 @@ int main(int argc, char* argv[])
/* Prepare log file of each thread before starting the use case */
for (i = 0; i < nthreads; i++) {
- tdata = &opts.threads_data[i];
+ tdata = &opts.threads_data[i];
tdata->duration = opts.duration;
tdata->main_app_start = t_start;
@@ -639,30 +533,27 @@ int main(int argc, char* argv[])
}
}
-
/* Prepare gnuplot files before starting the use case */
if (opts.logdir && opts.gnuplot) {
- snprintf(tmp, PATH_LENGTH, "%s/%s-duration.plot",
+ /* gnuplot plot of the period */
+ 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 loop\"\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);
-
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,
@@ -677,32 +568,32 @@ 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,
"set terminal postscript enhanced color\n"
"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 8940318..e5e34c0 100644
--- a/src/rt-app_parse_config.c
+++ b/src/rt-app_parse_config.c
@@ -275,224 +275,159 @@ static int get_resource_index(char *name, rtapp_resource_t *resources)
}
static void
-serialize_acl(rtapp_resource_access_list_t **acl,
- 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;
- char * next_name;
+ int i;
+
+ if (!strncmp(name, "run", strlen("run")) ||
+ !strncmp(name, "sleep", strlen("sleep"))) {
+ if (!json_object_is_type(obj, json_type_int))
+ goto unknown_event;
+
+ data->duration = json_object_get_int(obj);
+
+ if (!strncmp(name, "sleep", strlen("sleep")))
+ data->type = rtapp_sleep;
+ else
+ data->type = rtapp_run;
- if (!task_resources)
+ log_info(PIN2 "type %d duration %d", data->type, data->duration);
return;
+ }
- idx = get_resource_index(name, resources);
+ if (!strncmp(name, "lock", strlen("lock")) ||
+ !strncmp(name, "unlock", strlen("unlock"))) {
+ if (!json_object_is_type(obj, json_type_string))
+ goto unknown_event;
- if (!(*acl)) {
- *acl = malloc( sizeof(rtapp_resource_access_list_t));
- (*acl)->res = &resources[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->next = NULL;
- tmp->next->prev = tmp;
- tmp->next->res = &resources[idx];
- }
+ 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;
}
- res = get_in_object(task_resources, name, TRUE);
- if (!res)
+ if (!strncmp(name, "signal", strlen("signal")) ||
+ !strncmp(name, "broad", strlen("broad"))) {
+ if (!json_object_is_type(obj, json_type_string))
+ goto unknown_event;
+
+ 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, "signal", strlen("signal")))
+ data->type = rtapp_signal;
+ else
+ data->type = rtapp_broadcast;
+
+ log_info(PIN2 "type %d target %s", data->type, data->res->name);
return;
- assure_type_is(res, task_resources, name, json_type_object);
+ }
- access = get_in_object(res, "access", TRUE);
- if (!access)
+ if (!strncmp(name, "sync", strlen("sync")) ||
+ !strncmp(name, "wait", strlen("wait"))) {
+ i = get_resource_index(get_string_value_from(obj, "ref", TRUE, "unknown"), opts->resources);
+ if (i >= opts->nresources)
+ goto unknown_event;
+ data->res = &opts->resources[i];
+
+ i = get_resource_index(get_string_value_from(obj, "mutex", TRUE, "unknown"), opts->resources);
+ if (i >= opts->nresources)
+ goto unknown_event;
+ data->dep = &opts->resources[i];
+
+ if (!strncmp(name, "wait", strlen("wait")))
+ data->type = rtapp_wait;
+ else
+ data->type = rtapp_sig_and_wait;
+ log_info(PIN2 "type %d target %s mutex %s", data->type, data->res->name, data->dep->name);
return;
- assure_type_is(access, res, "access", json_type_array);
+ }
- for (i=0; i<json_object_array_length(access); i++)
- {
- char res_name[5];
- 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);
}
+
+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];
- 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, "wait", strlen("wait")))
+ return 1;
+ if (!strncmp(name, "signal", strlen("signal")))
+ return 1;
+ if (!strncmp(name, "broad", strlen("broad")))
+ return 1;
+ if (!strncmp(name, "sync", strlen("sync")))
+ 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,
+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);
+ 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->exec = 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);
-
- /* sleep */
- data->sleep = get_bool_value_from(obj, "sleep", TRUE, 1);
-
- /* 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)
{
char *policy;
@@ -501,10 +436,10 @@ 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, prior_def;
- 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->cpuset = NULL;
@@ -530,10 +465,8 @@ parse_thread_data(char *name, struct json_object *obj, int idx,
data->sched_prio = get_int_value_from(obj, "priority", TRUE,
prior_def);
- /* delay */
- data->wait_before_start = get_int_value_from(obj, "delay", TRUE, 0);
- /* cpu set */
+ /* cpuset */
cpuset_obj = get_in_object(obj, "cpus", TRUE);
if (cpuset_obj) {
assure_type_is(cpuset_obj, obj, "cpus", json_type_array);
@@ -541,7 +474,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);
@@ -552,10 +485,7 @@ parse_thread_data(char *name, struct json_object *obj, int idx,
}
log_info(PIN "key: cpus %s", data->cpuset_str);
-
- data->loop = get_int_value_from(obj, "loop", TRUE, -1);
-
- /* phases */
+ /* Get phases */
phases_obj = get_in_object(obj, "phases", TRUE);
if (phases_obj) {
/* used in the foreach macro */
@@ -569,18 +499,25 @@ 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);
+ data->phases = 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[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);
+ data->phases = malloc(sizeof(phase_data_t) * data->nphases);
+ parse_thread_phase_data(obj, &data->phases[0], opts);
+ /* Get loop number */
data->loop = 1;
- parse_thread_phase_data(obj, 0, data->phases_data, opts);
}
+
}
static void
diff --git a/src/rt-app_types.h b/src/rt-app_types.h
index 89dcb3a..f063a07 100644
--- a/src/rt-app_types.h
+++ b/src/rt-app_types.h
@@ -59,6 +59,8 @@ typedef enum resource_t
rtapp_sleep,
rtapp_run,
rtapp_sig_and_wait,
+ rtapp_lock,
+ rtapp_unlock,
} resource_t;
struct _rtapp_mutex {
@@ -87,23 +89,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;
+ rtapp_resource_t *dep;
+ int duration;
+} event_data_t;
typedef struct _phase_data_t {
- struct timespec exec;
- 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 {
@@ -113,11 +109,10 @@ typedef struct _thread_data_t {
int duration;
cpu_set_t *cpuset;
char *cpuset_str;
- unsigned long wait_before_start;
- int nphases;
- phase_data_t *phases_data;
int loop;
+ int nphases;
+ phase_data_t *phases;
struct timespec main_app_start;