benchmark: change format of ts file to yaml
1. Use libyaml to generate timestamp dump file in YAML format.
2. Misc cosmetic changes and refactoring (debug output).
Example of ts file:
timestamps:
- core: 0
counter: 5818870656
address: 0x804d01f0
component: kmodule
- core: 0
counter: 5819087360
address: 0xe01d81b
component: core
...
Acked-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Igor Opaniuk <igor.opaniuk@linaro.org>
diff --git a/main.c b/main.c
index 458f1a9..403363c 100644
--- a/main.c
+++ b/main.c
@@ -40,27 +40,32 @@
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <yaml.h>
#include "benchmark_aux.h"
+#include "common.h"
-#define STAT_AMOUNT 5
-#define TSFILE_NAME_SUFFIX ".ts"
-
-#define RING_SUCCESS 0
-#define RING_BADPARM -1
-#define RING_NODATA -2
+#define MAX_SCALAR 20
+static struct tee_ts_global *bench_ts_global;
static const TEEC_UUID pta_benchmark_uuid = PTA_BENCHMARK_UUID;
-struct tee_ts_global *bench_ts_global;
-static bool is_running;
-
static TEEC_SharedMemory ts_buf_shm = {
.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT
};
-
static TEEC_Context ctx;
static TEEC_Session sess;
+static volatile sig_atomic_t is_running;
+static yaml_emitter_t emitter;
+
+
+void sigint_handler(int data)
+{
+ (void)data;
+
+ is_running = 0;
+}
+
static void open_bench_pta(void)
{
TEEC_Result res;
@@ -165,6 +170,155 @@
return 0;
}
+static bool init_emitter(FILE *ts_file)
+{
+ yaml_event_t event;
+
+ if (!yaml_emitter_initialize(&emitter))
+ ERROR_RETURN_FALSE("Can't initialize YAML emitter");
+
+ yaml_emitter_set_canonical(&emitter, 0);
+ yaml_emitter_set_unicode(&emitter, 1);
+ yaml_emitter_set_output_file(&emitter, ts_file);
+
+ /* Stream start */
+ if (!yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING))
+ ERROR_GOTO(emitter_delete,
+ "Failed to initialize YAML stream start event");
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_GOTO(emitter_delete, "Failed to emit YAML stream start event");
+
+ /* Document start */
+ if (!yaml_document_start_event_initialize(&event,
+ NULL, NULL, NULL, YAML_IMPLICIT))
+ ERROR_GOTO(emitter_delete,
+ "Failed to initialize YAML document start event");
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_GOTO(emitter_delete, "Failed to emit YAML doc start event");
+
+ /* Mapping start */
+ if (!yaml_mapping_start_event_initialize(&event,
+ NULL, NULL , YAML_IMPLICIT,
+ YAML_ANY_SEQUENCE_STYLE))
+ ERROR_GOTO(emitter_delete,
+ "Failed to initialize YAML mapping start event");
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_GOTO(emitter_delete,
+ "Failed to emit YAML sequence mapping event");
+ /* Key timestamps */
+ yaml_scalar_event_initialize(&event, NULL, NULL,
+ (yaml_char_t *)"timestamps", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE);
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_RETURN_FALSE("Failed to emit YAML scalar");
+
+ /* Sequence start */
+ if (!yaml_sequence_start_event_initialize(&event,
+ NULL, NULL , YAML_IMPLICIT,
+ YAML_ANY_SEQUENCE_STYLE))
+ ERROR_GOTO(emitter_delete,
+ "Failed to initialize YAML sequence start event");
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_GOTO(emitter_delete, "Failed to emit YAML sequence start event");
+
+ return true;
+emitter_delete:
+ yaml_emitter_delete(&emitter);
+ return false;
+}
+
+static void deinit_emitter()
+{
+ yaml_event_t event;
+
+ /* Sequence cmd */
+ if (!yaml_sequence_end_event_initialize(&event))
+ ERROR_GOTO(emitter_delete,
+ "Failed to initialize YAML sequence end event");
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_GOTO(emitter_delete, "Failed to emit YAML sequence end event");
+
+ /* Mapping end */
+ if (!yaml_mapping_end_event_initialize(&event))
+ ERROR_GOTO(emitter_delete,
+ "Failed to initialize YAML mapping end event");
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_GOTO(emitter_delete,
+ "Failed to emit YAML mapping end event");
+
+ /* Document end */
+ if (!yaml_document_end_event_initialize(&event, 0))
+ ERROR_GOTO(emitter_delete,
+ "Failed to initialize YAML document end event");
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_GOTO(emitter_delete, "Failed to emit YAML doc end event");
+
+ /* Stream end */
+ if (!yaml_stream_end_event_initialize(&event))
+ ERROR_GOTO(emitter_delete,
+ "Error occured while initialising YAML stream end event");
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_GOTO(emitter_delete, "Failed to emit YAML stream end event");
+
+emitter_delete:
+ yaml_emitter_delete(&emitter);
+}
+
+static bool fill_map(char *var, char *value)
+{
+ yaml_event_t event;
+
+ yaml_scalar_event_initialize(&event, NULL, NULL,
+ (yaml_char_t *)var, -1, 1, 1, YAML_PLAIN_SCALAR_STYLE);
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_RETURN_FALSE("Failed to emit YAML scalar");
+
+ yaml_scalar_event_initialize(&event, NULL, NULL,
+ (yaml_char_t *)value, -1, 1, 1, YAML_PLAIN_SCALAR_STYLE);
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_RETURN_FALSE("Failed to emit YAML scalar");
+
+ return true;
+}
+
+static bool fill_timestamp(uint32_t core, uint64_t count, uint64_t addr,
+ const char *subsystem)
+{
+ yaml_event_t event;
+ char data[MAX_SCALAR];
+
+ /* Mapping start */
+ if (!yaml_mapping_start_event_initialize(&event,
+ NULL, NULL , YAML_IMPLICIT,
+ YAML_ANY_SEQUENCE_STYLE))
+ ERROR_RETURN_FALSE("Failed to initialize YAML mapping start event");
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_RETURN_FALSE("Failed to emit YAML mapping start event");
+
+ snprintf(data, MAX_SCALAR, "%" PRIu32, core);
+ fill_map("core", data);
+
+ snprintf(data, MAX_SCALAR, "%" PRIu64, count);
+ fill_map("counter", data);
+
+ snprintf(data, MAX_SCALAR, "0x%" PRIx64, addr);
+ fill_map("address", data);
+
+ snprintf(data, MAX_SCALAR, "%s", subsystem);
+ fill_map("component", data);
+
+ /* Mapping end */
+ if (!yaml_mapping_end_event_initialize(&event))
+ ERROR_RETURN_FALSE("Failed to initialize YAML mapping end event");
+ if (!yaml_emitter_emit(&emitter, &event))
+ ERROR_RETURN_FALSE("Failed to emit YAML mapping end event");
+
+ return true;
+}
+
+/*
+ * Consume all timestamps from per-cpu ringbuffers and put everything into
+ * the yaml file.
+ */
static void *ts_consumer(void *arg)
{
unsigned int i;
@@ -173,19 +327,21 @@
uint32_t cores;
struct tee_time_st ts_data;
FILE *ts_file;
- char *tsfile_path;
+ char *tsfile_path = arg;
- tsfile_path = arg;
if (!tsfile_path)
- goto exit;
+ ERROR_GOTO(exit, "Wrong timestamp file path");
cores = get_cores();
if (!cores)
- goto exit;
+ ERROR_GOTO(exit, "Can't receive amount of avalable cores");
ts_file = fopen(tsfile_path, "w");
if (!ts_file)
- goto exit;
+ ERROR_GOTO(exit, "Can't open timestamp file");
+
+ if (!init_emitter(ts_file))
+ ERROR_GOTO(file_close, "Error occured in emitter initialization");
while (is_running) {
ts_received = false;
@@ -194,21 +350,30 @@
&ts_data);
if (!ret) {
ts_received = true;
- fprintf(ts_file, "%u\t%lld\t0x%"
- PRIx64 "\t%s\n",
+ DBG("Timestamp: core = %u; tick = %lld; pc = 0x%"
+ PRIx64 ";system = %s",
i, ts_data.cnt, ts_data.addr,
bench_str_src(ts_data.src));
+ if (!fill_timestamp(i, ts_data.cnt,
+ ts_data.addr, bench_str_src(ts_data.src)))
+ ERROR_GOTO(deinit_yaml, "Adding timestamp failed");
+
}
}
if (!ts_received) {
- if (is_running)
+ if (is_running) {
+ DBG("yielding...");
sched_yield();
- else
- goto file_close;
+ } else {
+ ERROR_GOTO(deinit_yaml,
+ "No new data in the per-cpu ringbuffers, closing ts file");
+ }
}
}
+deinit_yaml:
+ deinit_emitter();
file_close:
fclose(ts_file);
exit:
@@ -240,15 +405,16 @@
}
}
- printf("1. Opening Benchmark Static TA...\n");
+ signal(SIGINT, sigint_handler);
+
+ INFO("1. Opening Benchmark Static TA...");
open_bench_pta();
cores = get_cores();
if (!cores)
- tee_errx("Receiving amount of active cores failed",
- EXIT_FAILURE);
+ ERROR_EXIT("Receiving amount of active cores failed");
- printf("2. Allocating per-core buffers, cores detected = %d\n",
+ INFO("2. Allocating per-core buffers, cores detected = %d",
cores);
register_bench_buf(cores);
@@ -258,32 +424,33 @@
alloc_argv(argc, argv, &testapp_argv);
- printf("3. Starting origin host app %s ...\n", testapp_path);
+ INFO("3. Starting origin host app %s ...", testapp_path);
/* fork/exec here */
pid = fork();
if (pid == -1) {
- tee_errx("fork() failed", EXIT_FAILURE);
+ DBG("fork() failed");
+ ERROR_EXIT("Starting origin host application failed.");
} else if (pid > 0) {
is_running = 1;
tsfile_path = malloc(strlen(testapp_path) +
strlen(TSFILE_NAME_SUFFIX) + 1);
if (!tsfile_path)
- return 1;
+ ERROR_EXIT("Memory allocation failed for timestamp file path.");
tsfile_path[0] = '\0';
strcat(tsfile_path, testapp_path);
strcat(tsfile_path, TSFILE_NAME_SUFFIX);
- printf("Dumping timestamps to %s ...\n", tsfile_path);
+ INFO("Dumping timestamps to %s ...", tsfile_path);
print_line();
if (pthread_create(&consumer_thread, NULL,
ts_consumer, tsfile_path)) {
- fprintf(stderr, "Error creating ts consumer thread\n");
- return 1;
+ DBG( "Error creating ts consumer thread");
+ ERROR_EXIT("Can't start process of reading timestamps");
}
/* wait for child app exits */
waitpid(pid, &status, 0);
@@ -291,16 +458,17 @@
/* wait for our consumer thread terminate */
if (pthread_join(consumer_thread, NULL)) {
- fprintf(stderr, "Error joining thread\n");
- return 2;
+ DBG("Error joining thread");
+ ERROR_EXIT("Something went wrong while consuming timestamps");
}
}
else {
execvp(testapp_path, testapp_argv);
- tee_errx("execve() failed", EXIT_FAILURE);
+ DBG("execve() failed");
+ ERROR_EXIT("Starting origin host application failed");
}
- printf("4. Done benchmark\n");
+ INFO("4. Done benchmark");
dealloc_argv(argc-1, testapp_argv);
unregister_bench();