diff options
author | Vincent Guittot <vincent.guittot@linaro.org> | 2014-06-20 14:45:03 +0200 |
---|---|---|
committer | Vincent Guittot <vincent.guittot@linaro.org> | 2014-06-24 15:02:20 +0200 |
commit | 2e8b89d4ea640347221a437ec87f7555f564f92b (patch) | |
tree | b2963465650fc952d5580c0b1421ec2118d9b4bd | |
parent | 4da8d51e49ad1329247d5e47966a80f6f569d79f (diff) |
Add new resourcesnew_resources
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
TODO: add detailed usage description
Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
-rw-r--r-- | src/rt-app.c | 39 | ||||
-rw-r--r-- | src/rt-app_parse_config.c | 198 | ||||
-rw-r--r-- | src/rt-app_types.h | 32 | ||||
-rw-r--r-- | src/rt-app_utils.c | 37 | ||||
-rw-r--r-- | src/rt-app_utils.h | 4 |
5 files changed, 265 insertions, 45 deletions
diff --git a/src/rt-app.c b/src/rt-app.c index 0c8f170..47e8c18 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -44,11 +44,40 @@ 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) { int i; - struct timespec t_start, now, t_exec, t_totexec = *max; + struct timespec t_start, t_now, t_exec, t_totexec = *max; rtapp_resource_access_list_t *lock, *last; /* Get the start time */ @@ -65,14 +94,14 @@ 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; } /* Busy wait */ - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now); - t_exec = timespec_add(&now, &blockages[i].usage); + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t_now); + t_exec = timespec_add(&t_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, @@ -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 952d390..009c2f1 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -163,41 +163,148 @@ get_string_value_from(struct json_object *where, 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 ignalwait", 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 +332,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 +344,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 +367,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 +383,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 +429,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 +439,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 +456,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); diff --git a/src/rt-app_types.h b/src/rt-app_types.h index 2cdc8bc..3886768 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 d749cfc..e35c7e9 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 41f2563..ceddc1c 100644 --- a/src/rt-app_utils.h +++ b/src/rt-app_utils.h @@ -127,6 +127,10 @@ int string_to_policy(const char *policy_name, policy_t *policy); 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, ...); |