Hi Vincent,
Thanks for reviewing. I haven't look into this new feature for a while. I'll restart to work on it and get back to you soon.
Best Regards, Pi-Cheng
On Fri, May 29, 2015 at 5:19 PM, Vincent Guittot vincent.guittot@linaro.org wrote:
Hi Pi-cheng,
On 16 December 2014 at 04:57, pi-cheng.chen pi-cheng.chen@linaro.org wrote:
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 }
changes v1 to v2: Allocate per-thread memory buffer. Add "mem_buffer_size" in global section to set the size of memory buffer to be allocated. And fix possible buffer overrun when creating IO-bounded load.
Signed-off-by: pi-cheng.chen pi-cheng.chen@linaro.org
src/rt-app.c | 104 +++++++++++++++++++++++++++++++++++++++++++++- src/rt-app_parse_config.c | 27 ++++++++++++ src/rt-app_types.h | 11 +++++ 3 files changed, 140 insertions(+), 2 deletions(-)
diff --git a/src/rt-app.c b/src/rt-app.c index 3cd601d..16bbe48 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -33,7 +33,9 @@ static volatile int continue_running; static pthread_t *threads; static int nthreads; static int p_load; +static int io_fd; rtapp_options_t opts; +static iomem_buf_t *iomem_buf;
You should better create a iomem_buf_t iomem_buf field into the thread struct so you don't have to allocate additionnal array beside
static ftrace_data_t ft_data = { .debugfs = "/sys/kernel/debug", @@ -110,8 +112,57 @@ static inline loadwait(unsigned long exec) return load_count; }
+static void ioload(unsigned long count, iomem_buf_t *iomem) +{
ssize_t ret;
while (count != 0) {
unsigned long size;
if (count > iomem->size)
size = iomem->size;
else
size = count;
Why can't we loop on the buffer and write more than it's size in the io ?
if (size > (iomem->size - iomem->pos))
size = iomem->size - iomem->pos;
ret = write(io_fd, iomem->buf + iomem->pos, size);
if (ret == -1) {
perror("write");
return;
}
count -= ret;
iomem->pos += ret;
if (iomem->pos >= iomem->size)
iomem->pos -= iomem->size;
}
+}
+static void memload(unsigned long count, iomem_buf_t *iomem) +{
while (count > 0) {
unsigned long size;
if (count > iomem->size)
size = iomem->size;
else
size = count;
same question as for io
if (size > (iomem->size - iomem->pos))
size = iomem->size - iomem->pos;
memset(iomem->buf + iomem->pos, 0, size);
count -= size;
iomem->pos += size;
if (iomem->pos >= iomem->size)
iomem->pos -= iomem->size;
}
+}
static int run_event(event_data_t *event, int dry_run,
unsigned long *perf, unsigned long *duration, rtapp_resource_t *resources)
unsigned long *perf, unsigned long *duration,
rtapp_resource_t *resources, int ind)
{ rtapp_resource_t *rdata = &(resources[event->res]); rtapp_resource_t *ddata = &(resources[event->dep]); @@ -196,6 +247,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, &iomem_buf[ind]);
}
break;
case rtapp_iorun:
{
log_debug("iorun %d", event->count);
ioload(event->count, &iomem_buf[ind]);
}
break; } return lock;
@@ -218,7 +281,8 @@ int run(int ind, event_data_t *events, log_ftrace(ft_data.marker_fd, "[%d] locking %d", ind, events[i].type);
lock += run_event(&events[i], !continue_running, &perf, duration, resources);
lock += run_event(&events[i], !continue_running, &perf,
duration, resources, ind); } return perf;
@@ -488,6 +552,35 @@ int main(int argc, char* argv[])
parse_command_line(argc, argv, &opts);
/*
* allocate per-thread memory buffers for memory-bound and IO-bound
* busy loops
*/
iomem_buf = malloc(sizeof(iomem_buf_t) * opts.nthreads);
if (!iomem_buf) {
log_error("Cannot allocate memory for IO/memory buffer struct");
exit(EXIT_FAILURE);
}
for (i = 0; i < opts.nthreads; i++) {
iomem_buf_t *iomem = &iomem_buf[i];
iomem->size = opts.mem_buffer_size;
iomem->buf = malloc(iomem->size);
if (!iomem->buf) {
log_error("Cannot allocate memory for memory-bounded"
"and IO-bounded busy loops");
exit(EXIT_FAILURE);
}
iomem->pos = 0;
}
/* 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 +806,13 @@ int main(int argc, char* argv[]) close(ft_data.trace_fd); close(ft_data.marker_fd); }
close(io_fd);
for (i = 0; i < nthreads; i++)
free(iomem_buf[i].buf);
free(iomem_buf);
exit(EXIT_SUCCESS);
diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index e062f79..9bdf38a 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 */
@@ -320,6 +321,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 +510,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 +698,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; }
@@ -719,6 +742,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 cefb3a6..d230d45 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,8 @@ typedef struct _rtapp_options_t {
int ftrace; int die_on_dmiss;
char *io_device;
int mem_buffer_size;
} rtapp_options_t;
typedef struct _timing_point_t { @@ -177,4 +182,10 @@ typedef struct _timing_point_t { __u64 rel_start_time; } timing_point_t;
+typedef struct {
char *buf;
int pos;
int size;
+} iomem_buf_t;
#endif // _RTAPP_TYPES_H_
1.9.1