diff options
author | Vincent Guittot <vincent.guittot@linaro.org> | 2014-09-10 09:30:42 +0200 |
---|---|---|
committer | Vincent Guittot <vincent.guittot@linaro.org> | 2014-09-10 09:41:55 +0200 |
commit | 82dae3e5ee2fdb1d759364d9d261e5c404d56269 (patch) | |
tree | 305833cc3c5c86dde5d38e91ac26b07f2e945377 /src | |
parent | 101a6f17cca9c4274c43a4b77963c92652e1ba91 (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.c | 311 | ||||
-rw-r--r-- | src/rt-app_parse_config.c | 335 | ||||
-rw-r--r-- | src/rt-app_types.h | 29 |
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; |