aboutsummaryrefslogtreecommitdiff
path: root/test/performance
diff options
context:
space:
mode:
Diffstat (limited to 'test/performance')
-rw-r--r--test/performance/odp_crypto.c44
-rw-r--r--test/performance/odp_ipsec.c57
-rw-r--r--test/performance/odp_pktio_perf.c19
-rw-r--r--test/performance/odp_sched_perf.c97
4 files changed, 131 insertions, 86 deletions
diff --git a/test/performance/odp_crypto.c b/test/performance/odp_crypto.c
index 4f81dab17..341782630 100644
--- a/test/performance/odp_crypto.c
+++ b/test/performance/odp_crypto.c
@@ -19,10 +19,6 @@
#include <odp_api.h>
#include <odp/helper/odph_api.h>
-#define app_err(fmt, ...) \
- fprintf(stderr, "%s:%d:%s(): Error: " fmt, __FILE__, \
- __LINE__, __func__, ##__VA_ARGS__)
-
/** @def POOL_NUM_PKT
* Number of packets in the pool
*/
@@ -640,7 +636,7 @@ create_session_from_config(odp_crypto_session_t *session,
/* Lookup the packet pool */
pkt_pool = odp_pool_lookup("packet_pool");
if (pkt_pool == ODP_POOL_INVALID) {
- app_err("packet_pool pool not found\n");
+ ODPH_ERR("packet_pool pool not found\n");
return -1;
}
params.output_pool = pkt_pool;
@@ -648,7 +644,7 @@ create_session_from_config(odp_crypto_session_t *session,
if (cargs->schedule || cargs->poll) {
out_queue = odp_queue_lookup("crypto-out");
if (out_queue == ODP_QUEUE_INVALID) {
- app_err("crypto-out queue not found\n");
+ ODPH_ERR("crypto-out queue not found\n");
return -1;
}
params.compl_queue = out_queue;
@@ -659,7 +655,7 @@ create_session_from_config(odp_crypto_session_t *session,
}
if (odp_crypto_session_create(&params, session,
&ses_create_rc)) {
- app_err("crypto session create failed.\n");
+ ODPH_ERR("crypto session create failed.\n");
return -1;
}
@@ -673,7 +669,7 @@ make_packet(odp_pool_t pkt_pool, unsigned int payload_length)
pkt = odp_packet_alloc(pkt_pool, payload_length);
if (pkt == ODP_PACKET_INVALID) {
- app_err("failed to allocate buffer\n");
+ ODPH_ERR("failed to allocate buffer\n");
return pkt;
}
@@ -704,14 +700,14 @@ run_measure_one(crypto_args_t *cargs,
pkt_pool = odp_pool_lookup("packet_pool");
if (pkt_pool == ODP_POOL_INVALID) {
- app_err("pkt_pool not found\n");
+ ODPH_ERR("pkt_pool not found\n");
return -1;
}
out_queue = odp_queue_lookup("crypto-out");
if (cargs->schedule || cargs->poll) {
if (out_queue == ODP_QUEUE_INVALID) {
- app_err("crypto-out queue not found\n");
+ ODPH_ERR("crypto-out queue not found\n");
return -1;
}
}
@@ -766,8 +762,7 @@ run_measure_one(crypto_args_t *cargs,
rc = odp_crypto_op_enq(&pkt, &out_pkt,
&params, 1);
if (rc <= 0) {
- app_err("failed odp_crypto_packet_op_enq: rc = %d\n",
- rc);
+ ODPH_ERR("failed odp_crypto_packet_op_enq: rc = %d\n", rc);
if (!cargs->reuse_packet)
odp_packet_free(pkt);
break;
@@ -777,8 +772,7 @@ run_measure_one(crypto_args_t *cargs,
rc = odp_crypto_op(&pkt, &out_pkt,
&params, 1);
if (rc <= 0) {
- app_err("failed odp_crypto_packet_op: rc = %d\n",
- rc);
+ ODPH_ERR("failed odp_crypto_packet_op: rc = %d\n", rc);
if (!cargs->reuse_packet)
odp_packet_free(pkt);
break;
@@ -1045,7 +1039,7 @@ int main(int argc, char *argv[])
/* Let helper collect its own arguments (e.g. --odph_proc) */
argc = odph_parse_options(argc, argv);
if (odph_options(&helper_options)) {
- app_err("Reading ODP helper options failed.\n");
+ ODPH_ERR("Reading ODP helper options failed.\n");
exit(EXIT_FAILURE);
}
@@ -1059,7 +1053,7 @@ int main(int argc, char *argv[])
/* Init ODP before calling anything else */
if (odp_init_global(&instance, &init_param, NULL)) {
- app_err("ODP global init failed.\n");
+ ODPH_ERR("ODP global init failed.\n");
exit(EXIT_FAILURE);
}
@@ -1069,22 +1063,22 @@ int main(int argc, char *argv[])
odp_sys_info_print();
if (odp_crypto_capability(&crypto_capa)) {
- app_err("Crypto capability request failed.\n");
+ ODPH_ERR("Crypto capability request failed.\n");
exit(EXIT_FAILURE);
}
if (cargs.schedule && crypto_capa.queue_type_sched == 0) {
- app_err("scheduled type completion queue not supported.\n");
+ ODPH_ERR("scheduled type completion queue not supported.\n");
exit(EXIT_FAILURE);
}
if (cargs.poll && crypto_capa.queue_type_plain == 0) {
- app_err("plain type completion queue not supported.\n");
+ ODPH_ERR("plain type completion queue not supported.\n");
exit(EXIT_FAILURE);
}
if (odp_pool_capability(&pool_capa)) {
- app_err("Pool capability request failed.\n");
+ ODPH_ERR("Pool capability request failed.\n");
exit(EXIT_FAILURE);
}
@@ -1106,7 +1100,7 @@ int main(int argc, char *argv[])
pool = odp_pool_create("packet_pool", &params);
if (pool == ODP_POOL_INVALID) {
- app_err("packet pool create failed.\n");
+ ODPH_ERR("packet pool create failed.\n");
exit(EXIT_FAILURE);
}
odp_pool_print(pool);
@@ -1125,7 +1119,7 @@ int main(int argc, char *argv[])
}
if (cargs.schedule || cargs.poll) {
if (out_queue == ODP_QUEUE_INVALID) {
- app_err("crypto-out queue create failed.\n");
+ ODPH_ERR("crypto-out queue create failed.\n");
exit(EXIT_FAILURE);
}
}
@@ -1185,17 +1179,17 @@ int main(int argc, char *argv[])
if (cargs.schedule || cargs.poll)
odp_queue_destroy(out_queue);
if (odp_pool_destroy(pool)) {
- app_err("Error: pool destroy\n");
+ ODPH_ERR("Error: pool destroy\n");
exit(EXIT_FAILURE);
}
if (odp_term_local()) {
- app_err("Error: term local\n");
+ ODPH_ERR("Error: term local\n");
exit(EXIT_FAILURE);
}
if (odp_term_global(instance)) {
- app_err("Error: term global\n");
+ ODPH_ERR("Error: term global\n");
exit(EXIT_FAILURE);
}
diff --git a/test/performance/odp_ipsec.c b/test/performance/odp_ipsec.c
index 04788995e..ee3e062b7 100644
--- a/test/performance/odp_ipsec.c
+++ b/test/performance/odp_ipsec.c
@@ -19,10 +19,6 @@
#include <odp_api.h>
#include <odp/helper/odph_api.h>
-#define app_err(fmt, ...) \
- fprintf(stderr, "%s:%d:%s(): Error: " fmt, __FILE__, \
- __LINE__, __func__, ##__VA_ARGS__)
-
/** @def POOL_NUM_PKT
* Number of packets in the pool
*/
@@ -567,7 +563,7 @@ create_sa_from_config(ipsec_alg_config_t *config,
if (cargs->schedule || cargs->poll) {
out_queue = odp_queue_lookup("ipsec-out");
if (out_queue == ODP_QUEUE_INVALID) {
- app_err("ipsec-out queue not found\n");
+ ODPH_ERR("ipsec-out queue not found\n");
return ODP_IPSEC_SA_INVALID;
}
param.dest_queue = out_queue;
@@ -598,7 +594,7 @@ make_packet(odp_pool_t pkt_pool, unsigned int payload_length)
pkt = odp_packet_alloc(pkt_pool, payload_length);
if (pkt == ODP_PACKET_INVALID) {
- app_err("failed to allocate buffer\n");
+ ODPH_ERR("failed to allocate buffer\n");
return pkt;
}
@@ -630,7 +626,7 @@ run_measure_one(ipsec_args_t *cargs,
pkt_pool = odp_pool_lookup("packet_pool");
if (pkt_pool == ODP_POOL_INVALID) {
- app_err("pkt_pool not found\n");
+ ODPH_ERR("pkt_pool not found\n");
return -1;
}
@@ -665,8 +661,7 @@ run_measure_one(ipsec_args_t *cargs,
&out_pkt, &num_out,
&param);
if (rc <= 0) {
- app_err("failed odp_ipsec_out: rc = %d\n",
- rc);
+ ODPH_ERR("failed odp_ipsec_out: rc = %d\n", rc);
odp_packet_free(pkt);
break;
}
@@ -674,8 +669,8 @@ run_measure_one(ipsec_args_t *cargs,
odp_ipsec_packet_result_t result;
odp_ipsec_result(&result, out_pkt);
- app_err("Received error packet: %d\n",
- result.status.error.all);
+ ODPH_ERR("Received error packet: %d\n",
+ result.status.error.all);
}
packets_sent += rc;
packets_received += num_out;
@@ -706,13 +701,13 @@ run_measure_one_async(ipsec_args_t *cargs,
pkt_pool = odp_pool_lookup("packet_pool");
if (pkt_pool == ODP_POOL_INVALID) {
- app_err("pkt_pool not found\n");
+ ODPH_ERR("pkt_pool not found\n");
return -1;
}
out_queue = odp_queue_lookup("ipsec-out");
if (out_queue == ODP_QUEUE_INVALID) {
- app_err("ipsec-out queue not found\n");
+ ODPH_ERR("ipsec-out queue not found\n");
return -1;
}
@@ -745,8 +740,8 @@ run_measure_one_async(ipsec_args_t *cargs,
rc = odp_ipsec_out_enq(&pkt, 1,
&param);
if (rc <= 0) {
- app_err("failed odp_crypto_packet_op_enq: rc = %d\n",
- rc);
+ ODPH_ERR("failed odp_crypto_packet_op_enq: rc = %d\n",
+ rc);
odp_packet_free(pkt);
break;
}
@@ -800,12 +795,12 @@ run_measure_one_config(ipsec_args_t *cargs,
int rc = 0;
if (odp_ipsec_capability(&capa) < 0) {
- app_err("IPSEC capability call failed.\n");
+ ODPH_ERR("IPSEC capability call failed.\n");
return -1;
}
if (cargs->ah && (ODP_SUPPORT_NO == capa.proto_ah)) {
- app_err("IPSEC AH protocol not supported.\n");
+ ODPH_ERR("IPSEC AH protocol not supported.\n");
return -1;
}
@@ -821,7 +816,7 @@ run_measure_one_config(ipsec_args_t *cargs,
sa = create_sa_from_config(config, cargs);
if (sa == ODP_IPSEC_SA_INVALID) {
- app_err("IPsec SA create failed.\n");
+ ODPH_ERR("IPsec SA create failed.\n");
return -1;
}
@@ -1041,7 +1036,7 @@ int main(int argc, char *argv[])
/* Let helper collect its own arguments (e.g. --odph_proc) */
argc = odph_parse_options(argc, argv);
if (odph_options(&helper_options)) {
- app_err("Reading ODP helper options failed.\n");
+ ODPH_ERR("Reading ODP helper options failed.\n");
exit(EXIT_FAILURE);
}
@@ -1055,20 +1050,20 @@ int main(int argc, char *argv[])
/* Init ODP before calling anything else */
if (odp_init_global(&instance, &init_param, NULL)) {
- app_err("ODP global init failed.\n");
+ ODPH_ERR("ODP global init failed.\n");
exit(EXIT_FAILURE);
}
/* Init this thread */
if (odp_init_local(instance, ODP_THREAD_WORKER)) {
- app_err("ODP local init failed.\n");
+ ODPH_ERR("ODP local init failed.\n");
exit(EXIT_FAILURE);
}
odp_sys_info_print();
if (odp_pool_capability(&capa)) {
- app_err("Pool capability request failed.\n");
+ ODPH_ERR("Pool capability request failed.\n");
exit(EXIT_FAILURE);
}
@@ -1090,23 +1085,23 @@ int main(int argc, char *argv[])
pool = odp_pool_create("packet_pool", &param);
if (pool == ODP_POOL_INVALID) {
- app_err("packet pool create failed.\n");
+ ODPH_ERR("packet pool create failed.\n");
exit(EXIT_FAILURE);
}
odp_pool_print(pool);
if (odp_ipsec_capability(&ipsec_capa) < 0) {
- app_err("IPSEC capability call failed.\n");
+ ODPH_ERR("IPSEC capability call failed.\n");
exit(EXIT_FAILURE);
}
if (cargs.schedule && !ipsec_capa.queue_type_sched) {
- app_err("Scheduled type destination queue not supported.\n");
+ ODPH_ERR("Scheduled type destination queue not supported.\n");
exit(EXIT_FAILURE);
}
if (cargs.poll && !ipsec_capa.queue_type_plain) {
- app_err("Plain type destination queue not supported.\n");
+ ODPH_ERR("Plain type destination queue not supported.\n");
exit(EXIT_FAILURE);
}
@@ -1129,7 +1124,7 @@ int main(int argc, char *argv[])
}
if (cargs.schedule || cargs.poll) {
if (out_queue == ODP_QUEUE_INVALID) {
- app_err("ipsec-out queue create failed.\n");
+ ODPH_ERR("ipsec-out queue create failed.\n");
exit(EXIT_FAILURE);
}
config.inbound_mode = ODP_IPSEC_OP_MODE_ASYNC;
@@ -1141,7 +1136,7 @@ int main(int argc, char *argv[])
config.inbound.default_queue = ODP_QUEUE_INVALID;
}
if (odp_ipsec_config(&config)) {
- app_err("odp_ipsec_config() failed\n");
+ ODPH_ERR("odp_ipsec_config() failed\n");
exit(EXIT_FAILURE);
}
@@ -1202,17 +1197,17 @@ int main(int argc, char *argv[])
if (cargs.schedule || cargs.poll)
odp_queue_destroy(out_queue);
if (odp_pool_destroy(pool)) {
- app_err("Error: pool destroy\n");
+ ODPH_ERR("Error: pool destroy\n");
exit(EXIT_FAILURE);
}
if (odp_term_local()) {
- app_err("Error: term local\n");
+ ODPH_ERR("Error: term local\n");
exit(EXIT_FAILURE);
}
if (odp_term_global(instance)) {
- app_err("Error: term global\n");
+ ODPH_ERR("Error: term global\n");
exit(EXIT_FAILURE);
}
diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
index 593465f4f..bf635abd9 100644
--- a/test/performance/odp_pktio_perf.c
+++ b/test/performance/odp_pktio_perf.c
@@ -52,12 +52,6 @@
* received by this time will be assumed to have been lost. */
#define SHUTDOWN_DELAY_NS (ODP_TIME_MSEC_IN_NS * 100)
-#define VPRINT(fmt, ...) \
- do { \
- if (gbl_args->args.verbose) \
- printf(fmt, ##__VA_ARGS__); \
- } while (0)
-
#define CACHE_ALIGN_ROUNDUP(x)\
((ODP_CACHE_LINE_SIZE) * \
(((x) + ODP_CACHE_LINE_SIZE - 1) / (ODP_CACHE_LINE_SIZE)))
@@ -369,12 +363,13 @@ static int run_thread_tx(void *arg)
cur_time = odp_time_local();
}
- VPRINT(" %02d: TxPkts %-8" PRIu64 " EnqFail %-6" PRIu64
- " AllocFail %-6" PRIu64 " Idle %" PRIu64 "ms\n",
- thr_id, stats->s.tx_cnt,
- stats->s.enq_failures, stats->s.alloc_failures,
- odp_time_to_ns(stats->s.idle_ticks) /
- (uint64_t)ODP_TIME_MSEC_IN_NS);
+ if (gbl_args->args.verbose)
+ printf(" %02d: TxPkts %-8" PRIu64 " EnqFail %-6" PRIu64
+ " AllocFail %-6" PRIu64 " Idle %" PRIu64 "ms\n",
+ thr_id, stats->s.tx_cnt, stats->s.enq_failures,
+ stats->s.alloc_failures,
+ odp_time_to_ns(stats->s.idle_ticks) /
+ (uint64_t)ODP_TIME_MSEC_IN_NS);
return 0;
}
diff --git a/test/performance/odp_sched_perf.c b/test/performance/odp_sched_perf.c
index f9b4ce548..af3a11c97 100644
--- a/test/performance/odp_sched_perf.c
+++ b/test/performance/odp_sched_perf.c
@@ -40,6 +40,7 @@ typedef struct test_options_t {
uint32_t max_burst;
int queue_type;
int forward;
+ int fairness;
uint32_t queue_size;
uint32_t tot_queue;
uint32_t tot_event;
@@ -88,6 +89,11 @@ typedef struct test_global_t {
} test_global_t;
+typedef struct {
+ odp_queue_t next;
+ odp_atomic_u64_t count;
+} queue_context_t;
+
static void print_usage(void)
{
printf("\n"
@@ -113,6 +119,7 @@ static void print_usage(void)
" -b, --burst Maximum number of events per operation. Default: 100.\n"
" -t, --type Queue type. 0: parallel, 1: atomic, 2: ordered. Default: 0.\n"
" -f, --forward 0: Keep event in the original queue, 1: Forward event to the next queue. Default: 0.\n"
+ " -a, --fairness 0: Don't count events per queue, 1: Count and report events relative to average. Default: 0.\n"
" -w, --wait_ns Number of nsec to wait before enqueueing events. Default: 0.\n"
" -k, --ctx_rd_words Number of queue context words (uint64_t) to read on every event. Default: 0.\n"
" -l, --ctx_rw_words Number of queue context words (uint64_t) to modify on every event. Default: 0.\n"
@@ -142,6 +149,7 @@ static int parse_options(int argc, char *argv[], test_options_t *test_options)
{"burst", required_argument, NULL, 'b'},
{"type", required_argument, NULL, 't'},
{"forward", required_argument, NULL, 'f'},
+ {"fairness", required_argument, NULL, 'a'},
{"wait_ns", required_argument, NULL, 'w'},
{"ctx_rd_words", required_argument, NULL, 'k'},
{"ctx_rw_words", required_argument, NULL, 'l'},
@@ -152,7 +160,7 @@ static int parse_options(int argc, char *argv[], test_options_t *test_options)
{NULL, 0, NULL, 0}
};
- static const char *shortopts = "+c:q:L:H:d:e:s:g:j:b:t:f:w:k:l:n:m:vh";
+ static const char *shortopts = "+c:q:L:H:d:e:s:g:j:b:t:f:a:w:k:l:n:m:vh";
test_options->num_cpu = 1;
test_options->num_queue = 1;
@@ -166,6 +174,7 @@ static int parse_options(int argc, char *argv[], test_options_t *test_options)
test_options->max_burst = 100;
test_options->queue_type = 0;
test_options->forward = 0;
+ test_options->fairness = 0;
test_options->ctx_rd_words = 0;
test_options->ctx_rw_words = 0;
test_options->rd_words = 0;
@@ -216,6 +225,9 @@ static int parse_options(int argc, char *argv[], test_options_t *test_options)
case 'f':
test_options->forward = atoi(optarg);
break;
+ case 'a':
+ test_options->fairness = atoi(optarg);
+ break;
case 'k':
test_options->ctx_rd_words = atoi(optarg);
break;
@@ -290,9 +302,11 @@ static int parse_options(int argc, char *argv[], test_options_t *test_options)
/* When forwarding, all events may end up into
* a single queue */
test_options->queue_size = test_options->tot_event;
- ctx_size = sizeof(odp_queue_t);
}
+ if (test_options->forward || test_options->fairness)
+ ctx_size = sizeof(queue_context_t);
+
if (test_options->ctx_rd_words || test_options->ctx_rw_words) {
/* Round up queue handle size to a multiple of 8 for correct
* context data alignment */
@@ -303,7 +317,7 @@ static int parse_options(int argc, char *argv[], test_options_t *test_options)
/* When context data is modified, round up to cache line size to avoid
* false sharing */
- if (test_options->ctx_rw_words)
+ if (test_options->fairness || test_options->ctx_rw_words)
ctx_size = ROUNDUP(ctx_size, ODP_CACHE_LINE_SIZE);
test_options->ctx_size = ctx_size;
@@ -624,17 +638,24 @@ static int create_queues(test_global_t *global)
queue = global->queue[i];
if (ctx_size) {
+ /*
+ * Cast increases alignment, but it's ok, since ctx and
+ * ctx_size are both cache line aligned.
+ */
+ queue_context_t *qc = (queue_context_t *)(uintptr_t)ctx;
+
if (test_options->forward) {
- odp_queue_t *next_queue;
uint32_t next = i + 1;
if (next == tot_queue)
next = first;
- next_queue = (odp_queue_t *)(uintptr_t)ctx;
- *next_queue = global->queue[next];
+ qc->next = global->queue[next];
}
+ if (test_options->fairness)
+ odp_atomic_init_u64(&qc->count, 0);
+
if (odp_queue_context_set(queue, ctx, ctx_size)) {
printf("Error: Context set failed %u\n", i);
return -1;
@@ -699,6 +720,45 @@ static int join_all_groups(test_global_t *global, int thr)
return 0;
}
+static void print_queue_fairness(test_global_t *global)
+{
+ uint32_t i;
+ queue_context_t *ctx;
+ test_options_t *test_options = &global->test_options;
+ uint32_t first = test_options->num_dummy;
+ uint32_t num_queue = test_options->num_queue;
+ uint32_t tot_queue = test_options->tot_queue;
+ uint64_t total = 0;
+ double average;
+
+ if (!test_options->fairness)
+ return;
+
+ for (i = first; i < tot_queue; i++) {
+ ctx = odp_queue_context(global->queue[i]);
+ total += odp_atomic_load_u64(&ctx->count);
+ }
+
+ average = (double)total / (double)num_queue;
+
+ printf("\n");
+ printf("RESULTS - events per queue (percent of average):\n");
+ printf("------------------------------------------------\n");
+ printf(" 1 2 3 4 5 6 7 8 9 10");
+
+ for (i = first; i < tot_queue; i++) {
+ ctx = odp_queue_context(global->queue[i]);
+
+ if ((i % 10) == 0)
+ printf("\n ");
+
+ printf("%6.1f ", (double)odp_atomic_load_u64(&ctx->count) /
+ average * 100.0);
+ }
+
+ printf("\n");
+}
+
static int destroy_queues(test_global_t *global)
{
uint32_t i;
@@ -802,7 +862,6 @@ static int test_sched(void *arg)
uint64_t events, enqueues, waits, events_prev;
odp_time_t t1, t2, last_retry_ts;
odp_queue_t queue;
- odp_queue_t *next;
thread_arg_t *thread_arg = arg;
test_global_t *global = thread_arg->global;
test_options_t *test_options = &global->test_options;
@@ -810,6 +869,7 @@ static int test_sched(void *arg)
uint32_t max_burst = test_options->max_burst;
int num_group = test_options->num_group;
int forward = test_options->forward;
+ int fairness = test_options->fairness;
int touch_data = test_options->touch_data;
uint32_t rd_words = test_options->rd_words;
uint32_t rw_words = test_options->rw_words;
@@ -826,8 +886,8 @@ static int test_sched(void *arg)
thr = odp_thread_id();
- if (forward)
- ctx_offset = ROUNDUP(sizeof(odp_queue_t), 8);
+ if (forward || fairness)
+ ctx_offset = ROUNDUP(sizeof(queue_context_t), 8);
if (num_group > 0) {
uint32_t num_join = test_options->num_join;
@@ -885,12 +945,13 @@ static int test_sched(void *arg)
i = 0;
if (odp_unlikely(ctx_size)) {
- void *ctx = odp_queue_context(queue);
+ queue_context_t *ctx = odp_queue_context(queue);
- if (forward) {
- next = ctx;
- queue = *next;
- }
+ if (forward)
+ queue = ctx->next;
+
+ if (fairness)
+ odp_atomic_add_u64(&ctx->count, num);
if (odp_unlikely(touch_ctx))
ctx_sum += rw_ctx_data(ctx, ctx_offset,
@@ -999,10 +1060,8 @@ static int test_sched(void *arg)
if (ev[0] == ODP_EVENT_INVALID)
break;
- if (odp_unlikely(forward)) {
- next = odp_queue_context(queue);
- queue = *next;
- }
+ if (odp_unlikely(forward))
+ queue = ((queue_context_t *)odp_queue_context(queue))->next;
if (odp_queue_enq(queue, ev[0])) {
printf("Error: Queue enqueue failed\n");
@@ -1276,6 +1335,8 @@ int main(int argc, char **argv)
/* Wait workers to exit */
odph_thread_join(global->thread_tbl, global->test_options.num_cpu);
+ print_queue_fairness(global);
+
if (destroy_queues(global))
return -1;