This series adds several new features to rt-app, e.g. signal, wait, broadcast, run, sleep ...etc. and updates the example taskset.json file to reflect those new features.
These patches are also found: ssh://git@git.linaro.org/people/picheng.chen/rt-app.git features_series1
Sanjay Singh Rawat (1): add delay param in thread parameters
Vincent Guittot (10): Add new wait, signal, and broadcast resources update the .json test file to reflect new capabilities add loop feature rt-app: make load frequency independent. update example file with new loop capabilities add sleep and run type of resources update taskset.json example with run and sleep capabilities make possible to remove the sleep step modify stat to reflect new behavior update example file with more capabilities
doc/taskset.json | 104 ++++++++++++---------- src/rt-app.c | 155 +++++++++++++++++++++++++++------ src/rt-app_parse_config.c | 214 +++++++++++++++++++++++++++++++++++++--------- src/rt-app_types.h | 35 +++++++- src/rt-app_utils.c | 64 ++++++++++++++ src/rt-app_utils.h | 9 ++ 6 files changed, 467 insertions(+), 114 deletions(-)
From: Vincent Guittot vincent.guittot@linaro.org
mutex is no more the only kind of resources but you can also use pthread_cond/wait/broadcast function
In addition, you can also use a plain string name instead of index in lock order array and resources description
Signed-off-by: Vincent Guittot vincent.guittot@linaro.org --- src/rt-app.c | 33 +++++++- src/rt-app_parse_config.c | 204 ++++++++++++++++++++++++++++++++++++---------- src/rt-app_types.h | 32 +++++++- src/rt-app_utils.c | 37 +++++++++ src/rt-app_utils.h | 6 ++ 5 files changed, 267 insertions(+), 45 deletions(-)
diff --git a/src/rt-app.c b/src/rt-app.c index 118f91a..f69977a 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -44,6 +44,35 @@ static inline busywait(struct timespec *to) } }
+void lock_resource(rtapp_resource_access_list_t *lock) +{ + rtapp_resource_access_list_t *prev; + + switch(lock->res->type) { + case rtapp_wait: + prev = lock->prev; + pthread_cond_wait(&(lock->res->res.cond.obj), &(prev->res->res.mtx.obj)); + break; + case rtapp_signal: + pthread_cond_signal(lock->res->res.signal.target); + break; + case rtapp_broadcast: + pthread_cond_broadcast(lock->res->res.signal.target); + break; + default: + pthread_mutex_lock(&(lock->res->res.mtx.obj)); + } +} + +void unlock_resource(rtapp_resource_access_list_t *lock) +{ + switch(lock->res->type) { + case rtapp_mutex: + pthread_mutex_unlock(&(lock->res->res.mtx.obj)); + break; + } +} + void run(int ind, struct timespec *min, struct timespec *max, rtapp_tasks_resource_list_t *blockages, int nblockages) { @@ -65,7 +94,7 @@ void run(int ind, struct timespec *min, struct timespec *max, log_ftrace(ft_data.marker_fd, "[%d] locking %d", ind, lock->res->index); - pthread_mutex_lock(&lock->res->mtx); + lock_resource(lock); last = lock; lock = lock->next; } @@ -88,7 +117,7 @@ void run(int ind, struct timespec *min, struct timespec *max, log_ftrace(ft_data.marker_fd, "[%d] unlocking %d", ind, lock->res->index); - pthread_mutex_unlock(&lock->res->mtx); + unlock_resource(lock); lock = lock->prev; } } diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index 5cc4493..23e1edd 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -120,7 +120,6 @@ get_int_value_from(struct json_object *where, set_default_if_needed(key, value, have_def, def_value); assure_type_is(value, where, key, json_type_int); i_value = json_object_get_int(value); - json_object_put(value); log_info(PIN "key: %s, value: %d, type <int>", key, i_value); return i_value; } @@ -137,7 +136,6 @@ get_bool_value_from(struct json_object *where, set_default_if_needed(key, value, have_def, def_value); assure_type_is(value, where, key, json_type_boolean); b_value = json_object_get_boolean(value); - json_object_put(value); log_info(PIN "key: %s, value: %d, type <bool>", key, b_value); return b_value; } @@ -158,46 +156,152 @@ get_string_value_from(struct json_object *where, } assure_type_is(value, where, key, json_type_string); s_value = strdup(json_object_get_string(value)); - json_object_put(value); log_info(PIN "key: %s, value: %s, type <string>", key, s_value); return s_value; }
+static int init_mutex_resource(rtapp_resource_t *data, const rtapp_options_t *opts) +{ + log_info(PIN "Init: %s mutex", data->name); + + pthread_mutexattr_init(&data->res.mtx.attr); + if (opts->pi_enabled) { + pthread_mutexattr_setprotocol( + &data->res.mtx.attr, + PTHREAD_PRIO_INHERIT); + } + pthread_mutex_init(&data->res.mtx.obj, + &data->res.mtx.attr); +} + +static int init_cond_resource(rtapp_resource_t *data, const rtapp_options_t *opts) +{ + log_info(PIN "Init: %s wait", data->name); + + pthread_condattr_init(&data->res.cond.attr); + pthread_cond_init(&data->res.cond.obj, + &data->res.cond.attr); +} + +static int init_signal_resource(rtapp_resource_t *data, const rtapp_options_t *opts, char *target) +{ + log_info(PIN "Init: %s signal", data->name); + + int i = 0; + while (strcmp(opts->resources[i].name, target) != 0) { + if (data->index == i) { + log_critical(PIN2 "Invalid target %s", target); + exit(EXIT_INV_CONFIG); + } + i++; + } + + data->res.signal.target = &(opts->resources[i].res.cond.obj); +} + +static void +parse_resource_data(char *name, struct json_object *obj, int idx, + rtapp_resource_t *data, const rtapp_options_t *opts) +{ + char *type, *target; + char def_type[RTAPP_RESOURCE_DESCR_LENGTH]; + + log_info(PFX "Parsing resources %s [%d]", name, idx); + + /* common and defaults */ + data->index = idx; + data->name = strdup(name); + + /* resource type */ + resource_to_string(0, def_type); + type = get_string_value_from(obj, "type", TRUE, def_type); + if (type) { + if (string_to_resource(type, &data->type) != 0) { + log_critical(PIN2 "Invalid type of resource %s", type); + exit(EXIT_INV_CONFIG); + } + } + + switch (data->type) { + case rtapp_wait: + init_cond_resource(data, opts); + break; + case rtapp_signal: + case rtapp_broadcast: + target = get_string_value_from(obj, "target", FALSE, NULL); + init_signal_resource(data, opts, target); + break; + default: + init_mutex_resource(data, opts); + + } +} + +static void parse_legacy_resources(int nresources, rtapp_options_t *opts) +{ + int i; + char name[5]; + + log_info(PIN "Creating %d mutex resources", nresources); + + opts->resources = malloc(sizeof(rtapp_resource_t) * nresources); + for (i = 0; i < nresources; i++) { + opts->resources[i].index = i; + snprintf(name, 5, "%d", i); + opts->resources[i].name = strdup(name); + init_mutex_resource(&opts->resources[i], opts); + } + opts->nresources = nresources; +} + static void parse_resources(struct json_object *resources, rtapp_options_t *opts) { int i; - int res = json_object_get_int(resources); - log_info(PFX "Creating %d resources", res); - opts->resources = malloc(sizeof(rtapp_resource_t) * res); - for (i = 0; i < res; i++) { - pthread_mutexattr_init(&opts->resources[i].mtx_attr); - if (opts->pi_enabled) { - pthread_mutexattr_setprotocol( - &opts->resources[i].mtx_attr, - PTHREAD_PRIO_INHERIT); + struct lh_entry *entry; char *key; struct json_object *val; int idx; + + log_info(PFX "Parsing resource section"); + + if (json_object_is_type(resources, json_type_int)) { + parse_legacy_resources(json_object_get_int(resources), opts); + } + else { + opts->nresources = 0; + foreach(resources, entry, key, val, idx) { + opts->nresources++; + } + + log_info(PFX "Found %d Resources", opts->nresources); + opts->resources = malloc(sizeof(rtapp_resource_t) * opts->nresources); + + foreach (resources, entry, key, val, idx) { + parse_resource_data(key, val, idx, &opts->resources[idx], opts); } - pthread_mutex_init(&opts->resources[i].mtx, - &opts->resources[i].mtx_attr); - opts->resources[i].index = i; } - opts->nresources = res; +} + +static int get_resource_index(char *name, rtapp_resource_t *resources) +{ + int i=0; + + while (strcmp(resources[i].name, name) != 0) + i++; + + return i; }
static void serialize_acl(rtapp_resource_access_list_t **acl, - int idx, + char *name, struct json_object *task_resources, rtapp_resource_t *resources) { - int i, next_idx, found; + int i, idx, found; struct json_object *access, *res, *next_res; rtapp_resource_access_list_t *tmp; - char s_idx[5]; + char * next_name;
- /* as keys are string in the json, we need a string for searching - * the resource */ - snprintf(s_idx, 5, "%d", idx); + idx = get_resource_index(name, resources);
if (!(*acl)) { *acl = malloc( sizeof(rtapp_resource_access_list_t)); @@ -225,10 +329,10 @@ serialize_acl(rtapp_resource_access_list_t **acl, } }
- res = get_in_object(task_resources, s_idx, TRUE); + res = get_in_object(task_resources, name, TRUE); if (!res) return; - assure_type_is(res, task_resources, s_idx, json_type_object); + assure_type_is(res, task_resources, name, json_type_object);
access = get_in_object(res, "access", TRUE); if (!access) @@ -237,14 +341,22 @@ serialize_acl(rtapp_resource_access_list_t **acl,
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_int)){ - log_critical("Invalid resource index"); - exit(EXIT_INV_CONFIG); - } - next_idx = json_object_get_int(next_res); + 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_idx, task_resources, resources); + serialize_acl(&(*acl), next_name, task_resources, resources); } }
@@ -252,10 +364,11 @@ static void parse_thread_resources(const rtapp_options_t *opts, struct json_object *locks, struct json_object *task_resources, thread_data_t *data) { - int i,j, cur_res_idx, usage_usec; + int i, j, usage_usec; struct json_object *res; int res_dur; - char res_name[4]; + char res_name[5]; + char *cur_res_name;
rtapp_resource_access_list_t *tmp, *head, *last; char debug_msg[512], tmpmsg[512]; @@ -267,15 +380,21 @@ parse_thread_resources(const rtapp_options_t *opts, struct json_object *locks, for (i = 0; i< data->nblockages; i++) { res = json_object_array_get_idx(locks, i); - if (!json_object_is_type(res, json_type_int)){ - log_critical("Invalid resource index"); - exit(EXIT_INV_CONFIG); - } - cur_res_idx = json_object_get_int(res); + 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_idx, + serialize_acl(&data->blockages[i].acl, cur_res_name, task_resources, opts->resources);
/* since the "current" resource is returned as the first @@ -307,8 +426,7 @@ parse_thread_resources(const rtapp_options_t *opts, struct json_object *locks,
log_info(PIN "key: acl %s", debug_msg);
- snprintf(res_name, 4, "%d", cur_res_idx); - res = get_in_object(task_resources, res_name, TRUE); + res = get_in_object(task_resources, cur_res_name, TRUE); if (!res) { usage_usec = 0; data->blockages[i].usage = usec_to_timespec(0); @@ -318,7 +436,7 @@ parse_thread_resources(const rtapp_options_t *opts, struct json_object *locks, usage_usec = get_int_value_from(res, "duration", TRUE, 0); data->blockages[i].usage = usec_to_timespec(usage_usec); } - log_info(PIN "res %d, usage: %d acl: %s", cur_res_idx, + log_info(PIN "res %s, usage: %d acl: %s", cur_res_name, usage_usec, debug_msg); } } @@ -335,6 +453,7 @@ parse_thread_data(char *name, struct json_object *obj, int idx, int i, cpu_idx;
log_info(PFX "Parsing thread %s [%d]", name, idx); + /* common and defaults */ data->ind = idx; data->name = strdup(name); @@ -493,8 +612,11 @@ get_opts_from_json_object(struct json_object *root, rtapp_options_t *opts) log_info(PFX "resources: %s", json_object_to_json_string(resources));
parse_global(global, opts); + json_object_put(global); parse_resources(resources, opts); + json_object_put(resources); parse_tasks(tasks, opts); + json_object_put(tasks);
}
diff --git a/src/rt-app_types.h b/src/rt-app_types.h index 603816b..cace363 100644 --- a/src/rt-app_types.h +++ b/src/rt-app_types.h @@ -35,6 +35,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #endif /* AQUOSA */
#define RTAPP_POLICY_DESCR_LENGTH 16 +#define RTAPP_RESOURCE_DESCR_LENGTH 16 #define RTAPP_FTRACE_PATH_LENGTH 256 /* exit codes */
@@ -56,11 +57,38 @@ typedef enum policy_t #endif } policy_t;
+typedef enum resource_t +{ + rtapp_mutex = 0, + rtapp_wait, + rtapp_signal, + rtapp_broadcast, +} resource_t; + +struct _rtapp_mutex { + pthread_mutex_t obj; + pthread_mutexattr_t attr; +} ; + +struct _rtapp_cond { + pthread_cond_t obj; + pthread_condattr_t attr; +}; + +struct _rtapp_signal { + pthread_cond_t *target; +}; + /* Shared resources */ typedef struct _rtapp_resource_t { - pthread_mutex_t mtx; - pthread_mutexattr_t mtx_attr; + union { + struct _rtapp_mutex mtx; + struct _rtapp_cond cond; + struct _rtapp_signal signal; + } res; int index; + resource_t type; + char *name; } rtapp_resource_t;
typedef struct _rtapp_resource_access_list_t { diff --git a/src/rt-app_utils.c b/src/rt-app_utils.c index 9719053..f83aadb 100644 --- a/src/rt-app_utils.c +++ b/src/rt-app_utils.c @@ -202,6 +202,43 @@ policy_to_string(policy_t policy, char *policy_name) return 0; }
+int +string_to_resource(const char *name, resource_t *resource) +{ + if (strcmp(name, "mutex") == 0) + *resource = rtapp_mutex; + else if (strcmp(name, "signal") == 0) + *resource = rtapp_signal; + else if (strcmp(name, "wait") == 0) + *resource = rtapp_wait; + else if (strcmp(name, "broadcast") == 0) + *resource = rtapp_broadcast; + else + return 1; + return 0; +} + +int +resource_to_string(resource_t resource, char *resource_name) +{ + switch (resource) { + case rtapp_mutex: + strcpy(resource_name, "mutex"); + break; + case rtapp_wait: + strcpy(resource_name, "wait"); + break; + case rtapp_signal: + strcpy(resource_name, "signal"); + break; + case rtapp_broadcast: + strcpy(resource_name, "broadcast"); + break; + default: + return 1; + } + return 0; +}
void ftrace_write(int mark_fd, const char *fmt, ...) { diff --git a/src/rt-app_utils.h b/src/rt-app_utils.h index c7444dc..10805ea 100644 --- a/src/rt-app_utils.h +++ b/src/rt-app_utils.h @@ -126,6 +126,12 @@ string_to_policy(const char *policy_name, policy_t *policy); int policy_to_string(policy_t policy, char *policy_name);
+int +string_to_resource(const char *name, resource_t *resource); + +int +resource_to_string(resource_t resource, char *name); + void ftrace_write(int mark_fd, const char *fmt, ...);
From: Vincent Guittot vincent.guittot@linaro.org
update the example file to reflect new wait, signal and broadcast capabilities
Signed-off-by: Vincent Guittot vincent.guittot@linaro.org --- doc/taskset.json | 88 +++++++++++++++++++++++++++----------------------------- 1 file changed, 43 insertions(+), 45 deletions(-)
diff --git a/doc/taskset.json b/doc/taskset.json index 0ce49d0..ded45b8 100644 --- a/doc/taskset.json +++ b/doc/taskset.json @@ -1,61 +1,59 @@ { - "resources" : 4, + /*"resources" : 4,*/ + "resources" : { + "m0" : { "type" : "mutex" }, + "sync_mutex" : { "type" : "mutex" }, + "wait" : { "type" : "wait" }, + "trig" : { "type" : "signal", "target" : "wait" }, + "m1" : { "type" : "mutex" }, + "wake" : { "type" : "wait" }, + "broad" : { "type" : "broadcast", "target" : "wake" }, + }, "tasks" : { "thread0" : { + "exec" : 5000, + "period" : 5000, + "deadline" : 5000, + "lock_order" : ["wait", "m0", "broad"], + "resources" : { + "m0" : { "duration" : 1000 }, + "wait" : { "duration" : 0, "access": ["sync_mutex"] }, + "broad" : { "duration" : 0, "access": ["m1"] } + } + }, + "thread1" : { "exec" : 1000, "period" : 10000, "deadline" : 8000, - "cpus" : [0,1], - "policy" : "SCHED_FIFO", - "lock_order" : [0], + "lock_order" : ["m0", "trig"], "resources" : { - "0" : { "duration" : 1000 } + "m0" : { "duration" : 500 }, + "trig" : { "duration" : 0, "access": ["sync_mutex"] }, } }, - "thread1" : { - "exec" : 50000, - "period" : 100000, - "cpus" : [1], - "policy" : "SCHED_FIFO", - "priority": 20, - /* - * Resources are acquired in "lock_order" order; - * the dependecy chain for nested locks is built through "access"; - * the innermost lock is held for "duration" msec. - * - * In the case below: - * - * L(2) - * | - * -> L(1) L(1) - * | | - * -> L(3) -> L(3) - * | | - * -> L(0) L(3) -> L(2) - * | | | - * busy_wait(1000) --- busy_wait(500) --- busy_wait(200) - * | | | - * U(0) U(3) U(2) - * | | - * U(3)<- U(3)<- - * | | - * U(1)<- U(1)<- - * | - * U(2)<- - */ - "lock_order" : [ 0, 3, 2 ], - "resources": { - "0" : { "duration" : 1000, "access": [2] }, - "1" : { "duration" : 100, "access": [3] }, - "2" : { "duration" : 200, "access": [1] }, - "3" : { "duration" : 500} + "thread2" : { + "exec" : 1000, + "period" : 1000, + "deadline" : 1000, + "lock_order" : ["wake"], + "resources" : { + "wake" : { "duration" : 0, "access": ["m1"] } + } + }, + "thread3" : { + "exec" : 1000, + "period" : 1000, + "deadline" : 1000, + "lock_order" : ["wake"], + "resources" : { + "wake" : { "duration" : 0, "access": ["m1"] } } - } + }, }, "global" : { - "spacing" : 1000, "default_policy" : "SCHED_OTHER", - "duration" : 20, + "duration" : 5, + "ftrace" : true, "gnuplot" : true, "logdir" : "/tmp/", "log_basename" : "rt-app",
From: Sanjay Singh Rawat sanjay.rawat@linaro.org
Start thread after a certain amount of time,. Add delay option in the json file in microseconds
Signed-off-by: Sanjay Singh Rawat sanjay.rawat@linaro.org Signed-off-by: Vincent Guittot vincent.guittot@linaro.org --- src/rt-app.c | 4 +--- src/rt-app_parse_config.c | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/rt-app.c b/src/rt-app.c index f69977a..107872c 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -519,14 +519,12 @@ int main(int argc, char* argv[]) /* start threads */ for (i = 0; i < nthreads; i++) { tdata = &opts.threads_data[i]; - if (opts.spacing > 0 ) { + if (!tdata->wait_before_start && (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; diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index 23e1edd..b45a5be 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -510,6 +510,9 @@ parse_thread_data(char *name, struct json_object *obj, int idx, data->sched_prio = get_int_value_from(obj, "priority", TRUE, DEFAULT_THREAD_PRIORITY);
+ /* delay */ + data->wait_before_start = get_int_value_from(obj, "delay", TRUE, 0); + /* cpu set */ cpuset_obj = get_in_object(obj, "cpus", TRUE); if (cpuset_obj) {
From: Vincent Guittot vincent.guittot@linaro.org
the thread will run a number of loop before exiting
Signed-off-by: Sanjay Singh Rawat sanjay.rawat@linaro.org --- src/rt-app.c | 2 +- src/rt-app_parse_config.c | 3 +++ src/rt-app_types.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/rt-app.c b/src/rt-app.c index 107872c..f714d58 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -364,7 +364,7 @@ void *thread_body(void *arg) t_next = t_now; data->deadline = timespec_add(&t_now, &data->deadline);
- while (continue_running) { + while (continue_running && (i != data->loop)) { struct timespec t_start, t_end, t_diff, t_slack;
if (opts.ftrace) diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index b45a5be..003e99b 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -462,6 +462,9 @@ parse_thread_data(char *name, struct json_object *obj, int idx, data->cpuset = NULL; data->cpuset_str = NULL;
+ /* loop */ + data->loop = get_int_value_from(obj, "loop", TRUE, -1); + /* period */ period = get_int_value_from(obj, "period", FALSE, 0); if (period <= 0) { diff --git a/src/rt-app_types.h b/src/rt-app_types.h index cace363..3ce58ee 100644 --- a/src/rt-app_types.h +++ b/src/rt-app_types.h @@ -113,6 +113,7 @@ typedef struct _thread_data_t { struct timespec min_et, max_et; struct timespec period, deadline; struct timespec main_app_start; + int loop;
FILE *log_handler; policy_t sched_policy;
From: Vincent Guittot vincent.guittot@linaro.org
Use calibration variable to calculate loop count for load simulation.
Signed-off-by: Christian Muller christian.muller@linaro.org --- src/rt-app.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++------ src/rt-app_utils.c | 17 +++++++++++ src/rt-app_utils.h | 3 ++ 3 files changed, 95 insertions(+), 9 deletions(-)
diff --git a/src/rt-app.c b/src/rt-app.c index f714d58..bf893d3 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -26,6 +26,7 @@ static int errno; static volatile int continue_running; static pthread_t *threads; static int nthreads; +static int p_load; rtapp_options_t opts;
static ftrace_data_t ft_data = { @@ -34,6 +35,74 @@ static ftrace_data_t ft_data = { .marker_fd = -1, };
+/* + * Function: to do some useless operation. + * TODO: improve the waste loop with more heavy functions + */ +void waste_cpu_cycles(int load_loops) +{ + double param, result; + double n, i; + + param = 0.95; + n = 4; + for (i = 0 ; i < load_loops ; i++) { + result = ldexp(param , (ldexp(param , ldexp(param , n)))); + result = ldexp(param , (ldexp(param , ldexp(param , n)))); + result = ldexp(param , (ldexp(param , ldexp(param , n)))); + result = ldexp(param , (ldexp(param , ldexp(param , n)))); + } + return; +} + +/* +* calibrate_cpu_cycles() +* collects the time that waste_cycles runs. +*/ +int calibrate_cpu_cycles(int clock) +{ + struct timespec start, stop; + int max_load_loop = 10000; + unsigned int diff; + int nsec_per_loop, avg_per_loop = 0; + int ret, cal_trial = 1000; + + while (cal_trial) { + cal_trial--; + + clock_gettime(clock, &start); + waste_cpu_cycles(max_load_loop); + clock_gettime(clock, &stop); + + diff = (int)timespec_sub_to_ns(&stop, &start); + nsec_per_loop = diff / max_load_loop; + avg_per_loop = (avg_per_loop + nsec_per_loop) >> 1; + + /* collect a critical mass of samples.*/ + if ((abs(nsec_per_loop - avg_per_loop) * 50) < avg_per_loop) + return avg_per_loop; + + /* + * use several loop duration in order to be sure to not + * fall into a specific platform loop duration + *(like the cpufreq period) + */ + /*randomize the number of loops and recheck 1000 times*/ + max_load_loop += 33333; + max_load_loop %= 1000000; + } + return 0; +} + +static inline loadwait(struct timespec *exec_time) +{ + unsigned long exec, load_count; + + exec = timespec_to_usec(exec_time); + load_count = (exec * 1000)/p_load; + waste_cpu_cycles(load_count); +} + static inline busywait(struct timespec *to) { struct timespec t_step; @@ -77,15 +146,13 @@ void run(int ind, struct timespec *min, struct timespec *max, rtapp_tasks_resource_list_t *blockages, int nblockages) { int i; - struct timespec t_start, now, t_exec, t_totexec = *max; + struct timespec t_exec; rtapp_resource_access_list_t *lock, *last;
- /* Get the start time */ - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t_start); + t_exec = *min;
for (i = 0; i < nblockages; i++) { - /* Lock resources */ lock = blockages[i].acl; while (lock != NULL) { @@ -100,14 +167,13 @@ void run(int ind, struct timespec *min, struct timespec *max, }
/* 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)); if (opts.ftrace) log_ftrace(ft_data.marker_fd, "[%d] busywait for %d", ind, timespec_to_usec(&blockages[i].usage)); - busywait(&t_exec); + loadwait(&blockages[i].usage); + t_exec = timespec_sub(&t_exec, &blockages[i].usage);
/* Unlock resources */ lock = last; @@ -123,13 +189,12 @@ void run(int ind, struct timespec *min, struct timespec *max, }
/* Compute finish time for CPUTIME_ID clock */ - t_exec = timespec_add(&t_start, &t_totexec); 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)); - busywait(&t_exec); + loadwait(&t_exec); }
static void @@ -513,6 +578,7 @@ int main(int argc, char* argv[])
continue_running = 1;
+ p_load = calibrate_cpu_cycles(CLOCK_THREAD_CPUTIME_ID); /* Take the beginning time for everything */ clock_gettime(CLOCK_MONOTONIC, &t_start);
diff --git a/src/rt-app_utils.c b/src/rt-app_utils.c index f83aadb..72bca7a 100644 --- a/src/rt-app_utils.c +++ b/src/rt-app_utils.c @@ -116,6 +116,23 @@ timespec_lower(struct timespec *what, struct timespec *than) return 0; }
+int64_t +timespec_sub_to_ns(struct timespec *t1, struct timespec *t2) +{ + int64_t diff; + + if (t1->tv_nsec < t2->tv_nsec) { + diff = 1E9 * (int64_t)((int) t1->tv_sec - + (int) t2->tv_sec - 1); + diff += ((int) t1->tv_nsec + 1E9 - (int) t2->tv_nsec); + } else { + diff = 1E9 * (int64_t)((int) t1->tv_sec - (int) t2->tv_sec); + diff += ((int) t1->tv_nsec - (int) t2->tv_nsec); + } + return diff; +} + + void log_timing(FILE *handler, timing_point_t *t) { diff --git a/src/rt-app_utils.h b/src/rt-app_utils.h index 10805ea..c11bb38 100644 --- a/src/rt-app_utils.h +++ b/src/rt-app_utils.h @@ -109,6 +109,9 @@ timespec_sub(struct timespec *t1, struct timespec *t2); int timespec_lower(struct timespec *what, struct timespec *than);
+int64_t +timespec_sub_to_ns(struct timespec *t1, struct timespec *t2); + void log_timing(FILE *handler, timing_point_t *t);
From: Vincent Guittot vincent.guittot@linaro.org
update example file with new loop capabilities
Signed-off-by: Vincent Guittot vincent.guittot@linaro.org --- doc/taskset.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/doc/taskset.json b/doc/taskset.json index ded45b8..62acfeb 100644 --- a/doc/taskset.json +++ b/doc/taskset.json @@ -8,15 +8,16 @@ "m1" : { "type" : "mutex" }, "wake" : { "type" : "wait" }, "broad" : { "type" : "broadcast", "target" : "wake" }, + "m2" : { "type" : "mutex" }, }, "tasks" : { "thread0" : { "exec" : 5000, "period" : 5000, "deadline" : 5000, - "lock_order" : ["wait", "m0", "broad"], + "lock_order" : ["wait", "m0", "broad", "m0", "broad"], "resources" : { - "m0" : { "duration" : 1000 }, + "m0" : { "duration" : 500 }, "wait" : { "duration" : 0, "access": ["sync_mutex"] }, "broad" : { "duration" : 0, "access": ["m1"] } } @@ -32,12 +33,14 @@ } }, "thread2" : { + "loop" : 100, "exec" : 1000, "period" : 1000, "deadline" : 1000, - "lock_order" : ["wake"], + "lock_order" : [ "m2", "wake", "m2", "wake"], "resources" : { - "wake" : { "duration" : 0, "access": ["m1"] } + "wake" : { "duration" : 0, "access": ["m1"] }, + "m2" : { "duration" : 200 } } }, "thread3" : {
From: Vincent Guittot vincent.guittot@linaro.org
add new sleep and run type of resources
Signed-off-by: Vincent Guittot vincent.guittot@linaro.org --- src/rt-app.c | 47 +++++++++++++++++++++++++++-------------------- src/rt-app_parse_config.c | 7 ++++--- src/rt-app_types.h | 2 ++ src/rt-app_utils.c | 10 ++++++++++ 4 files changed, 43 insertions(+), 23 deletions(-)
diff --git a/src/rt-app.c b/src/rt-app.c index bf893d3..90afe7f 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -113,11 +113,15 @@ static inline busywait(struct timespec *to) } }
-void lock_resource(rtapp_resource_access_list_t *lock) +int get_resource(rtapp_resource_access_list_t *lock, struct timespec *usage) { + int busywait = 1; rtapp_resource_access_list_t *prev;
switch(lock->res->type) { + case rtapp_mutex: + pthread_mutex_lock(&(lock->res->res.mtx.obj)); + break; case rtapp_wait: prev = lock->prev; pthread_cond_wait(&(lock->res->res.cond.obj), &(prev->res->res.mtx.obj)); @@ -128,24 +132,25 @@ void lock_resource(rtapp_resource_access_list_t *lock) case rtapp_broadcast: pthread_cond_broadcast(lock->res->res.signal.target); break; - default: - pthread_mutex_lock(&(lock->res->res.mtx.obj)); + case rtapp_sleep: + nanosleep(usage, NULL); + busywait = 0; + break; } + + return busywait; }
-void unlock_resource(rtapp_resource_access_list_t *lock) +void put_resource(rtapp_resource_access_list_t *lock) { - switch(lock->res->type) { - case rtapp_mutex: + if (lock->res->type == rtapp_mutex) pthread_mutex_unlock(&(lock->res->res.mtx.obj)); - break; - } }
void run(int ind, struct timespec *min, struct timespec *max, rtapp_tasks_resource_list_t *blockages, int nblockages) { - int i; + int i, busywait = 1; struct timespec t_exec; rtapp_resource_access_list_t *lock, *last;
@@ -153,7 +158,7 @@ void run(int ind, struct timespec *min, struct timespec *max,
for (i = 0; i < nblockages; i++) { - /* Lock resources */ + /* Lock resources sequence including the busy wait */ lock = blockages[i].acl; while (lock != NULL) { log_debug("[%d] locking %d", ind, lock->res->index); @@ -161,19 +166,21 @@ void run(int ind, struct timespec *min, struct timespec *max, log_ftrace(ft_data.marker_fd, "[%d] locking %d", ind, lock->res->index); - lock_resource(lock); + busywait = get_resource(lock, &blockages[i].usage); last = lock; lock = lock->next; }
- /* 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 (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); + }
/* Unlock resources */ lock = last; @@ -183,7 +190,7 @@ void run(int ind, struct timespec *min, struct timespec *max, log_ftrace(ft_data.marker_fd, "[%d] unlocking %d", ind, lock->res->index); - unlock_resource(lock); + put_resource(lock); lock = lock->prev; } } diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index 003e99b..30a331c 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -205,6 +205,7 @@ parse_resource_data(char *name, struct json_object *obj, int idx, { char *type, *target; char def_type[RTAPP_RESOURCE_DESCR_LENGTH]; + int duration;
log_info(PFX "Parsing resources %s [%d]", name, idx);
@@ -223,6 +224,9 @@ parse_resource_data(char *name, struct json_object *obj, int idx, }
switch (data->type) { + case rtapp_mutex: + init_mutex_resource(data, opts); + break; case rtapp_wait: init_cond_resource(data, opts); break; @@ -231,9 +235,6 @@ parse_resource_data(char *name, struct json_object *obj, int idx, target = get_string_value_from(obj, "target", FALSE, NULL); init_signal_resource(data, opts, target); break; - default: - init_mutex_resource(data, opts); - } }
diff --git a/src/rt-app_types.h b/src/rt-app_types.h index 3ce58ee..dbec836 100644 --- a/src/rt-app_types.h +++ b/src/rt-app_types.h @@ -63,6 +63,8 @@ typedef enum resource_t rtapp_wait, rtapp_signal, rtapp_broadcast, + rtapp_sleep, + rtapp_run } resource_t;
struct _rtapp_mutex { diff --git a/src/rt-app_utils.c b/src/rt-app_utils.c index 72bca7a..c2dc60c 100644 --- a/src/rt-app_utils.c +++ b/src/rt-app_utils.c @@ -230,6 +230,10 @@ string_to_resource(const char *name, resource_t *resource) *resource = rtapp_wait; else if (strcmp(name, "broadcast") == 0) *resource = rtapp_broadcast; + else if (strcmp(name, "sleep") == 0) + *resource = rtapp_sleep; + else if (strcmp(name, "run") == 0) + *resource = rtapp_run; else return 1; return 0; @@ -251,6 +255,12 @@ resource_to_string(resource_t resource, char *resource_name) case rtapp_broadcast: strcpy(resource_name, "broadcast"); break; + case rtapp_sleep: + strcpy(resource_name, "sleep"); + break; + case rtapp_run: + strcpy(resource_name, "run"); + break; default: return 1; }
From: Vincent Guittot vincent.guittot@linaro.org
update taskset.json example file with new run and sleep type of resources
Signed-off-by: Vincent Guittot vincent.guittot@linaro.org --- doc/taskset.json | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-)
diff --git a/doc/taskset.json b/doc/taskset.json index 62acfeb..a87d50a 100644 --- a/doc/taskset.json +++ b/doc/taskset.json @@ -9,27 +9,33 @@ "wake" : { "type" : "wait" }, "broad" : { "type" : "broadcast", "target" : "wake" }, "m2" : { "type" : "mutex" }, + "s1" : { "type" : "sleep" }, + "s2" : { "type" : "sleep" }, + "r1" : { "type" : "run" }, + "r2" : { "type" : "run" }, }, "tasks" : { "thread0" : { - "exec" : 5000, - "period" : 5000, - "deadline" : 5000, - "lock_order" : ["wait", "m0", "broad", "m0", "broad"], + "exec" : 1000, + "period" : 20000, + "deadline" : 8000, + "lock_order" : ["r1", "m0", "trig"], "resources" : { + "r1" : { "duration" : 200 }, "m0" : { "duration" : 500 }, - "wait" : { "duration" : 0, "access": ["sync_mutex"] }, - "broad" : { "duration" : 0, "access": ["m1"] } + "trig" : { "duration" : 0, "access": ["sync_mutex"] }, } }, "thread1" : { - "exec" : 1000, - "period" : 10000, - "deadline" : 8000, - "lock_order" : ["m0", "trig"], + "exec" : 5000, + "period" : 5000, + "deadline" : 5000, + "lock_order" : ["wait", "m0", "broad", "r1", "broad"], "resources" : { + "wait" : { "duration" : 0, "access": ["sync_mutex"] }, "m0" : { "duration" : 500 }, - "trig" : { "duration" : 0, "access": ["sync_mutex"] }, + "broad" : { "duration" : 0, "access": ["m1"] }, + "r1" : { "duration" : 1000 }, } }, "thread2" : { @@ -40,16 +46,19 @@ "lock_order" : [ "m2", "wake", "m2", "wake"], "resources" : { "wake" : { "duration" : 0, "access": ["m1"] }, - "m2" : { "duration" : 200 } + "m2" : { "duration" : 200 }, } }, "thread3" : { "exec" : 1000, "period" : 1000, "deadline" : 1000, - "lock_order" : ["wake"], + "lock_order" : ["wake", "r1", "s1", "r2" ], "resources" : { - "wake" : { "duration" : 0, "access": ["m1"] } + "wake" : { "duration" : 0, "access": ["m1"] }, + "r1" : { "duration" : 200 }, + "s1" : { "duration" : 2000 }, + "r2" : { "duration" : 200 }, } }, },
From: Vincent Guittot vincent.guittot@linaro.org
when we have sync dependency between threads, we don't need to sleep when waiting for the next period. We will wait on the 1st resource that blocked
Signed-off-by: Vincent Guittot vincent.guittot@linaro.org --- src/rt-app.c | 2 +- src/rt-app_parse_config.c | 3 +++ src/rt-app_types.h | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/rt-app.c b/src/rt-app.c index 90afe7f..5384149 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -503,7 +503,7 @@ void *thread_body(void *arg) }
clock_gettime(CLOCK_MONOTONIC, &t_now); - if (timespec_lower(&t_now, &t_next)) + if (data->sleep && timespec_lower(&t_now, &t_next)) clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t_next, NULL);
i++; diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index 30a331c..97302a7 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -517,6 +517,9 @@ parse_thread_data(char *name, struct json_object *obj, int idx, /* delay */ data->wait_before_start = get_int_value_from(obj, "delay", TRUE, 0);
+ /* sleep */ + data->sleep = get_bool_value_from(obj, "sleep", TRUE, 1); + /* cpu set */ cpuset_obj = get_in_object(obj, "cpus", TRUE); if (cpuset_obj) { diff --git a/src/rt-app_types.h b/src/rt-app_types.h index dbec836..94a6aad 100644 --- a/src/rt-app_types.h +++ b/src/rt-app_types.h @@ -115,7 +115,7 @@ typedef struct _thread_data_t { struct timespec min_et, max_et; struct timespec period, deadline; struct timespec main_app_start; - int loop; + int loop, sleep;
FILE *log_handler; policy_t sched_policy;
From: Vincent Guittot vincent.guittot@linaro.org
with new resources and way to sync, we have to change how a run period is measured.
Signed-off-by: Vincent Guittot vincent.guittot@linaro.org --- src/rt-app.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/rt-app.c b/src/rt-app.c index 5384149..c799403 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -148,7 +148,7 @@ void put_resource(rtapp_resource_access_list_t *lock) }
void run(int ind, struct timespec *min, struct timespec *max, - rtapp_tasks_resource_list_t *blockages, int nblockages) + rtapp_tasks_resource_list_t *blockages, int nblockages, struct timespec *t_start) { int i, busywait = 1; struct timespec t_exec; @@ -171,6 +171,9 @@ void run(int ind, struct timespec *min, struct timespec *max, lock = lock->next; }
+ if (!i && t_start) + clock_gettime(CLOCK_MONOTONIC, t_start); + if (busywait) { /* Busy wait */ log_debug("[%d] busywait for %lu", ind, timespec_to_usec(&blockages[i].usage)); @@ -444,7 +447,7 @@ void *thread_body(void *arg)
clock_gettime(CLOCK_MONOTONIC, &t_start); run(data->ind, &data->min_et, &data->max_et, data->blockages, - data->nblockages); + data->nblockages, data->sleep ? NULL: &t_start); clock_gettime(CLOCK_MONOTONIC, &t_end);
t_diff = timespec_sub(&t_end, &t_start);
From: Vincent Guittot vincent.guittot@linaro.org
update the example file to show all the capabilities
Signed-off-by: Vincent Guittot vincent.guittot@linaro.org --- doc/taskset.json | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/doc/taskset.json b/doc/taskset.json index a87d50a..b051b26 100644 --- a/doc/taskset.json +++ b/doc/taskset.json @@ -19,6 +19,7 @@ "exec" : 1000, "period" : 20000, "deadline" : 8000, + "cpus" : [0], "lock_order" : ["r1", "m0", "trig"], "resources" : { "r1" : { "duration" : 200 }, @@ -28,22 +29,22 @@ }, "thread1" : { "exec" : 5000, - "period" : 5000, - "deadline" : 5000, + "period" : 20000, + "sleep" : false, "lock_order" : ["wait", "m0", "broad", "r1", "broad"], "resources" : { "wait" : { "duration" : 0, "access": ["sync_mutex"] }, - "m0" : { "duration" : 500 }, - "broad" : { "duration" : 0, "access": ["m1"] }, + "m0" : { "duration" : 1000 }, + "broad" : { "duration" : 0}, "r1" : { "duration" : 1000 }, } }, "thread2" : { "loop" : 100, "exec" : 1000, - "period" : 1000, - "deadline" : 1000, - "lock_order" : [ "m2", "wake", "m2", "wake"], + "period" : 20000, + "sleep" : false, + "lock_order" : ["wake", "m2", "wake", "m2"], "resources" : { "wake" : { "duration" : 0, "access": ["m1"] }, "m2" : { "duration" : 200 }, @@ -51,14 +52,17 @@ }, "thread3" : { "exec" : 1000, - "period" : 1000, - "deadline" : 1000, - "lock_order" : ["wake", "r1", "s1", "r2" ], + "period" : 20000, + "deadline" : 15000, + "delay" : 15000, + "sleep" : true, + "lock_order" : ["r1", "s1", "r1", "s2", "r2" ], "resources" : { "wake" : { "duration" : 0, "access": ["m1"] }, "r1" : { "duration" : 200 }, "s1" : { "duration" : 2000 }, "r2" : { "duration" : 200 }, + "s2" : { "duration" : 1000 }, } }, },
Hi Pi-Cheng,
On 15/07/15 04:39, Pi-Cheng Chen wrote:
This series adds several new features to rt-app, e.g. signal, wait, broadcast, run, sleep ...etc. and updates the example taskset.json file to reflect those new features.
First of all, thanks a lot again for the hard work of sending these series out. Really appreciated :).
Regarding this series. I started reviewing it, but I noticed that it seems composed of "intermediate" changes that ended up to simpler/ cleaner features in the end (on Linaro's rt-app repo). I understand this to be a foundational series, but, since we have the opportunity to write a clean git history here, don't you think it would be better to squash some patches from the full history as to get something like:
- json grammar clean-up (e.g., remove lock order and resource defs) - introduce self contained features in their final shape (e.g., run, sleep, timer, sync, etc.) - introduce examples alongside features - introduce phases - other things/fixes
I understand it is some work to do, but what are your feelings about this? I really think it is important to come up with a clean set of changes.
Anyway, I already merged patch 04/11 (loop feature). Also, I think patch 05/11 can go in as is, but it would be nice to have "calibration: parse for CPU or forces ns per loop value" together with it (and any other calibration related patches as well).
Best,
- Juri
These patches are also found: ssh://git@git.linaro.org/people/picheng.chen/rt-app.git features_series1
Sanjay Singh Rawat (1): add delay param in thread parameters
Vincent Guittot (10): Add new wait, signal, and broadcast resources update the .json test file to reflect new capabilities add loop feature rt-app: make load frequency independent. update example file with new loop capabilities add sleep and run type of resources update taskset.json example with run and sleep capabilities make possible to remove the sleep step modify stat to reflect new behavior update example file with more capabilities
doc/taskset.json | 104 ++++++++++++---------- src/rt-app.c | 155 +++++++++++++++++++++++++++------ src/rt-app_parse_config.c | 214 +++++++++++++++++++++++++++++++++++++--------- src/rt-app_types.h | 35 +++++++- src/rt-app_utils.c | 64 ++++++++++++++ src/rt-app_utils.h | 9 ++ 6 files changed, 467 insertions(+), 114 deletions(-)
Hi Juri,
On Tue, Jul 28, 2015 at 04:05:54PM +0100, Juri Lelli wrote:
Hi Pi-Cheng,
On 15/07/15 04:39, Pi-Cheng Chen wrote:
This series adds several new features to rt-app, e.g. signal, wait, broadcast, run, sleep ...etc. and updates the example taskset.json file to reflect those new features.
First of all, thanks a lot again for the hard work of sending these series out. Really appreciated :).
Regarding this series. I started reviewing it, but I noticed that it seems composed of "intermediate" changes that ended up to simpler/ cleaner features in the end (on Linaro's rt-app repo). I understand this to be a foundational series, but, since we have the opportunity to write a clean git history here, don't you think it would be better to squash some patches from the full history as to get something like:
- json grammar clean-up (e.g., remove lock order and resource defs)
- introduce self contained features in their final shape (e.g., run, sleep, timer, sync, etc.)
- introduce examples alongside features
- introduce phases
- other things/fixes
Yes. I agree with you. This will make things cleaner. But for the 2nd point: "introduce self contained features in their final shape", I am not sure. Would it lead to the loss of some development history?
@Vincent: How do you think about it?
I understand it is some work to do, but what are your feelings about this? I really think it is important to come up with a clean set of changes.
Anyway, I already merged patch 04/11 (loop feature). Also, I think patch 05/11 can go in as is, but it would be nice to have "calibration: parse for CPU or forces ns per loop value" together with it (and any other calibration related patches as well).
I will do it.
Thanks for reviewing.
Best Regards, Pi-Cheng
Best,
- Juri
These patches are also found: ssh://git@git.linaro.org/people/picheng.chen/rt-app.git features_series1
Sanjay Singh Rawat (1): add delay param in thread parameters
Vincent Guittot (10): Add new wait, signal, and broadcast resources update the .json test file to reflect new capabilities add loop feature rt-app: make load frequency independent. update example file with new loop capabilities add sleep and run type of resources update taskset.json example with run and sleep capabilities make possible to remove the sleep step modify stat to reflect new behavior update example file with more capabilities
doc/taskset.json | 104 ++++++++++++---------- src/rt-app.c | 155 +++++++++++++++++++++++++++------ src/rt-app_parse_config.c | 214 +++++++++++++++++++++++++++++++++++++--------- src/rt-app_types.h | 35 +++++++- src/rt-app_utils.c | 64 ++++++++++++++ src/rt-app_utils.h | 9 ++ 6 files changed, 467 insertions(+), 114 deletions(-)
On 31 July 2015 at 05:42, Pi-Cheng Chen pi-cheng.chen@linaro.org wrote:
Hi Juri,
On Tue, Jul 28, 2015 at 04:05:54PM +0100, Juri Lelli wrote:
Hi Pi-Cheng,
On 15/07/15 04:39, Pi-Cheng Chen wrote:
This series adds several new features to rt-app, e.g. signal, wait, broadcast, run, sleep ...etc. and updates the example taskset.json file to reflect those new features.
First of all, thanks a lot again for the hard work of sending these series out. Really appreciated :).
Regarding this series. I started reviewing it, but I noticed that it seems composed of "intermediate" changes that ended up to simpler/ cleaner features in the end (on Linaro's rt-app repo). I understand this to be a foundational series, but, since we have the opportunity to write a clean git history here, don't you think it would be better to squash some patches from the full history as to get something like:
- json grammar clean-up (e.g., remove lock order and resource defs)
- introduce self contained features in their final shape (e.g., run, sleep, timer, sync, etc.)
- introduce examples alongside features
- introduce phases
- other things/fixes
Yes. I agree with you. This will make things cleaner. But for the 2nd point: "introduce self contained features in their final shape", I am not sure. Would it lead to the loss of some development history?
@Vincent: How do you think about it?
I have no objection to reorder patches in order to have patches linked to same features together like the example of the loop and the calibration. We can also probably squash some patches that fixes bugs into the original patch that creates the feature. Nevertheless, the order of the patches have tried to keep rt-app usable along the tree and IMHO it's important to maintain that
Regards, Vincent
I understand it is some work to do, but what are your feelings about this? I really think it is important to come up with a clean set of changes.
Anyway, I already merged patch 04/11 (loop feature). Also, I think patch 05/11 can go in as is, but it would be nice to have "calibration: parse for CPU or forces ns per loop value" together with it (and any other calibration related patches as well).
I will do it.
Thanks for reviewing.
Best Regards, Pi-Cheng
Best,
- Juri
These patches are also found: ssh://git@git.linaro.org/people/picheng.chen/rt-app.git features_series1
Sanjay Singh Rawat (1): add delay param in thread parameters
Vincent Guittot (10): Add new wait, signal, and broadcast resources update the .json test file to reflect new capabilities add loop feature rt-app: make load frequency independent. update example file with new loop capabilities add sleep and run type of resources update taskset.json example with run and sleep capabilities make possible to remove the sleep step modify stat to reflect new behavior update example file with more capabilities
doc/taskset.json | 104 ++++++++++++---------- src/rt-app.c | 155 +++++++++++++++++++++++++++------ src/rt-app_parse_config.c | 214 +++++++++++++++++++++++++++++++++++++--------- src/rt-app_types.h | 35 +++++++- src/rt-app_utils.c | 64 ++++++++++++++ src/rt-app_utils.h | 9 ++ 6 files changed, 467 insertions(+), 114 deletions(-)