From: "pi-cheng.chen" pi-cheng.chen@linaro.org
Add 2 new kind of event for running a memory or a io bounded load. "mem" name for a load is memory bounded, and "iorun" name for a load is io bounded. The default file to be written to create the load is /dev/null and the device/file could be specified with "io_device" key in "global" section. The size of per-thread memory buffer to create IO/memory load could also be specified with "mem_buffer_size" in the same section.
E.g. "tasks" : { "thread0" : { "sleep" : 1000, "run" : 100, "mem" : 1000, "sleep" 10000, "iorun" : 1000 } },
"global" : { "io_device" : "/dev/ttyS0", "mem_buffer_size" : 1048576 }
Signed-off-by: pi-cheng.chen pi-cheng.chen@linaro.org --- changes from v2: - allocate / open resouces at parsing stage
changes from v1: - Allocate per-thread memory buffer - Add "mem_buffer_size" in global section to specify the size of buffer - fix possible buffer overrun when creating IO-bounded load --- src/rt-app.c | 48 +++++++++++++++++++++++++++++++++++++++ src/rt-app_parse_config.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++ src/rt-app_types.h | 16 +++++++++++++ 3 files changed, 122 insertions(+)
diff --git a/src/rt-app.c b/src/rt-app.c index 37e9892..4e78844 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -179,6 +179,42 @@ static inline loadwait(unsigned long exec) return load_count; }
+static void ioload(unsigned long count, struct _rtapp_iomem_buf *iomem, int io_fd) +{ + ssize_t ret; + + while (count != 0) { + unsigned long size; + + if (count > iomem->size) + size = iomem->size; + else + size = count; + + ret = write(io_fd, iomem->ptr, size); + if (ret == -1) { + perror("write"); + return; + } + count -= ret; + } +} + +static void memload(unsigned long count, struct _rtapp_iomem_buf *iomem) +{ + while (count > 0) { + unsigned long size; + + if (count > iomem->size) + size = iomem->size; + else + size = count; + + memset(iomem->ptr, 0, size); + count -= size; + } +} + static int run_event(event_data_t *event, int dry_run, unsigned long *perf, unsigned long *duration, rtapp_resource_t *resources) { @@ -271,6 +307,18 @@ static int run_event(event_data_t *event, int dry_run, pthread_mutex_unlock(&(ddata->res.mtx.obj)); break; } + case rtapp_mem: + { + log_debug("mem %d", event->count); + memload(event->count, &rdata->res.buf); + } + break; + case rtapp_iorun: + { + log_debug("iorun %d", event->count); + ioload(event->count, &rdata->res.buf, ddata->res.dev.fd); + } + break; }
return lock; diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index 96e5517..def3070 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define PIN2 PIN" " #define PIN3 PIN2" " #define JSON_FILE_BUF_SIZE 4096 +#define DEFAULT_MEM_BUF_SIZE (4 * 1024 * 1024)
/* redefine foreach as in <json/json_object.h> but to be ANSI * compatible */ @@ -191,6 +192,21 @@ static int init_cond_resource(rtapp_resource_t *data, const rtapp_options_t *opt &data->res.cond.attr); }
+static int init_membuf_resource(rtapp_resource_t *data, const rtapp_options_t *opts) +{ + log_info(PIN3 "Init: %s membuf", data->name); + + data->res.buf.ptr = malloc(opts->mem_buffer_size); + data->res.buf.size = opts->mem_buffer_size; +} + +static int init_iodev_resource(rtapp_resource_t *data, const rtapp_options_t *opts) +{ + log_info(PIN3 "Init: %s io device", data->name); + + data->res.dev.fd = open(opts->io_device, O_CREAT | O_WRONLY, 0644); +} + static void init_resource_data(const char *name, int type, int idx, const rtapp_options_t *opts) { @@ -211,6 +227,12 @@ init_resource_data(const char *name, int type, int idx, const rtapp_options_t *o case rtapp_wait: init_cond_resource(data, opts); break; + case rtapp_mem: + init_membuf_resource(data, opts); + break; + case rtapp_iorun: + init_iodev_resource(data, opts); + break; } }
@@ -332,6 +354,32 @@ parse_thread_event_data(char *name, struct json_object *obj, return; }
+ if (!strncmp(name, "mem", strlen("mem")) || + !strncmp(name, "iorun", strlen("iorun"))) { + if (!json_object_is_type(obj, json_type_int)) + goto unknown_event; + + /* create an unique name for per-thread buffer */ + ref = create_unique_name(unique_name, sizeof(unique_name), "mem", tag); + i = get_resource_index(ref, rtapp_mem, opts); + data->res = i; + data->count = json_object_get_int(obj); + + /* A single IO devices for all threads */ + if (strncmp(name, "iorun", strlen("iorun")) == 0) { + i = get_resource_index("io_device", rtapp_iorun, opts); + data->dep = i; + }; + + if (!strncmp(name, "mem", strlen("mem"))) + data->type = rtapp_mem; + else + data->type = rtapp_iorun; + + log_info(PIN2 "type %d count %d", data->type, data->count); + return; + } + if (!strncmp(name, "lock", strlen("lock")) || !strncmp(name, "unlock", strlen("unlock"))) {
@@ -526,6 +574,10 @@ obj_is_event(char *name) return rtapp_suspend; if (!strncmp(name, "resume", strlen("resume"))) return rtapp_resume; + if (!strncmp(name, "mem", strlen("mem"))) + return rtapp_mem; + if (!strncmp(name, "iorun", strlen("iorun"))) + return rtapp_iorun;
return 0; } @@ -710,6 +762,8 @@ parse_global(struct json_object *global, rtapp_options_t *opts) opts->logbasename = strdup("rt-app"); opts->ftrace = 0; opts->pi_enabled = 0; + opts->io_device = strdup("/dev/null"); + opts->mem_buffer_size = DEFAULT_MEM_BUF_SIZE; return; }
@@ -762,6 +816,10 @@ parse_global(struct json_object *global, rtapp_options_t *opts) TRUE, "rt-app"); opts->ftrace = get_bool_value_from(global, "ftrace", TRUE, 0); opts->pi_enabled = get_bool_value_from(global, "pi_enabled", TRUE, 0); + opts->io_device = get_string_value_from(global, "io_device", TRUE, + "/dev/null"); + opts->mem_buffer_size = get_int_value_from(global, "mem_buffer_size", + TRUE, DEFAULT_MEM_BUF_SIZE);
}
diff --git a/src/rt-app_types.h b/src/rt-app_types.h index 1075f64..aab96a7 100644 --- a/src/rt-app_types.h +++ b/src/rt-app_types.h @@ -65,6 +65,8 @@ typedef enum resource_t rtapp_timer, rtapp_suspend, rtapp_resume, + rtapp_mem, + rtapp_iorun, } resource_t;
struct _rtapp_mutex { @@ -86,6 +88,15 @@ struct _rtapp_timer { int init; };
+struct _rtapp_iomem_buf { + char *ptr; + int size; +}; + +struct _rtapp_iodev { + int fd; +}; + /* Shared resources */ typedef struct _rtapp_resource_t { union { @@ -93,6 +104,8 @@ typedef struct _rtapp_resource_t { struct _rtapp_cond cond; struct _rtapp_signal signal; struct _rtapp_timer timer; + struct _rtapp_iomem_buf buf; + struct _rtapp_iodev dev; } res; int index; resource_t type; @@ -104,6 +117,7 @@ typedef struct _event_data_t { int res; int dep; int duration; + int count; } event_data_t;
typedef struct _phase_data_t { @@ -166,6 +180,8 @@ typedef struct _rtapp_options_t {
int ftrace; int die_on_dmiss; + int mem_buffer_size; + char *io_device; } rtapp_options_t;
typedef struct _timing_point_t {
Hi Pi-Cheng,
On 14 July 2015 at 10:07, Pi-Cheng Chen pi-cheng.chen@linaro.org wrote:
From: "pi-cheng.chen" pi-cheng.chen@linaro.org
Add 2 new kind of event for running a memory or a io bounded load. "mem" name for a load is memory bounded, and "iorun" name for a load is io bounded. The default file to be written to create the load is /dev/null and the device/file could be specified with "io_device" key in "global" section. The size of per-thread memory buffer to create IO/memory load could also be specified with "mem_buffer_size" in the same section.
E.g. "tasks" : { "thread0" : { "sleep" : 1000, "run" : 100, "mem" : 1000, "sleep" 10000, "iorun" : 1000 } },
"global" : { "io_device" : "/dev/ttyS0", "mem_buffer_size" : 1048576 }
I have only 1 comment about your patch: there is no description of these 2 new events like the unit that is used (IIUC it's Bytes). Adding a description of these events is the tutorial.txt file would be a good thing and you can also put your example above in an example6.json file
Thanks, Vincent
Signed-off-by: pi-cheng.chen pi-cheng.chen@linaro.org
changes from v2:
- allocate / open resouces at parsing stage
changes from v1:
- Allocate per-thread memory buffer
- Add "mem_buffer_size" in global section to specify the size of buffer
- fix possible buffer overrun when creating IO-bounded load
src/rt-app.c | 48 +++++++++++++++++++++++++++++++++++++++ src/rt-app_parse_config.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++ src/rt-app_types.h | 16 +++++++++++++ 3 files changed, 122 insertions(+)
diff --git a/src/rt-app.c b/src/rt-app.c index 37e9892..4e78844 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -179,6 +179,42 @@ static inline loadwait(unsigned long exec) return load_count; }
+static void ioload(unsigned long count, struct _rtapp_iomem_buf *iomem, int io_fd) +{
ssize_t ret;
while (count != 0) {
unsigned long size;
if (count > iomem->size)
size = iomem->size;
else
size = count;
ret = write(io_fd, iomem->ptr, size);
if (ret == -1) {
perror("write");
return;
}
count -= ret;
}
+}
+static void memload(unsigned long count, struct _rtapp_iomem_buf *iomem) +{
while (count > 0) {
unsigned long size;
if (count > iomem->size)
size = iomem->size;
else
size = count;
memset(iomem->ptr, 0, size);
count -= size;
}
+}
static int run_event(event_data_t *event, int dry_run, unsigned long *perf, unsigned long *duration, rtapp_resource_t *resources) { @@ -271,6 +307,18 @@ static int run_event(event_data_t *event, int dry_run, pthread_mutex_unlock(&(ddata->res.mtx.obj)); break; }
case rtapp_mem:
{
log_debug("mem %d", event->count);
memload(event->count, &rdata->res.buf);
}
break;
case rtapp_iorun:
{
log_debug("iorun %d", event->count);
ioload(event->count, &rdata->res.buf, ddata->res.dev.fd);
}
break; } return lock;
diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index 96e5517..def3070 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define PIN2 PIN" " #define PIN3 PIN2" " #define JSON_FILE_BUF_SIZE 4096 +#define DEFAULT_MEM_BUF_SIZE (4 * 1024 * 1024)
/* redefine foreach as in <json/json_object.h> but to be ANSI
- compatible */
@@ -191,6 +192,21 @@ static int init_cond_resource(rtapp_resource_t *data, const rtapp_options_t *opt &data->res.cond.attr); }
+static int init_membuf_resource(rtapp_resource_t *data, const rtapp_options_t *opts) +{
log_info(PIN3 "Init: %s membuf", data->name);
data->res.buf.ptr = malloc(opts->mem_buffer_size);
data->res.buf.size = opts->mem_buffer_size;
+}
+static int init_iodev_resource(rtapp_resource_t *data, const rtapp_options_t *opts) +{
log_info(PIN3 "Init: %s io device", data->name);
data->res.dev.fd = open(opts->io_device, O_CREAT | O_WRONLY, 0644);
+}
static void init_resource_data(const char *name, int type, int idx, const rtapp_options_t *opts) { @@ -211,6 +227,12 @@ init_resource_data(const char *name, int type, int idx, const rtapp_options_t *o case rtapp_wait: init_cond_resource(data, opts); break;
case rtapp_mem:
init_membuf_resource(data, opts);
break;
case rtapp_iorun:
init_iodev_resource(data, opts);
break; }
}
@@ -332,6 +354,32 @@ parse_thread_event_data(char *name, struct json_object *obj, return; }
if (!strncmp(name, "mem", strlen("mem")) ||
!strncmp(name, "iorun", strlen("iorun"))) {
if (!json_object_is_type(obj, json_type_int))
goto unknown_event;
/* create an unique name for per-thread buffer */
ref = create_unique_name(unique_name, sizeof(unique_name), "mem", tag);
i = get_resource_index(ref, rtapp_mem, opts);
data->res = i;
data->count = json_object_get_int(obj);
/* A single IO devices for all threads */
if (strncmp(name, "iorun", strlen("iorun")) == 0) {
i = get_resource_index("io_device", rtapp_iorun, opts);
data->dep = i;
};
if (!strncmp(name, "mem", strlen("mem")))
data->type = rtapp_mem;
else
data->type = rtapp_iorun;
log_info(PIN2 "type %d count %d", data->type, data->count);
return;
}
if (!strncmp(name, "lock", strlen("lock")) || !strncmp(name, "unlock", strlen("unlock"))) {
@@ -526,6 +574,10 @@ obj_is_event(char *name) return rtapp_suspend; if (!strncmp(name, "resume", strlen("resume"))) return rtapp_resume;
if (!strncmp(name, "mem", strlen("mem")))
return rtapp_mem;
if (!strncmp(name, "iorun", strlen("iorun")))
return rtapp_iorun; return 0;
} @@ -710,6 +762,8 @@ parse_global(struct json_object *global, rtapp_options_t *opts) opts->logbasename = strdup("rt-app"); opts->ftrace = 0; opts->pi_enabled = 0;
opts->io_device = strdup("/dev/null");
opts->mem_buffer_size = DEFAULT_MEM_BUF_SIZE; return; }
@@ -762,6 +816,10 @@ parse_global(struct json_object *global, rtapp_options_t *opts) TRUE, "rt-app"); opts->ftrace = get_bool_value_from(global, "ftrace", TRUE, 0); opts->pi_enabled = get_bool_value_from(global, "pi_enabled", TRUE, 0);
opts->io_device = get_string_value_from(global, "io_device", TRUE,
"/dev/null");
opts->mem_buffer_size = get_int_value_from(global, "mem_buffer_size",
TRUE, DEFAULT_MEM_BUF_SIZE);
}
diff --git a/src/rt-app_types.h b/src/rt-app_types.h index 1075f64..aab96a7 100644 --- a/src/rt-app_types.h +++ b/src/rt-app_types.h @@ -65,6 +65,8 @@ typedef enum resource_t rtapp_timer, rtapp_suspend, rtapp_resume,
rtapp_mem,
rtapp_iorun,
} resource_t;
struct _rtapp_mutex { @@ -86,6 +88,15 @@ struct _rtapp_timer { int init; };
+struct _rtapp_iomem_buf {
char *ptr;
int size;
+};
+struct _rtapp_iodev {
int fd;
+};
/* Shared resources */ typedef struct _rtapp_resource_t { union { @@ -93,6 +104,8 @@ typedef struct _rtapp_resource_t { struct _rtapp_cond cond; struct _rtapp_signal signal; struct _rtapp_timer timer;
struct _rtapp_iomem_buf buf;
struct _rtapp_iodev dev; } res; int index; resource_t type;
@@ -104,6 +117,7 @@ typedef struct _event_data_t { int res; int dep; int duration;
int count;
} event_data_t;
typedef struct _phase_data_t { @@ -166,6 +180,8 @@ typedef struct _rtapp_options_t {
int ftrace; int die_on_dmiss;
int mem_buffer_size;
char *io_device;
} rtapp_options_t;
typedef struct _timing_point_t {
1.9.1