summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Guittot <vincent.guittot@linaro.org>2014-06-20 14:45:03 +0200
committerVincent Guittot <vincent.guittot@linaro.org>2014-06-24 15:02:20 +0200
commit2e8b89d4ea640347221a437ec87f7555f564f92b (patch)
treeb2963465650fc952d5580c0b1421ec2118d9b4bd
parent4da8d51e49ad1329247d5e47966a80f6f569d79f (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.c39
-rw-r--r--src/rt-app_parse_config.c198
-rw-r--r--src/rt-app_types.h32
-rw-r--r--src/rt-app_utils.c37
-rw-r--r--src/rt-app_utils.h4
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, ...);