@@ -16,5 +16,16 @@ AM_LDFLAGS = -L$(PAPI_PATH)/lib -lpapi
lib_LTLIBRARIES = $(LIB)/libinstrum.la
+noinst_HEADERS = \
+ $(srcdir)/instrum_common.h \
+ $(srcdir)/store.h \
+ $(srcdir)/init.h \
+ $(srcdir)/drv.h \
+ $(srcdir)/sched.h
+
__LIB__libinstrum_la_SOURCES = \
- instrum.c
+ instrum.c \
+ store.c \
+ init.c \
+ drv.c \
+ sched.c
new file mode 100644
@@ -0,0 +1,39 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <odp_drv.h>
+#include <instrum_common.h>
+#include <drv.h>
+#include <store.h>
+
+static int (*instr_odpdrv_print_all)(void);
+
+int instr_odpdrv_init(void)
+{
+ INSTR_FUNCTION(odpdrv_print_all);
+
+ if (!instr_odpdrv_print_all) {
+ printf("odpdrv_print_all: Not Found\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int odpdrv_print_all(void)
+{
+ int ret;
+
+ STORE_SAMPLE_INIT;
+
+ STORE_SAMPLE_START;
+ ret = (*instr_odpdrv_print_all)();
+ STORE_SAMPLE_END;
+
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,19 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __INSTRUM_DRV_H__
+#define __INSTRUM_DRV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int instr_odpdrv_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __INSTRUM_DRV_H__ */
new file mode 100644
@@ -0,0 +1,54 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <odp_api.h>
+#include <instrum_common.h>
+#include <init.h>
+#include <store.h>
+
+static int (*instr_odp_init_local)(odp_instance_t instance,
+ odp_thread_type_t thr_type);
+
+static int (*instr_odp_term_local)(void);
+
+int instr_odpinit_init(void)
+{
+ INSTR_FUNCTION(odp_init_local);
+
+ if (!instr_odp_init_local) {
+ printf("odp_init_local: Not Found\n");
+ return -1;
+ }
+
+ INSTR_FUNCTION(odp_term_local);
+
+ if (!instr_odp_term_local) {
+ printf("odp_term_local: Not Found\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
+{
+ int ret;
+
+ ret = (*instr_odp_init_local)(instance, thr_type);
+
+ instr_store_init_local();
+
+ return ret;
+}
+
+int odp_term_local(void)
+{
+ instr_store_term_local();
+
+ return (*instr_odp_term_local)();
+}
new file mode 100644
@@ -0,0 +1,19 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __INSTRUM_INIT_H__
+#define __INSTRUM_INIT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int instr_odpinit_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__INSTRUM_INIT_H__*/
@@ -6,13 +6,30 @@
#include <stdio.h>
#include <stdlib.h>
+#include <store.h>
+#include <init.h>
+#include <drv.h>
+#include <sched.h>
static __attribute__((constructor)) void setup_wrappers(void)
{
printf("Setup Wrappers\n");
+
+ if (instr_store_init())
+ return;
+
+ if (instr_odpinit_init())
+ return;
+
+ if (instr_odpdrv_init())
+ return;
+
+ if (instr_odpsched_init())
+ return;
}
static __attribute__((destructor)) void teardown_wrappers(void)
{
printf("Teardown Wrappers\n");
+ instr_store_term();
}
new file mode 100644
@@ -0,0 +1,34 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __INSTRUM_COMMON_H__
+#define __INSTRUM_COMMON_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef RTLD_NEXT
+/*#define __GNU_SOURCE*/
+#define __USE_GNU
+#endif
+
+#include <dlfcn.h>
+#include <errno.h>
+
+#define INSTR_FUNCTION(func) do { \
+ instr_##func = dlsym(RTLD_NEXT, #func); \
+ if (dlerror()) { \
+ errno = EACCES; \
+ instr_##func = NULL; \
+ } \
+ } while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INSTRUM_COMMON_H__ */
new file mode 100644
@@ -0,0 +1,43 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <odp_api.h>
+#include <instrum_common.h>
+#include <sched.h>
+#include <store.h>
+
+static int (*instr_odp_schedule_multi)(odp_queue_t *from,
+ uint64_t wait,
+ odp_event_t events[],
+ int num);
+
+int instr_odpsched_init(void)
+{
+ INSTR_FUNCTION(odp_schedule_multi);
+
+ if (!instr_odp_schedule_multi) {
+ printf("odp_schedule_multi: Not Found\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int odp_schedule_multi(odp_queue_t *from, uint64_t wait, odp_event_t events[],
+ int num)
+{
+ int ret;
+
+ STORE_SAMPLE_INIT;
+
+ STORE_SAMPLE_START;
+ ret = (*instr_odp_schedule_multi)(from, wait, events, num);
+ STORE_SAMPLE_END;
+
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,19 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __INSTRUM_SCHED_H__
+#define __INSTRUM_SCHED_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int instr_odpsched_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __INSTRUM_SCHED_H__ */
new file mode 100644
@@ -0,0 +1,244 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <odp_api.h>
+#include <store.h>
+#include <pthread.h>
+#include "papi.h"
+
+#define PAPI_EVENT_CNT 2
+static int papi_event_tab[PAPI_EVENT_CNT] = {PAPI_BR_CN, PAPI_L2_DCM};
+
+#define PROFILE_SAMPLE_CNT_MAX 50000
+#define PROFILE_SAMPLE_NAME_SIZE_MAX 20
+
+typedef struct {
+ char name[PROFILE_SAMPLE_NAME_SIZE_MAX];
+ long long timestamp_ns;
+ long long diff_cyc;
+
+ long long counters[PAPI_EVENT_CNT];
+} profiling_sample_t;
+
+static __thread profiling_sample_t profile_sample_tab[PROFILE_SAMPLE_CNT_MAX];
+static __thread uint64_t profile_sample_idx;
+static __thread uint64_t profile_sample_ovf;
+
+static __thread int event_set = PAPI_NULL;
+
+#define STORE_DIR_ENV "ODP_INSTRUM_STORE_DIR"
+#define STORE_DIR_NAME_DFLT "/tmp"
+#define STORE_DIR_NAME_SIZE_MAX 250
+#define STORE_FILE_NAME_SIZE_MAX 250
+
+static char store_dir[STORE_DIR_NAME_SIZE_MAX];
+
+static int papi_init(void)
+{
+ int retval, i;
+
+ retval = PAPI_library_init(PAPI_VER_CURRENT);
+ if (retval != PAPI_VER_CURRENT) {
+ printf("PAPI Library initialization error!\n");
+ return -1;
+ }
+
+ retval = PAPI_thread_init((unsigned long(*)(void))(pthread_self));
+ if (retval != PAPI_OK) {
+ printf("PAPI_thread_init error!\n");
+ goto err_shutdown;
+ }
+
+ if (PAPI_set_granularity(PAPI_GRN_THR) != PAPI_OK) {
+ printf("PAPI_set_granularity error!\n");
+ goto err_shutdown;
+ }
+
+ for (i = 0; i < PAPI_EVENT_CNT; i++) {
+ retval = PAPI_query_event(papi_event_tab[i]);
+ if (retval != PAPI_OK) {
+ printf("PAPI_query_event %d - error\n", i);
+ goto err_shutdown;
+ }
+ }
+
+ return 0;
+
+err_shutdown:
+ PAPI_shutdown();
+
+ return -1;
+}
+
+static void papi_term(void)
+{
+ PAPI_shutdown();
+}
+
+static int papi_init_local(void)
+{
+ int retval;
+
+ retval = PAPI_register_thread();
+ if (retval != PAPI_OK) {
+ printf("PAPI_register_thread failed - %d\n", retval);
+ return -1;
+ }
+
+ /* Create LL event set */
+ event_set = PAPI_NULL;
+ retval = PAPI_create_eventset(&event_set);
+ if (retval != PAPI_OK) {
+ printf("PAPI_create_eventset error: %d\n", retval);
+ return -1;
+ }
+
+ retval = PAPI_add_events(event_set, papi_event_tab, PAPI_EVENT_CNT);
+ if (retval != PAPI_OK) {
+ printf("PAPI_add_events error: %d\n", retval);
+ goto err_clean_evset;
+ }
+
+ retval = PAPI_start(event_set);
+ if (retval != PAPI_OK) {
+ printf("PAPI_start error: %d\n", retval);
+ goto err_clean_evset;
+ }
+
+ return 0;
+
+err_clean_evset:
+ PAPI_cleanup_eventset(event_set);
+ PAPI_destroy_eventset(&event_set);
+
+ return -1;
+}
+
+static int papi_term_local(void)
+{
+ long long last_counters[PAPI_EVENT_CNT];
+
+ if (PAPI_stop(event_set, last_counters) == PAPI_OK) {
+ int i;
+
+ for (i = 0; i < PAPI_EVENT_CNT; i++)
+ printf("Counter[%d] = %lld\n", i, last_counters[i]);
+ }
+
+ PAPI_cleanup_eventset(event_set);
+ PAPI_destroy_eventset(&event_set);
+
+ return 0;
+}
+
+int instr_store_init(void)
+{
+ const char *store_dir_env = NULL;
+
+ store_dir_env = getenv(STORE_DIR_ENV);
+ if (!store_dir_env)
+ store_dir_env = STORE_DIR_NAME_DFLT;
+
+ strncpy(store_dir, store_dir_env, STORE_DIR_NAME_SIZE_MAX);
+ store_dir[STORE_DIR_NAME_SIZE_MAX - 1] = '\0';
+
+ if (papi_init())
+ return -1;
+
+ return 0;
+}
+
+void instr_store_term(void)
+{
+ papi_term();
+}
+
+int instr_store_init_local(void)
+{
+ return papi_init_local();
+}
+
+int instr_store_term_local(void)
+{
+ return papi_term_local();
+}
+
+static void store_dump(void)
+{
+ FILE *f = NULL;
+ char file_name[STORE_DIR_NAME_SIZE_MAX + STORE_FILE_NAME_SIZE_MAX];
+ char smpl[250], smpl_tmp[250];
+ int i, j;
+
+ sprintf(file_name, "%s/profile_%d_%ju.csv",
+ store_dir, odp_thread_id(),
+ profile_sample_ovf);
+
+ f = fopen(file_name, "w");
+ if (f == NULL) {
+ printf("Failed to create profiling file %s\n", file_name);
+ return;
+ }
+
+ for (i = 0; i < PROFILE_SAMPLE_CNT_MAX; i++) {
+ sprintf(smpl, "%lld,%lld,%s",
+ profile_sample_tab[i].timestamp_ns,
+ profile_sample_tab[i].diff_cyc,
+ profile_sample_tab[i].name);
+ for (j = 0; j < PAPI_EVENT_CNT; j++) {
+ sprintf(smpl_tmp, ",%lld",
+ profile_sample_tab[i].counters[j]);
+ strcat(smpl, smpl_tmp);
+ }
+ fprintf(f, "%s\n", smpl);
+ }
+
+ fclose(f);
+}
+
+instr_profiling_sample_t store_sample_start(const char *func)
+{
+ profiling_sample_t *spl = NULL;
+
+ spl = &profile_sample_tab[profile_sample_idx++];
+ if (profile_sample_idx == PROFILE_SAMPLE_CNT_MAX) {
+ store_dump();
+ profile_sample_idx = 0;
+ profile_sample_ovf++;
+ }
+ strncpy(spl->name, func, PROFILE_SAMPLE_NAME_SIZE_MAX);
+ spl->name[PROFILE_SAMPLE_NAME_SIZE_MAX - 1] = '\0';
+ spl->timestamp_ns = PAPI_get_real_nsec();
+ if (PAPI_read_ts(event_set, spl->counters, &spl->diff_cyc) != PAPI_OK) {
+ fprintf(stderr, "PAPI_read_counters - FAILED\n");
+ spl->name[0] = 0; /* signal failed sample */
+ }
+
+ return spl;
+}
+
+void store_sample_end(instr_profiling_sample_t _spl)
+{
+ profiling_sample_t *spl = _spl;
+ long long end_counters[PAPI_EVENT_CNT], end_cyc;
+ int i;
+
+ if (!spl->name[0]) /* failed sample - on start */
+ return;
+
+ if (PAPI_read_ts(event_set, end_counters, &end_cyc) != PAPI_OK) {
+ fprintf(stderr, "PAPI_read_counters - FAILED\n");
+ spl->name[0] = 0; /* signal failed sample*/
+ return;
+ }
+
+ for (i = 0; i < PAPI_EVENT_CNT; i++)
+ spl->counters[i] = end_counters[i] - spl->counters[i];
+
+ spl->diff_cyc = end_cyc - spl->diff_cyc;
+}
new file mode 100644
@@ -0,0 +1,36 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __INSTRUM_STORE_H__
+#define __INSTRUM_STORE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *instr_profiling_sample_t;
+
+#define STORE_SAMPLE_INIT \
+ instr_profiling_sample_t _spl
+
+#define STORE_SAMPLE_START \
+ (_spl = store_sample_start(__func__))
+
+#define STORE_SAMPLE_END \
+ store_sample_end(_spl)
+
+int instr_store_init(void);
+void instr_store_term(void);
+int instr_store_init_local(void);
+int instr_store_term_local(void);
+
+instr_profiling_sample_t store_sample_start(const char *);
+void store_sample_end(instr_profiling_sample_t);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __INSTRUM_STORE_H__ */