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, ...);