#include "bench_common.h"
#include <getopt.h>
#include <unistd.h>
#include<time.h>
#define UAREA_SIZE 8
#define EVENT_SIZE 1024
#define NUM_EVENTS 1024
#define MAX_POOL_STATS 1024u
#define CORE_COUNT 2
typedef struct {
run_bench_arg_t run_bench_arg;
odp_pool_stats_opt_t stats_opt_odp;
} gbl_args_t;
static gbl_args_t *gbl_args;
ODP_STATIC_ASSERT(REPEAT_COUNT <= MAX_POOL_STATS, "REPEAT_COUNT is bigger than MAX_POOL_STATS\n");
static int pool_stats(void)
{
int i;
for (i = 0; i < REPEAT_COUNT; i++)
return i;
}
static void set_stats_opt(void)
{
gbl_args->stats_opt.all = 0;
gbl_args->stats_opt.available = 1;
gbl_args->stats_opt.alloc_ops = 1;
gbl_args->stats_opt.alloc_fails = 1;
gbl_args->stats_opt.cache_alloc_ops = 1;
gbl_args->stats_opt.cache_free_ops = 1;
gbl_args->stats_opt.free_ops = 1;
gbl_args->stats_opt.total_ops = 1;
gbl_args->stats_opt.cache_available = 1;
}
static void set_stats_opt_no_cache_avail(void)
{
gbl_args->stats_opt.all = 0;
gbl_args->stats_opt.available = 1;
gbl_args->stats_opt.alloc_ops = 1;
gbl_args->stats_opt.alloc_fails = 1;
gbl_args->stats_opt.cache_alloc_ops = 1;
gbl_args->stats_opt.cache_free_ops = 1;
gbl_args->stats_opt.free_ops = 1;
gbl_args->stats_opt.total_ops = 1;
}
static int pool_stats_selected(void)
{
int i;
for (i = 0; i < REPEAT_COUNT; i++)
&gbl_args->stats_opt);
return i;
}
static void set_subpools(void)
{
gbl_args->subpools[0] = 0;
}
static int subpool_stats(void)
{
int i;
for (i = 0; i < REPEAT_COUNT; i++)
&gbl_args->subpool_stats[i]);
return i;
}
static int subpool_stats_selected(void)
{
int i;
for (i = 0; i < REPEAT_COUNT; i++)
&gbl_args->subpool_stats_selected[i],
&gbl_args->stats_opt);
return i;
}
static int pool_info(void)
{
int i;
for (i = 0; i < REPEAT_COUNT; i++)
return i;
}
bench_info_t test_suite[] = {
BENCH_INFO(pool_info, NULL, NULL, 0, "em_pool_info"),
BENCH_INFO(pool_stats, NULL, NULL, 0, "em_pool_stats"),
BENCH_INFO(subpool_stats, set_subpools, NULL, 0, "em_pool_subpool_stats"),
BENCH_INFO(pool_stats_selected, set_stats_opt, NULL, 0, "em_pool_stats_selected"),
BENCH_INFO(pool_stats_selected, set_stats_opt_no_cache_avail, NULL, 0,
"em_pool_stats_selected(no cache_availeble)"),
BENCH_INFO(subpool_stats_selected, set_stats_opt, NULL, 0,
"em_pool_subpool_stats_selected"),
BENCH_INFO(subpool_stats_selected, set_stats_opt_no_cache_avail, NULL, 0,
"em_pool_subpool_stats_selected(no cache_available)")
};
static void usage(void)
{
printf("\n"
"EM event API micro benchmarks\n"
"\n"
"Options:\n"
" -t, --time <opt> Time measurement.\n"
" 0: measure CPU cycles (default)\n"
" 1: measure time\n"
" -i, --index <idx> Benchmark index to run indefinitely.\n"
" -r, --rounds <num> Run each test case 'num' times (default %u).\n"
" -w, --write-csv Write result to csv files(used in CI) or not.\n"
" default: not write\n"
" -h, --help Display help and exit.\n\n"
"\n", ROUNDS);
}
static int parse_args(int argc, char *argv[], int num_bench, cmd_opt_t *cmd_opt)
{
int opt;
int long_index;
static const struct option longopts[] = {
{"time", required_argument, NULL, 't'},
{"index", required_argument, NULL, 'i'},
{"rounds", required_argument, NULL, 'r'},
{"write-csv", no_argument, NULL, 'w'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
static const char *shortopts = "t:i:r:wh";
cmd_opt->time = 0;
cmd_opt->bench_idx = 0;
cmd_opt->rounds = ROUNDS;
cmd_opt->write_csv = 0;
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
if (opt == -1)
break;
switch (opt) {
case 't':
cmd_opt->time = atoi(optarg);
break;
case 'i':
cmd_opt->bench_idx = atoi(optarg);
break;
case 'r':
cmd_opt->rounds = atoi(optarg);
break;
case 'w':
cmd_opt->write_csv = 1;
break;
case 'h':
usage();
return 1;
default:
ODPH_ERR("Bad option. Use -h for help.\n");
return -1;
}
}
if (cmd_opt->rounds < 1) {
ODPH_ERR("Invalid test cycle repeat count: %u\n", cmd_opt->rounds);
return -1;
}
if (cmd_opt->bench_idx < 0 || cmd_opt->bench_idx > num_bench) {
ODPH_ERR("Bad bench index %i\n", cmd_opt->bench_idx);
return -1;
}
optind = 1;
return 0;
}
static void print_info(const char *cpumask_str, const cmd_opt_t *com_opt)
{
odp_sys_info_print();
printf("\n"
"bench_pool options\n"
"-------------------\n");
printf("Worker CPU mask: %s\n", cpumask_str);
printf("Measurement unit: %s\n", com_opt->time ? "nsec" : "CPU cycles");
printf("Test rounds: %u\n", com_opt->rounds);
printf("\n");
}
{
}
static void alloc_free_event(void)
{
const int event_tbl_size = NUM_EVENTS + 10;
em_event_t event_tbl[event_tbl_size];
int i;
for (i = 0; i < event_tbl_size; i++) {
}
for (i = 0; i < event_tbl_size; i++) {
}
}
static void write_result_to_csv(void)
{
FILE *file;
char time_str[72] = {0};
char bench4_desc[60] = {0};
char bench5_desc[60] = {0};
char bench6_desc[60] = {0};
double *result = gbl_args->run_bench_arg.result;
bench_info_t *bench = gbl_args->run_bench_arg.bench;
fill_time_str(time_str);
file = fopen("em_pool.csv", "w");
if (file == NULL) {
perror("Failed to open file em_pool.csv");
return;
}
strncpy(bench4_desc, bench[4].desc, 22);
strncpy(bench5_desc, bench[5].desc + 8, 22);
strncpy(bench6_desc, bench[6].desc + 8, 22);
fprintf(file, "Date,%s,%s,%s,%s,%s\n"
"%s,%.2f,%.2f,%.2f,%.2f,%.2f\n",
bench[0].desc, bench[1].desc, bench[2].desc, bench[3].desc, bench5_desc,
time_str, result[0], result[1], result[2], result[3], result[5]);
fclose(file);
file = fopen("em_pool_no_cache_available.csv", "w");
if (file == NULL) {
perror("Failed to open file em_pool_no_cache_available.csv");
return;
}
fprintf(file, "Date,%s,%s\n%s,%.2f,%.2f\n", bench4_desc, bench6_desc,
time_str, result[4], result[6]);
fclose(file);
}
int main(int argc, char *argv[])
{
cmd_opt_t cmd_opt;
odph_helper_options_t helper_options;
odph_thread_t worker_thread;
odph_thread_common_param_t thr_common;
odph_thread_param_t thr_param;
odp_shm_t shm;
odp_cpumask_t cpumask, worker_mask;
odp_instance_t instance;
odp_init_t init_param;
int worker_cpu;
char cpumask_str[ODP_CPUMASK_STR_SIZE];
int ret = 0;
int num_bench = ARRAY_SIZE(test_suite);
double result[ARRAY_SIZE(test_suite)] = {0};
argc = odph_parse_options(argc, argv);
if (odph_options(&helper_options)) {
ODPH_ERR("Reading ODP helper options failed\n");
exit(EXIT_FAILURE);
}
ret = parse_args(argc, argv, num_bench, &cmd_opt);
if (ret)
exit(EXIT_FAILURE);
odp_init_param_init(&init_param);
init_param.mem_model = helper_options.mem_model;
if (odp_init_global(&instance, &init_param, NULL)) {
ODPH_ERR("Global init failed\n");
exit(EXIT_FAILURE);
}
if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
ODPH_ERR("Local init failed\n");
exit(EXIT_FAILURE);
}
odp_schedule_config(NULL);
if (odp_cpumask_default_worker(&worker_mask, 1) != 1) {
ODPH_ERR("Unable to allocate worker thread\n");
goto odp_term;
}
worker_cpu = odp_cpumask_first(&worker_mask);
(void)odp_cpumask_to_str(&worker_mask, cpumask_str, ODP_CPUMASK_STR_SIZE);
print_info(cpumask_str, &cmd_opt);
if (odp_cpumask_count(&core_mask.
odp_cpumask) != CORE_COUNT)
goto odp_term;
init_default_pool_config(&pool_conf);
if (helper_options.mem_model == ODP_MEM_MODEL_PROCESS)
else
ODPH_ERR("EM init failed\n");
exit(EXIT_FAILURE);
}
ODPH_ERR("EM core init failed\n");
exit(EXIT_FAILURE);
}
if (setup_sig_handler()) {
ODPH_ERR("Signal handler setup failed\n");
exit(EXIT_FAILURE);
}
shm = odp_shm_reserve("shm_args", sizeof(gbl_args_t), ODP_CACHE_LINE_SIZE, 0);
if (shm == ODP_SHM_INVALID) {
ODPH_ERR("Shared mem reserve failed\n");
exit(EXIT_FAILURE);
}
gbl_args = odp_shm_addr(shm);
if (gbl_args == NULL) {
ODPH_ERR("Shared mem alloc failed\n");
exit(EXIT_FAILURE);
}
odp_atomic_init_u32(&exit_thread, 0);
memset(gbl_args, 0, sizeof(gbl_args_t));
gbl_args->run_bench_arg.bench = test_suite;
gbl_args->run_bench_arg.num_bench = num_bench;
gbl_args->run_bench_arg.opt = cmd_opt;
gbl_args->run_bench_arg.result = result;
alloc_free_event();
memset(&worker_thread, 0, sizeof(odph_thread_t));
odp_cpumask_zero(&cpumask);
odp_cpumask_set(&cpumask, worker_cpu);
odph_thread_common_param_init(&thr_common);
thr_common.instance = instance;
thr_common.cpumask = &cpumask;
thr_common.share_param = 1;
odph_thread_param_init(&thr_param);
thr_param.start = run_benchmarks;
thr_param.arg = &gbl_args->run_bench_arg;
thr_param.thr_type = ODP_THREAD_WORKER;
odph_thread_create(&worker_thread, &thr_common, &thr_param, 1);
odph_thread_join(&worker_thread, 1);
ret = gbl_args->run_bench_arg.bench_failed;
if (cmd_opt.write_csv)
write_result_to_csv();
ODPH_ERR("EM core terminate failed\n");
ODPH_ERR("EM terminate failed\n");
if (odp_shm_free(shm)) {
ODPH_ERR("Shared mem free failed\n");
exit(EXIT_FAILURE);
}
odp_term:
if (odp_term_local()) {
ODPH_ERR("Local term failed\n");
exit(EXIT_FAILURE);
}
if (odp_term_global(instance)) {
ODPH_ERR("Global term failed\n");
exit(EXIT_FAILURE);
}
if (ret < 0)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}