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.
E.g. "tasks" : { "thread0" : { "sleep" : 1000, "run" : 100, "mem" : 1000, "sleep" 10000, "iorun" : 1000 } }, "global" : { "io_device" : "/dev/ttyS0" }
Signed-off-by: pi-cheng.chen pi-cheng.chen@linaro.org --- src/rt-app.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ src/rt-app.h | 2 ++ src/rt-app_parse_config.c | 23 +++++++++++++++ src/rt-app_types.h | 4 +++ 4 files changed, 103 insertions(+)
diff --git a/src/rt-app.c b/src/rt-app.c index 3cd601d..13f72e4 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -33,6 +33,8 @@ static volatile int continue_running; static pthread_t *threads; static int nthreads; static int p_load; +static char *buffer[2]; +static int io_fd; rtapp_options_t opts;
static ftrace_data_t ft_data = { @@ -110,6 +112,45 @@ static inline loadwait(unsigned long exec) return load_count; }
+static void ioload(unsigned long count) +{ + ssize_t ret; + char *buf = buffer[0]; + + while (count != 0) { + ret = write(io_fd, buffer, count); + if (ret == -1) { + perror("write"); + return; + } + count -= ret; + buf += ret; + } +} + +static void memload(unsigned long count) +{ + static unsigned long current = 0; + + while (count > 0) { + unsigned long size; + + if (count > MEM_BUFFER_SIZE) + size = MEM_BUFFER_SIZE; + else + size = count; + + if (size > (MEM_BUFFER_SIZE - current)) + size = MEM_BUFFER_SIZE - current; + + memcpy(buffer[0], buffer[1], size); + count -= size; + current += size; + if (current >= MEM_BUFFER_SIZE) + current -= MEM_BUFFER_SIZE; + } +} + static int run_event(event_data_t *event, int dry_run, unsigned long *perf, unsigned long *duration, rtapp_resource_t *resources) { @@ -196,6 +237,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); + } + break; + case rtapp_iorun: + { + log_debug("iorun %d", event->count); + ioload(event->count); + } + break; }
return lock; @@ -488,6 +541,22 @@ int main(int argc, char* argv[])
parse_command_line(argc, argv, &opts);
+ /* allocate memory buffers for memory-bound and IO-bound busy loops */ + buffer[0] = malloc(MEM_BUFFER_SIZE); + buffer[1] = malloc(MEM_BUFFER_SIZE); + if (!buffer[0] || !buffer[1]) { + log_error("Cannot allocate memory buffers for memory-bound and" + "IO-bound busy loops"); + exit(EXIT_FAILURE); + } + + /* open file for IO-bound busy loops */ + io_fd = open(opts.io_device, O_CREAT | O_WRONLY, 0644); + if (io_fd < 0) { + log_error("Cannot open io_device file %s", opts.io_device); + exit(EXIT_FAILURE); + } + /* allocated threads */ nthreads = opts.nthreads; threads = malloc(nthreads * sizeof(pthread_t)); @@ -713,6 +782,11 @@ int main(int argc, char* argv[]) close(ft_data.trace_fd); close(ft_data.marker_fd); } + + close(io_fd); + free(buffer[0]); + free(buffer[1]); + exit(EXIT_SUCCESS);
diff --git a/src/rt-app.h b/src/rt-app.h index d55271f..477d493 100644 --- a/src/rt-app.h +++ b/src/rt-app.h @@ -36,6 +36,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define BUDGET_OVERP 5
+#define MEM_BUFFER_SIZE (4 * 1024 * 1024) + void *thread_body(void *arg);
#endif /* _RT_APP_H_ */ diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index e062f79..f715424 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -320,6 +320,22 @@ 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; + + data->count = json_object_get_int(obj); + + 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"))) {
@@ -493,6 +509,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; } @@ -677,6 +697,7 @@ 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"); return; }
@@ -719,6 +740,8 @@ 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");
}
diff --git a/src/rt-app_types.h b/src/rt-app_types.h index cefb3a6..3a7c231 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 { @@ -103,6 +105,7 @@ typedef struct _event_data_t { int res; int dep; int duration; + int count; } event_data_t;
typedef struct _phase_data_t { @@ -165,6 +168,7 @@ typedef struct _rtapp_options_t {
int ftrace; int die_on_dmiss; + char *io_device; } rtapp_options_t;
typedef struct _timing_point_t {