blob: 86225bd669534cfda27ed24bc6162115c78912bd [file] [log] [blame]
Igor Opaniukab88c952017-02-14 13:22:54 +02001/*
2 * Copyright (c) 2016, Linaro Limited
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <errno.h>
29#include <fcntl.h>
30#include <inttypes.h>
31#include <limits.h>
32#include <libgen.h>
33#include <pthread.h>
34#include <string.h>
35#include <stdio.h>
36#include <stdbool.h>
37#include <stdlib.h>
38#include <sys/types.h>
39#include <sys/mman.h>
40#include <sys/stat.h>
41#include <sys/wait.h>
42#include <unistd.h>
Igor Opaniukf1f3fd02017-09-14 15:34:56 +030043#include <yaml.h>
Igor Opaniukab88c952017-02-14 13:22:54 +020044
45#include "benchmark_aux.h"
Igor Opaniukf1f3fd02017-09-14 15:34:56 +030046#include "common.h"
Igor Opaniukab88c952017-02-14 13:22:54 +020047
Igor Opaniukf1f3fd02017-09-14 15:34:56 +030048#define MAX_SCALAR 20
49static struct tee_ts_global *bench_ts_global;
Igor Opaniukab88c952017-02-14 13:22:54 +020050
51static const TEEC_UUID pta_benchmark_uuid = PTA_BENCHMARK_UUID;
Igor Opaniukab88c952017-02-14 13:22:54 +020052static TEEC_Context ctx;
53static TEEC_Session sess;
54
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +020055static sig_atomic_t is_running;
Igor Opaniukf1f3fd02017-09-14 15:34:56 +030056static yaml_emitter_t emitter;
57
Igor Opaniuk3d566ae2018-01-29 02:41:33 +020058struct consumer_param {
59 pid_t child_pid;
60 char *ts_filepath;
61};
Igor Opaniukf1f3fd02017-09-14 15:34:56 +030062void sigint_handler(int data)
63{
64 (void)data;
65
66 is_running = 0;
67}
68
Igor Opaniukab88c952017-02-14 13:22:54 +020069static void open_bench_pta(void)
70{
71 TEEC_Result res;
72 uint32_t err_origin;
73
74 res = TEEC_InitializeContext(NULL, &ctx);
75 tee_check_res(res, "TEEC_InitializeContext");
76
77 res = TEEC_OpenSession(&ctx, &sess, &pta_benchmark_uuid,
78 TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
79 tee_check_res(res, "TEEC_OpenSession");
80}
81
82static void close_bench_pta(void)
83{
84 /* release benchmark timestamp shm */
Igor Opaniukab88c952017-02-14 13:22:54 +020085 TEEC_CloseSession(&sess);
86 TEEC_FinalizeContext(&ctx);
87}
88
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +020089static void alloc_bench_buf(uint32_t cores)
Igor Opaniukab88c952017-02-14 13:22:54 +020090{
91 TEEC_Result res;
92 TEEC_Operation op = { 0 };
93 uint32_t ret_orig;
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +020094 intptr_t paddr_ts_buf = 0;
95 size_t size;
Igor Opaniukab88c952017-02-14 13:22:54 +020096
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +020097 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT,
98 TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE);
Igor Opaniukab88c952017-02-14 13:22:54 +020099
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +0200100 op.params[1].value.a = cores;
Igor Opaniukab88c952017-02-14 13:22:54 +0200101
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +0200102 res = TEEC_InvokeCommand(&sess, BENCHMARK_CMD_REGISTER_MEMREF,
Igor Opaniukab88c952017-02-14 13:22:54 +0200103 &op, &ret_orig);
104 tee_check_res(res, "TEEC_InvokeCommand");
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +0200105
106 paddr_ts_buf = op.params[0].value.a;
107 size = op.params[0].value.b;
108
ChrisG55ecba70d2018-12-06 11:52:29 +0100109 INFO("ts buffer paddr = %" PRIiPTR ", size = %zu\n", paddr_ts_buf, size);
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +0200110 if (paddr_ts_buf) {
111
112 bench_ts_global = mmap_paddr(paddr_ts_buf, size);
113 if (!bench_ts_global)
114 ERROR_EXIT("Failed to allocate timestamp buffer");
115 } else {
116 ERROR_EXIT("Failed to allocate timestamp buffer");
117 }
Igor Opaniukab88c952017-02-14 13:22:54 +0200118}
119
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +0200120static void free_bench_buf(void)
Igor Opaniukab88c952017-02-14 13:22:54 +0200121{
122 TEEC_Result res;
123 TEEC_Operation op = { 0 };
124 uint32_t ret_orig;
125
Igor Opaniuk845a7832018-06-06 14:06:10 +0300126 DBG("Freeing benchmark buffer.");
Igor Opaniukab88c952017-02-14 13:22:54 +0200127 op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE,
128 TEEC_NONE, TEEC_NONE, TEEC_NONE);
129
130 res = TEEC_InvokeCommand(&sess, BENCHMARK_CMD_UNREGISTER,
131 &op, &ret_orig);
132 tee_check_res(res, "TEEC_InvokeCommand");
133}
134
135static void usage(char *progname)
136{
137 fprintf(stderr, "Call latency benchmark tool for OP-TEE\n\n");
138 fprintf(stderr, "Usage:\n");
139 fprintf(stderr, " %s -h\n", progname);
140 fprintf(stderr, " %s host_app [host_app_args]\n", progname);
141 fprintf(stderr, "Options:\n");
142 fprintf(stderr, " -h Print this help and exit\n");
143 fprintf(stderr, " host_app Path to host app to benchmark\n");
144 fprintf(stderr, " host_app_args Original host app args\n");
145}
146
147static int timestamp_pop(struct tee_ts_cpu_buf *cpu_buf,
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +0200148 struct tee_time_st *ts)
Igor Opaniukab88c952017-02-14 13:22:54 +0200149{
150 uint64_t ts_tail;
151
152 if (!cpu_buf && !ts)
153 return RING_BADPARM;
154
155 if (cpu_buf->tail >= cpu_buf->head)
156 return RING_NODATA;
157
158 ts_tail = cpu_buf->tail++;
159 *ts = cpu_buf->stamps[ts_tail & TEE_BENCH_MAX_MASK];
160
161 return 0;
162}
163
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300164static bool init_emitter(FILE *ts_file)
165{
166 yaml_event_t event;
167
168 if (!yaml_emitter_initialize(&emitter))
169 ERROR_RETURN_FALSE("Can't initialize YAML emitter");
170
171 yaml_emitter_set_canonical(&emitter, 0);
172 yaml_emitter_set_unicode(&emitter, 1);
173 yaml_emitter_set_output_file(&emitter, ts_file);
174
175 /* Stream start */
176 if (!yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING))
177 ERROR_GOTO(emitter_delete,
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200178 "Failed to initialize YAML stream start event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300179 if (!yaml_emitter_emit(&emitter, &event))
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200180 ERROR_GOTO(emitter_delete,
181 "Failed to emit YAML stream start event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300182
183 /* Document start */
184 if (!yaml_document_start_event_initialize(&event,
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200185 NULL, NULL, NULL, YAML_IMPLICIT))
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300186 ERROR_GOTO(emitter_delete,
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200187 "Failed to initialize YAML document start event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300188 if (!yaml_emitter_emit(&emitter, &event))
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200189 ERROR_GOTO(emitter_delete,
190 "Failed to emit YAML doc start event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300191
192 /* Mapping start */
193 if (!yaml_mapping_start_event_initialize(&event,
194 NULL, NULL , YAML_IMPLICIT,
195 YAML_ANY_SEQUENCE_STYLE))
196 ERROR_GOTO(emitter_delete,
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200197 "Failed to initialize YAML mapping start event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300198 if (!yaml_emitter_emit(&emitter, &event))
199 ERROR_GOTO(emitter_delete,
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200200 "Failed to emit YAML sequence mapping event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300201 /* Key timestamps */
202 yaml_scalar_event_initialize(&event, NULL, NULL,
203 (yaml_char_t *)"timestamps", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE);
204 if (!yaml_emitter_emit(&emitter, &event))
205 ERROR_RETURN_FALSE("Failed to emit YAML scalar");
206
207 /* Sequence start */
208 if (!yaml_sequence_start_event_initialize(&event,
209 NULL, NULL , YAML_IMPLICIT,
210 YAML_ANY_SEQUENCE_STYLE))
211 ERROR_GOTO(emitter_delete,
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200212 "Failed to initialize YAML sequence start event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300213 if (!yaml_emitter_emit(&emitter, &event))
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200214 ERROR_GOTO(emitter_delete,
215 "Failed to emit YAML sequence start event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300216
217 return true;
218emitter_delete:
219 yaml_emitter_delete(&emitter);
220 return false;
221}
222
223static void deinit_emitter()
224{
225 yaml_event_t event;
226
227 /* Sequence cmd */
228 if (!yaml_sequence_end_event_initialize(&event))
229 ERROR_GOTO(emitter_delete,
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200230 "Failed to initialize YAML sequence end event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300231 if (!yaml_emitter_emit(&emitter, &event))
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200232 ERROR_GOTO(emitter_delete,
233 "Failed to emit YAML sequence end event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300234
235 /* Mapping end */
236 if (!yaml_mapping_end_event_initialize(&event))
237 ERROR_GOTO(emitter_delete,
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200238 "Failed to initialize YAML mapping end event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300239 if (!yaml_emitter_emit(&emitter, &event))
240 ERROR_GOTO(emitter_delete,
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200241 "Failed to emit YAML mapping end event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300242
243 /* Document end */
244 if (!yaml_document_end_event_initialize(&event, 0))
245 ERROR_GOTO(emitter_delete,
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200246 "Failed to initialize YAML document end event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300247 if (!yaml_emitter_emit(&emitter, &event))
248 ERROR_GOTO(emitter_delete, "Failed to emit YAML doc end event");
249
250 /* Stream end */
251 if (!yaml_stream_end_event_initialize(&event))
252 ERROR_GOTO(emitter_delete,
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200253 "Failed to initialise YAML stream end event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300254 if (!yaml_emitter_emit(&emitter, &event))
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200255 ERROR_GOTO(emitter_delete,
256 "Failed to emit YAML stream end event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300257
258emitter_delete:
259 yaml_emitter_delete(&emitter);
260}
261
262static bool fill_map(char *var, char *value)
263{
264 yaml_event_t event;
265
266 yaml_scalar_event_initialize(&event, NULL, NULL,
267 (yaml_char_t *)var, -1, 1, 1, YAML_PLAIN_SCALAR_STYLE);
268 if (!yaml_emitter_emit(&emitter, &event))
269 ERROR_RETURN_FALSE("Failed to emit YAML scalar");
270
271 yaml_scalar_event_initialize(&event, NULL, NULL,
272 (yaml_char_t *)value, -1, 1, 1, YAML_PLAIN_SCALAR_STYLE);
273 if (!yaml_emitter_emit(&emitter, &event))
274 ERROR_RETURN_FALSE("Failed to emit YAML scalar");
275
276 return true;
277}
278
279static bool fill_timestamp(uint32_t core, uint64_t count, uint64_t addr,
280 const char *subsystem)
281{
282 yaml_event_t event;
283 char data[MAX_SCALAR];
284
285 /* Mapping start */
286 if (!yaml_mapping_start_event_initialize(&event,
287 NULL, NULL , YAML_IMPLICIT,
288 YAML_ANY_SEQUENCE_STYLE))
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200289 ERROR_RETURN_FALSE(
290 "Failed to initialize YAML mapping start event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300291 if (!yaml_emitter_emit(&emitter, &event))
292 ERROR_RETURN_FALSE("Failed to emit YAML mapping start event");
293
294 snprintf(data, MAX_SCALAR, "%" PRIu32, core);
295 fill_map("core", data);
296
297 snprintf(data, MAX_SCALAR, "%" PRIu64, count);
298 fill_map("counter", data);
299
300 snprintf(data, MAX_SCALAR, "0x%" PRIx64, addr);
301 fill_map("address", data);
302
303 snprintf(data, MAX_SCALAR, "%s", subsystem);
304 fill_map("component", data);
305
306 /* Mapping end */
307 if (!yaml_mapping_end_event_initialize(&event))
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200308 ERROR_RETURN_FALSE(
309 "Failed to initialize YAML mapping end event");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300310 if (!yaml_emitter_emit(&emitter, &event))
311 ERROR_RETURN_FALSE("Failed to emit YAML mapping end event");
312
313 return true;
314}
315
316/*
317 * Consume all timestamps from per-cpu ringbuffers and put everything into
318 * the yaml file.
319 */
Igor Opaniukab88c952017-02-14 13:22:54 +0200320static void *ts_consumer(void *arg)
321{
Yves Leflochb31789d2017-08-01 14:51:18 +0200322 unsigned int i;
323 int ret;
Igor Opaniukab88c952017-02-14 13:22:54 +0200324 bool ts_received = false;
325 uint32_t cores;
326 struct tee_time_st ts_data;
327 FILE *ts_file;
Igor Opaniuk3d566ae2018-01-29 02:41:33 +0200328 struct consumer_param *prm = (struct consumer_param *)arg;
329 char *tsfile_path = prm->ts_filepath;
330 pid_t child_pid = prm->child_pid;
331 size_t teec_dyn_addr = 0;
Igor Opaniukab88c952017-02-14 13:22:54 +0200332
Igor Opaniukab88c952017-02-14 13:22:54 +0200333 if (!tsfile_path)
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300334 ERROR_GOTO(exit, "Wrong timestamp file path");
Igor Opaniukab88c952017-02-14 13:22:54 +0200335
336 cores = get_cores();
337 if (!cores)
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300338 ERROR_GOTO(exit, "Can't receive amount of avalable cores");
Igor Opaniukab88c952017-02-14 13:22:54 +0200339
340 ts_file = fopen(tsfile_path, "w");
341 if (!ts_file)
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300342 ERROR_GOTO(exit, "Can't open timestamp file");
343
344 if (!init_emitter(ts_file))
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200345 ERROR_GOTO(file_close,
346 "Error occurred in emitter initialization");
Igor Opaniukab88c952017-02-14 13:22:54 +0200347
348 while (is_running) {
349 ts_received = false;
350 for (i = 0; i < cores; i++) {
351 ret = timestamp_pop(&bench_ts_global->cpu_buf[i],
352 &ts_data);
353 if (!ret) {
354 ts_received = true;
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +0200355 DBG("Timestamp: core = %u; tick = %lld; "
356 "pc = 0x%" PRIx64 "; system = %s",
357 i, ts_data.cnt, ts_data.addr,
358 bench_str_src(ts_data.src));
Igor Opaniuk845a7832018-06-06 14:06:10 +0300359 do {
Igor Opaniuk3d566ae2018-01-29 02:41:33 +0200360 teec_dyn_addr = get_library_load_offset
361 (child_pid,
362 LIBTEEC_NAME);
Igor Opaniuk845a7832018-06-06 14:06:10 +0300363
364 } while (!teec_dyn_addr && is_running);
Igor Opaniuk3d566ae2018-01-29 02:41:33 +0200365 if (ts_data.src == TEE_BENCH_CLIENT) {
366 DBG("ts_addr = %llx, teec_addr = %x",
367 ts_data.addr, teec_dyn_addr);
368 ts_data.addr -= teec_dyn_addr;
369 }
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300370 if (!fill_timestamp(i, ts_data.cnt,
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +0200371 ts_data.addr,
372 bench_str_src(ts_data.src)))
373 ERROR_GOTO(deinit_yaml,
374 "Adding timestamp failed");
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300375
Igor Opaniukab88c952017-02-14 13:22:54 +0200376 }
377 }
378
Yves Leflochb31789d2017-08-01 14:51:18 +0200379 if (!ts_received) {
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300380 if (is_running) {
381 DBG("yielding...");
Igor Opaniukab88c952017-02-14 13:22:54 +0200382 sched_yield();
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300383 } else {
384 ERROR_GOTO(deinit_yaml,
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +0200385 "No new data in the per-cpu ringbuffers"
386 );
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300387 }
Yves Leflochb31789d2017-08-01 14:51:18 +0200388 }
Igor Opaniukab88c952017-02-14 13:22:54 +0200389 }
390
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300391deinit_yaml:
392 deinit_emitter();
Igor Opaniukab88c952017-02-14 13:22:54 +0200393file_close:
394 fclose(ts_file);
395exit:
396 return NULL;
397}
398
399int main(int argc, char *argv[])
400{
401 int i;
402 int status;
403 pid_t pid;
404 char testapp_path[PATH_MAX];
405 char **testapp_argv;
406 char *res;
407 char *tsfile_path;
408 uint32_t cores;
409 pthread_t consumer_thread;
Igor Opaniuk3d566ae2018-01-29 02:41:33 +0200410 struct consumer_param prm;
Igor Opaniukab88c952017-02-14 13:22:54 +0200411
412 if (argc == 1) {
413 usage(argv[0]);
414 return 0;
415 }
416
417 /* Parse command line */
418 for (i = 1; i < argc; i++) {
419 if (!strcmp(argv[i], "-h")) {
420 usage(argv[0]);
421 return 0;
422 }
423 }
424
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300425 signal(SIGINT, sigint_handler);
426
427 INFO("1. Opening Benchmark Static TA...");
Igor Opaniukab88c952017-02-14 13:22:54 +0200428 open_bench_pta();
429
430 cores = get_cores();
431 if (!cores)
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300432 ERROR_EXIT("Receiving amount of active cores failed");
Igor Opaniukab88c952017-02-14 13:22:54 +0200433
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300434 INFO("2. Allocating per-core buffers, cores detected = %d",
Igor Opaniukab88c952017-02-14 13:22:54 +0200435 cores);
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +0200436 alloc_bench_buf(cores);
Igor Opaniukab88c952017-02-14 13:22:54 +0200437
438 res = realpath(argv[1], testapp_path);
439 if (!res)
440 tee_errx("Failed to get realpath", EXIT_FAILURE);
441
442 alloc_argv(argc, argv, &testapp_argv);
443
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300444 INFO("3. Starting origin host app %s ...", testapp_path);
Igor Opaniukab88c952017-02-14 13:22:54 +0200445
446 /* fork/exec here */
447 pid = fork();
448
449 if (pid == -1) {
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300450 DBG("fork() failed");
451 ERROR_EXIT("Starting origin host application failed.");
Igor Opaniukab88c952017-02-14 13:22:54 +0200452 } else if (pid > 0) {
453 is_running = 1;
Igor Opaniukab88c952017-02-14 13:22:54 +0200454 tsfile_path = malloc(strlen(testapp_path) +
455 strlen(TSFILE_NAME_SUFFIX) + 1);
456 if (!tsfile_path)
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200457 ERROR_EXIT("Memory allocation failed the file path.");
Igor Opaniukab88c952017-02-14 13:22:54 +0200458
459 tsfile_path[0] = '\0';
460 strcat(tsfile_path, testapp_path);
461 strcat(tsfile_path, TSFILE_NAME_SUFFIX);
462
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300463 INFO("Dumping timestamps to %s ...", tsfile_path);
Igor Opaniukab88c952017-02-14 13:22:54 +0200464 print_line();
465
Igor Opaniuk3d566ae2018-01-29 02:41:33 +0200466 prm.child_pid = pid;
467 prm.ts_filepath = tsfile_path;
468
Igor Opaniukab88c952017-02-14 13:22:54 +0200469 if (pthread_create(&consumer_thread, NULL,
Igor Opaniuk3d566ae2018-01-29 02:41:33 +0200470 ts_consumer, &prm)) {
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300471 DBG( "Error creating ts consumer thread");
472 ERROR_EXIT("Can't start process of reading timestamps");
Igor Opaniukab88c952017-02-14 13:22:54 +0200473 }
474 /* wait for child app exits */
475 waitpid(pid, &status, 0);
Igor Opaniuk845a7832018-06-06 14:06:10 +0300476 DBG("Origin host application finished executing");
477
Igor Opaniukab88c952017-02-14 13:22:54 +0200478 is_running = 0;
479
480 /* wait for our consumer thread terminate */
481 if (pthread_join(consumer_thread, NULL)) {
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300482 DBG("Error joining thread");
Igor Opaniuk66e23bf2018-02-06 19:18:59 +0200483 ERROR_EXIT("Couldn't start consuming timestamps");
Igor Opaniukab88c952017-02-14 13:22:54 +0200484 }
485 }
486 else {
487 execvp(testapp_path, testapp_argv);
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300488 DBG("execve() failed");
489 ERROR_EXIT("Starting origin host application failed");
Igor Opaniukab88c952017-02-14 13:22:54 +0200490 }
491
Igor Opaniukf1f3fd02017-09-14 15:34:56 +0300492 INFO("4. Done benchmark");
Igor Opaniukab88c952017-02-14 13:22:54 +0200493
494 dealloc_argv(argc-1, testapp_argv);
Igor Opaniuk55fcc4a2018-02-06 19:20:22 +0200495 free_bench_buf();
Igor Opaniukab88c952017-02-14 13:22:54 +0200496 close_bench_pta();
497 return 0;
498}